/
kochkatech
/
Queue
Обзор
Документация
Войти
/
kochkatech
/
Queue
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
dev
src/Queue.Admin/ViewModels/ServicesViewModel.cs
196 строк
6 KB
kochkareal
refactor: применить общие стили и добавить поиск/фильтры в панели администратора
27 июл 2026, 18:37
27 июл 2026, 18:37
cd6a08b
Код
Авторство
О чём код?
using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows.Data; using System.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.EntityFrameworkCore; using Queue.Core.Models; using Queue.Data; namespace Queue.Admin.ViewModels; public partial class ServicesViewModel : ObservableObject { private readonly QueueDbContextFactory _dbContextFactory; public ObservableCollection<Service> Services { get; } = new(); // См. TicketsViewModel.TicketsView — тот же приём: DataGrid привязан к представлению, // а не к Services напрямую, чтобы SearchText фильтровал без отдельной копии списка. public ICollectionView ServicesView { get; } public ObservableCollection<WindowSelectionItem> AvailableWindows { get; } = new(); [ObservableProperty] private string searchText = string.Empty; [ObservableProperty] private string newServiceName = string.Empty; [ObservableProperty] private string newServiceCode = string.Empty; [ObservableProperty] private int newServiceDurationMinutes = 5; [ObservableProperty] private Service? selectedService; public ServicesViewModel(QueueDbContextFactory dbContextFactory) { _dbContextFactory = dbContextFactory; ServicesView = CollectionViewSource.GetDefaultView(Services); ServicesView.Filter = FilterService; _ = LoadAsync(); } partial void OnSearchTextChanged(string value) => ServicesView.Refresh(); private bool FilterService(object obj) { if (string.IsNullOrWhiteSpace(SearchText)) { return true; } var service = (Service)obj; var text = SearchText.Trim(); return service.Name.Contains(text, StringComparison.OrdinalIgnoreCase) || service.Code.Contains(text, StringComparison.OrdinalIgnoreCase); } [RelayCommand] private async Task LoadAsync() { using var db = _dbContextFactory.CreateDbContext(); var items = await db.Services.Include(s => s.Windows).OrderBy(s => s.SortOrder).ToListAsync(); Services.Clear(); foreach (var item in items) { Services.Add(item); } } [RelayCommand] private async Task AddAsync() { if (string.IsNullOrWhiteSpace(NewServiceName) || string.IsNullOrWhiteSpace(NewServiceCode)) { return; } var service = new Service { Name = NewServiceName.Trim(), Code = NewServiceCode.Trim(), AverageDurationMinutes = NewServiceDurationMinutes, IsActive = true, SortOrder = Services.Count }; using (var db = _dbContextFactory.CreateDbContext()) { db.Services.Add(service); await db.SaveChangesAsync(); } Services.Add(service); NewServiceName = string.Empty; NewServiceCode = string.Empty; NewServiceDurationMinutes = 5; } // Сохраняет изменения полей строки (название, код, время, активность) после редактирования в гриде. [RelayCommand] private async Task UpdateAsync(Service? service) { if (service is null) { return; } using var db = _dbContextFactory.CreateDbContext(); db.Attach(service); db.Entry(service).Property(s => s.Name).IsModified = true; db.Entry(service).Property(s => s.Code).IsModified = true; db.Entry(service).Property(s => s.AverageDurationMinutes).IsModified = true; db.Entry(service).Property(s => s.IsActive).IsModified = true; db.Entry(service).Property(s => s.SortOrder).IsModified = true; await db.SaveChangesAsync(); } [RelayCommand] private async Task DeleteAsync(Service? service) { if (service is null) { return; } using (var db = _dbContextFactory.CreateDbContext()) { db.Services.Attach(service); db.Services.Remove(service); await db.SaveChangesAsync(); } Services.Remove(service); } // Список окон для панели справа пересобирается при выборе услуги в гриде. partial void OnSelectedServiceChanged(Service? value) { _ = LoadAvailableWindowsAsync(value); } private async Task LoadAvailableWindowsAsync(Service? service) { AvailableWindows.Clear(); using var db = _dbContextFactory.CreateDbContext(); var windows = await db.Windows.OrderBy(w => w.Name).ToListAsync(); var selectedIds = service?.Windows.Select(w => w.Id).ToHashSet() ?? new System.Collections.Generic.HashSet<int>(); foreach (var window in windows) { AvailableWindows.Add(new WindowSelectionItem(window) { IsSelected = selectedIds.Contains(window.Id) }); } } [RelayCommand] private async Task SaveWindowAssignmentsAsync() { if (SelectedService is null) { return; } using var db = _dbContextFactory.CreateDbContext(); var service = await db.Services.Include(s => s.Windows).FirstOrDefaultAsync(s => s.Id == SelectedService.Id); if (service is null) { return; } service.Windows.Clear(); foreach (var item in AvailableWindows.Where(w => w.IsSelected)) { var window = await db.Windows.FindAsync(item.Window.Id); if (window is not null) { service.Windows.Add(window); } } await db.SaveChangesAsync(); SelectedService.Windows = service.Windows.ToList(); } }