using Presence.Desktop.Models; using ReactiveUI; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Reactive; using System.Reactive.Linq; using System.Threading.Tasks; using Avalonia.Controls; using System.IO; using presence_client.ApiClients.Interfaces; using Demo.Domain.Models; using Microsoft.Extensions.DependencyInjection; using Presence.Desktop.DI; namespace Presence.Desktop.ViewModels { public class GroupViewModel : ViewModelBase, IRoutableViewModel { private readonly IGroupApiClient _groupApiClient; private readonly IUserApiClient _userApiClient; private readonly List _groupPresentersDataSource = new(); private ObservableCollection _groups; private ObservableCollection _users; private string? _newFIO; private GroupPresenter? _selectedGroupItem; private UserPresenter? _selectedUser; private string? _selectedSecondItem; public ObservableCollection Groups => _groups; public ObservableCollection Users => _users; public ObservableCollection SecondComboBoxItems { get; } = new ObservableCollection { "no sort", "name sort", "name sort rev" }; public GroupPresenter? SelectedGroupItem { get => _selectedGroupItem; set => this.RaiseAndSetIfChanged(ref _selectedGroupItem, value); } public UserPresenter? SelectedUser { get => _selectedUser; set => this.RaiseAndSetIfChanged(ref _selectedUser, value); } public string? SelectedSecondItem { get => _selectedSecondItem; set => this.RaiseAndSetIfChanged(ref _selectedSecondItem, value); } public string? NewFIO { get => _newFIO; set => this.RaiseAndSetIfChanged(ref _newFIO, value); } public ReactiveCommand DeleteUsersByGroupCommand { get; } public ReactiveCommand ImportStudentsCommand { get; } public ReactiveCommand DeleteUserCommand { get; } public ReactiveCommand UpdateUserFIOCommand { get; } public ReactiveCommand GoBackCommand { get; } public GroupViewModel(IGroupApiClient groupApiClient, IUserApiClient userApiClient, IScreen hostScreen) { _groupApiClient = groupApiClient; _userApiClient = userApiClient; _groups = new ObservableCollection(); _users = new ObservableCollection(); DeleteUsersByGroupCommand = ReactiveCommand.CreateFromTask(DeleteUsersByGroupAsync); ImportStudentsCommand = ReactiveCommand.CreateFromTask(ImportStudentsAsync); DeleteUserCommand = ReactiveCommand.CreateFromTask(DeleteUserAsync); UpdateUserFIOCommand = ReactiveCommand.CreateFromTask(UpdateUserFIOAsync); HostScreen = hostScreen; GoBackCommand = ReactiveCommand.Create(() => { HostScreen.Router.Navigate.Execute(new StartViewModel(HostScreen)); }); SelectedSecondItem = SecondComboBoxItems.First(); this.WhenAnyValue(vm => vm.SelectedGroupItem) .WhereNotNull() .Subscribe(_ => SetUsers()); this.WhenAnyValue(vm => vm.SelectedSecondItem) .WhereNotNull() .Subscribe(_ => SetUsers()); LoadDataAsync().ConfigureAwait(false); } private async Task LoadDataAsync() { await RefreshGroupsAsync(); } private async Task RefreshGroupsAsync() { var groupsFromApi = await _groupApiClient.GetGroupsWithUsersAsync(); _groupPresentersDataSource.Clear(); foreach (var group in groupsFromApi) { var groupPresenter = new GroupPresenter { Id = group.ID, Name = group.Name, users = group.Users?.Select(user => new UserPresenter { Name = user.FIO, Guid = user.Guid, Group = new GroupPresenter { Id = group.ID, Name = group.Name } }).ToList() ?? new List() }; _groupPresentersDataSource.Add(groupPresenter); } _groups = new ObservableCollection(_groupPresentersDataSource); this.RaisePropertyChanged(nameof(Groups)); if (_groups.Any()) { SelectedGroupItem = _groups.First(); } } private void SetUsers() { Users.Clear(); if (SelectedGroupItem == null) { this.RaisePropertyChanged(nameof(Users)); return; } var group = _groupPresentersDataSource.FirstOrDefault(it => it.Id == SelectedGroupItem.Id); if (group?.users == null) { this.RaisePropertyChanged(nameof(Users)); return; } var sortedUsers = SelectedSecondItem switch { "name sort" => group.users.OrderBy(user => user.Name), "name sort rev" => group.users.OrderByDescending(user => user.Name), _ => group.users }; foreach (var user in sortedUsers) { Users.Add(user); } this.RaisePropertyChanged(nameof(Users)); } private async Task ImportStudentsAsync() { if (SelectedGroupItem == null || SelectedGroupItem.Id == null) return; var openFileDialog = new OpenFileDialog { Filters = new List { new() { Name = "CSV Files", Extensions = { "csv" } } }, AllowMultiple = false }; var result = await openFileDialog.ShowAsync(new Window()); if (result?.Length > 0) { var filePath = result[0]; var lines = File.ReadAllLines(filePath); var createdUsers = new List(); foreach (var line in lines.Skip(1)) { var columns = line.Split(';'); if (columns.Length < 2) continue; var fio = columns[0]; var groupName = columns[1]; var newUser = new ImportStudents { fio = fio, groupName = groupName }; createdUsers.Add(newUser); } foreach (var user in createdUsers) { var success = await _userApiClient.CreateUser(user.fio, user.groupName); if (!success) { return; } } await RefreshGroupsAsync(); } } private async Task DeleteUsersByGroupAsync() { if (SelectedGroupItem == null) return; var groupId = SelectedGroupItem.Id; var success = await _userApiClient.DeleteUsersByGroupIdAsync(groupId); if (success) { await RefreshGroupsAsync(); } } private async Task DeleteUserAsync(UserPresenter user) { if (user == null) return; var success = await _userApiClient.DeleteUserAsync(user.Guid); if (success) { await RefreshGroupsAsync(); } } private async Task UpdateUserFIOAsync(UserPresenter user) { if (user == null || string.IsNullOrWhiteSpace(NewFIO)) { return; } var success = await _userApiClient.UpdateUserFioAsync(user.Guid, NewFIO); if (success) { user.Name = NewFIO; NewFIO = string.Empty; this.RaisePropertyChanged(nameof(Users)); await RefreshGroupsAsync(); } } public string? UrlPathSegment { get; } public IScreen HostScreen { get; } } }