using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Platform.Storage; using LehrerApp.Core.Importing; using LehrerApp.Core.Interfaces; using LehrerApp.Core.Models; using LehrerApp.Core.Services; using LehrerApp.Desktop.ViewModels.Groups; using LehrerApp.Desktop.ViewModels.Students; using LehrerApp.Desktop.Services; using LehrerApp.Desktop.Views.Shared; using LehrerApp.Desktop.Views.Students; using Microsoft.Extensions.DependencyInjection; namespace LehrerApp.Desktop.Views.Groups; public partial class GroupDetailView : UserControl { private const int MaximumImportFileSize = 20 * 1024 * 1024; public GroupDetailView() => InitializeComponent(); protected override void OnDataContextChanged(EventArgs e) { base.OnDataContextChanged(e); if (DataContext is GroupDetailViewModel vm) { vm.OnAddStudent = ShowAddStudentDialog; vm.OnWithdrawStudent = ShowWithdrawStudentDialog; vm.OnAddExam = ShowAddExamDialog; vm.OnEditExam = ShowEditExamDialog; vm.OnDuplicateExam = ShowDuplicateExamDialog; vm.OnConfirmDeleteExam = ShowDeleteExamDialog; vm.OnGradeExam = ShowGradeExamDialog; vm.OnEvaluateExam = ShowEvaluateExamDialog; vm.OnConfirmReactivate = ShowReactivateConfirmDialog; } } private async Task ShowReactivateConfirmDialog() { var dialog = new ConfirmDialog { DataContext = new ConfirmDialogInfo { Title = "Archivierte Gruppe wieder aktivieren?", Message = "Nach der Wiederaktivierung können historische Daten dieser Gruppe wieder verändert werden.", ConfirmText = "Wieder aktivieren", }, }; var owner = TopLevel.GetTopLevel(this) as Window; return owner is not null && await dialog.ShowDialog(owner); } private async Task ShowAddStudentDialog() { if (DataContext is not GroupDetailViewModel vm || vm.Group is null) return false; var dialogVm = new AddStudentToGroupDialogViewModel( App.Services.GetRequiredService(), App.Services.GetRequiredService(), vm.Group.Id); var dialog = new AddStudentToGroupDialog { DataContext = dialogVm }; var owner = TopLevel.GetTopLevel(this) as Window; if (owner is null) return false; return await dialog.ShowDialog(owner); } private async void OnImportParticipantsClick(object? sender, RoutedEventArgs e) { var owner = TopLevel.GetTopLevel(this) as Window; if (owner is null || DataContext is not GroupDetailViewModel vm || vm.Group is null) return; var service = App.Services.GetRequiredService(); var patterns = service.SupportedExtensions.Select(extension => $"*{extension}").ToArray(); var files = await owner.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions { Title = $"Teilnehmer für {vm.Group.Name} importieren", AllowMultiple = false, FileTypeFilter = [ new FilePickerFileType("Unterstützte Schülerlisten") { Patterns = patterns.Length > 0 ? patterns : ["*.csv"], }, ], }); if (files.Count == 0) return; try { await using var source = await files[0].OpenReadAsync(); if (source.CanSeek && source.Length > MaximumImportFileSize) throw new InvalidDataException("Die Importdatei ist größer als 20 MB."); using var buffer = new MemoryStream(); await source.CopyToAsync(buffer); if (buffer.Length > MaximumImportFileSize) throw new InvalidDataException("Die Importdatei ist größer als 20 MB."); var importFile = new ImportFile(files[0].Name, buffer.ToArray()); var preview = await Task.Run(async () => await service.AnalyzeAsync(importFile, vm.Group.Id).ConfigureAwait(false)); var dialogVm = new StudentImportDialogViewModel(service, preview, files[0].Name); var dialog = new StudentImportDialog { DataContext = dialogVm }; if (!await dialog.ShowDialog(owner)) return; vm.LoadStudents(); vm.ParticipationTab.RefreshCurrentGrid(); var result = dialogVm.Result!; App.Services.GetRequiredService().ShowSuccess( $"Teilnehmerimport abgeschlossen: {result.CreatedStudents} neu, " + $"{result.UpdatedStudents} ergänzt, {result.CreatedMemberships} zugeordnet."); } catch (Exception ex) when (ex is ImportFormatException or InvalidDataException or IOException or UnauthorizedAccessException) { App.Services.GetRequiredService().ShowError(ex.Message); } } private async Task ShowWithdrawStudentDialog(StudentSummary student) { if (DataContext is not GroupDetailViewModel vm || vm.Group is null) return false; var memberships = App.Services.GetRequiredService(); var membership = memberships.GetByStudentAndGroup(student.Id, vm.Group.Id); if (membership is null) return false; var dialogVm = new WithdrawStudentDialogViewModel( memberships, membership, student.FullName, vm.Group.Name); var dialog = new WithdrawStudentDialog { DataContext = dialogVm }; var owner = TopLevel.GetTopLevel(this) as Window; return owner is not null && await dialog.ShowDialog(owner); } private Task ShowAddExamDialog(Guid groupId) => ShowExamDialog(groupId, editingExam: null, duplicateSource: null); private Task ShowEditExamDialog(Exam exam) => ShowExamDialog(exam.GroupId, editingExam: exam, duplicateSource: null); private Task ShowDuplicateExamDialog(Exam exam) => ShowExamDialog(exam.GroupId, editingExam: null, duplicateSource: exam); private async Task ShowExamDialog(Guid groupId, Exam? editingExam, Exam? duplicateSource) { if (DataContext is not GroupDetailViewModel vm || vm.Group is null) return false; var dialogVm = new ExamDialogViewModel( App.Services.GetRequiredService(), App.Services.GetRequiredService(), App.Services.GetRequiredService(), App.Services.GetRequiredService(), groupId, vm.Group.SubjectId, vm.Group.GradeLevel, vm.Group.GradingSystem, vm.SubjectName, vm.Group.IsDifferentiated, editingExam, duplicateSource); var dialog = new ExamDialog { DataContext = dialogVm }; var owner = TopLevel.GetTopLevel(this) as Window; if (owner is null) return false; return await dialog.ShowDialog(owner); } private async Task ShowDeleteExamDialog(ExamSummary exam) { var dialog = new DeleteExamDialog { DataContext = exam.Title }; var owner = TopLevel.GetTopLevel(this) as Window; return owner is not null && await dialog.ShowDialog(owner); } private async Task ShowGradeExamDialog(Exam exam) { if (DataContext is not GroupDetailViewModel vm || vm.Group is null) return; var dialogVm = new ExamGradingDialogViewModel( App.Services.GetRequiredService(), App.Services.GetRequiredService(), App.Services.GetRequiredService(), App.Services.GetRequiredService(), exam, vm.Group.Id); var dialog = new ExamGradingDialog { DataContext = dialogVm }; var owner = TopLevel.GetTopLevel(this) as Window; if (owner is not null) await dialog.ShowDialog(owner); } private async Task ShowEvaluateExamDialog(Exam exam) { if (DataContext is not GroupDetailViewModel vm || vm.Group is null) return; var dialogVm = new ExamEvaluationDialogViewModel( App.Services.GetRequiredService(), App.Services.GetRequiredService(), App.Services.GetRequiredService(), exam, vm.Group.GradingSystem); var dialog = new ExamEvaluationDialog { DataContext = dialogVm }; var owner = TopLevel.GetTopLevel(this) as Window; if (owner is not null) await dialog.ShowDialog(owner); } }