using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using LehrerApp.Core.Interfaces; using LehrerApp.Core.Models; using System.Collections.ObjectModel; namespace LehrerApp.Desktop.ViewModels.Settings; /// /// Papierkorb (14.3): zeigt gelöschte Datensätze der abgedeckten Modelle (siehe /// TODO.md 14.3 für die vollständige Liste und die bewusst ausgeschlossenen, kaskadierenden /// Löschvorgänge wie eine ganze Lerngruppe) und erlaubt das Wiederherstellen. Rein lokal — der /// Papierkorb selbst wird nicht synchronisiert (siehe TrashRepository-Klassenkommentar); /// wiederhergestellte Einträge synchronisieren sich danach ganz normal wie jede andere Änderung. /// public partial class TrashViewModel : ObservableObject { private readonly ITrashRepository _trash; private readonly IGradeRepository _grades; private readonly IWorkTaskRepository _tasks; private readonly ITimeEntryRepository _timeEntries; private readonly ISeatingPlanRepository _seatingPlans; private readonly IGradingKeyTemplateRepository _gradingKeyTemplates; [ObservableProperty] private string _status = ""; public ObservableCollection Items { get; } = []; public bool HasItems => Items.Count > 0; public TrashViewModel(ITrashRepository trash, IGradeRepository grades, IWorkTaskRepository tasks, ITimeEntryRepository timeEntries, ISeatingPlanRepository seatingPlans, IGradingKeyTemplateRepository gradingKeyTemplates) { _trash = trash; _grades = grades; _tasks = tasks; _timeEntries = timeEntries; _seatingPlans = seatingPlans; _gradingKeyTemplates = gradingKeyTemplates; Load(); } public void Load() { Items.Clear(); foreach (var item in _trash.GetAll()) Items.Add(new TrashItemViewModel(item, TypeLabel(item.EntityType))); OnPropertyChanged(nameof(HasItems)); } [RelayCommand] private void Restore(TrashItemViewModel? item) { if (item is null) return; switch (item.EntityType) { case nameof(Grade): _grades.Restore(item.Id); break; case nameof(WorkTask): _tasks.Restore(item.Id); break; case nameof(TimeEntry): _timeEntries.Restore(item.Id); break; case nameof(SeatingPlan): _seatingPlans.Restore(item.Id); break; case nameof(GradingKeyTemplate): _gradingKeyTemplates.Restore(item.Id); break; default: return; // Unbekannter Typ (sollte nicht vorkommen) - Eintrag unverändert lassen. } Status = $"„{item.Summary}“ wiederhergestellt."; Load(); } private static string TypeLabel(string entityType) => entityType switch { nameof(Grade) => "Note", nameof(WorkTask) => "Aufgabe", nameof(TimeEntry) => "Zeiteintrag", nameof(SeatingPlan) => "Sitzplan", nameof(GradingKeyTemplate) => "Notenschlüssel-Vorlage", _ => entityType, }; } public class TrashItemViewModel { private const int RetentionDays = 30; public Guid Id { get; } public string EntityType { get; } public string TypeLabel { get; } public string Summary { get; } public string DeletedAtDisplay { get; } public string ExpiresInDisplay { get; } public TrashItemViewModel(TrashedItem item, string typeLabel) { Id = item.Id; EntityType = item.EntityType; TypeLabel = typeLabel; Summary = item.Summary; DeletedAtDisplay = item.DeletedAt.ToLocalTime().ToString("dd.MM.yyyy HH:mm"); var daysLeft = RetentionDays - (DateTime.UtcNow - item.DeletedAt).Days; ExpiresInDisplay = daysLeft <= 0 ? "läuft heute ab" : $"noch {daysLeft} Tag(e)"; } }