using CommunityToolkit.Mvvm.ComponentModel; using System.Windows.Input; namespace LehrerApp.Desktop.ViewModels; /// Die sieben Dashboard-Kacheln, die tatsächlich "wo muss ich reagieren" beantworten /// (siehe ), zusammengefasst zu einer Karte mit /// Filter-Chips statt sieben eigenen Sichtbarkeits-Schaltern. Reihenfolge hier ist die Reihenfolge /// der Gruppen in der zusammengefassten Ansicht (siehe DashboardViewModel.RebuildAttention) — sie /// übernimmt bewusst die frühere Sortierung aus DashboardSettingsService.DefaultCardOrder, damit /// sich nichts, was Nutzer bereits kennen, unvorhersehbar umsortiert. /// "Klausurwochen" (examload) bleibt bewusst außen vor: die Einträge dort sind Wochen-Aggregate, /// keine Einzelvorgänge, die sich abhaken oder anklicken lassen — sie passen nicht ins Item-Modell. public enum AttentionKind { MissingTeachingTime, Excuse, Correction, Unplanned, Alert, Attendance, SupportPlan } /// Eine Inline-Aktion auf einem Handlungsbedarf-Eintrag (z.B. "Entschuldigt"/"Unentschuldigt", /// "Erfassen"). Verwendet ICommand statt Action, damit die bereits vorhandenen generierten /// RelayCommands (OpenExcuseItem.MarkExcusedCommand, DashboardViewModel.AddMissingTeachingTimeCommand) /// direkt weiterverwendet werden können, statt sie in einen zweiten Delegate-Typ zu verpacken. public sealed record AttentionAction(string Label, ICommand Command, object? Parameter = null); /// Gemeinsame Projektion für die sieben Handlungsbedarf-Arten. Trägt nur Anzeigedaten — /// die eigentliche Beschaffung bleibt unverändert in den jeweiligen DashboardViewModel.LoadXxx- /// Methoden; sie erzeugen am Ende ein AttentionItem statt (wie vorher) ihre eigene Item-Klasse in /// ihre eigene ObservableCollection einzutragen. public sealed class AttentionItem { public AttentionKind Kind { get; } public string Title { get; } public string Subtitle { get; } /// Kurztext rechts neben dem Titel — Fehlzeitenquote, Alert-Kind-Label. Meist leer. public string TrailingText { get; } public string DateDisplay { get; } public bool IsOverdue { get; } public AlertSeverity? Severity { get; } /// Nur bei Korrekturen gesetzt (0–100); steuert die ProgressBar. Eigenes HasProgress statt /// Nullability, damit die ProgressBar-Bindung ein einfaches int (kompatibel mit Value:double) bleibt. public int ProgressPercent { get; } public bool HasProgress { get; } /// Text unter der ProgressBar, z.B. "3 von 5 Arbeiten bewertet". Nur bei Korrekturen gesetzt. public string ProgressLabel { get; } /// Färbt TrailingText wie die frühere Fehlzeiten-Warnung (fest "Foreground=Red") ein — /// nur bei Attendance gesetzt, weil ein AttentionItem dieser Art per Konstruktion nur entsteht, /// wenn die Fehlzeitenquote den Schwellenwert bereits überschreitet. public bool IsWarningTrailing { get; } public IReadOnlyList Actions { get; } public Action? Navigate { get; } public AttentionItem(AttentionKind kind, string title, string subtitle = "", string trailingText = "", string dateDisplay = "", bool isOverdue = false, AlertSeverity? severity = null, int progressPercent = 0, string progressLabel = "", bool hasProgress = false, bool isWarningTrailing = false, IReadOnlyList? actions = null, Action? navigate = null) { Kind = kind; Title = title; Subtitle = subtitle; TrailingText = trailingText; DateDisplay = dateDisplay; IsOverdue = isOverdue; Severity = severity; ProgressPercent = progressPercent; ProgressLabel = progressLabel; HasProgress = hasProgress; IsWarningTrailing = isWarningTrailing; Actions = actions ?? []; Navigate = navigate; } public bool HasSubtitle => !string.IsNullOrWhiteSpace(Subtitle); public bool HasTrailingText => !string.IsNullOrWhiteSpace(TrailingText); public bool HasDate => !string.IsNullOrWhiteSpace(DateDisplay); public bool HasActions => Actions.Count > 0; public bool HasSeverity => Severity is not null; public bool IsHighSeverity => Severity == AlertSeverity.High; public bool IsMediumSeverity => Severity == AlertSeverity.Medium; } /// Eine Kind-Gruppe innerhalb der zusammengefassten Handlungsbedarf-Liste. Items behalten /// die Sortierung, die ihre jeweilige LoadXxx-Methode schon immer produziert hat (z.B. Fehlzeiten /// nach Quote absteigend, Korrekturen nach Datum) — ein zweites, generisches "Importance"-Sortieren /// quer über alle Arten würde diese bewusst gewählten Reihenfolgen wieder zerstören. public sealed class AttentionGroup(AttentionKind kind, string header, IReadOnlyList items) { public AttentionKind Kind { get; } = kind; public string Header { get; } = header; public IReadOnlyList Items { get; } = items; public int Count => Items.Count; } /// Ein Filter-Chip für eine Handlungsbedarf-Art in der zusammengefassten Karte — ersetzt /// die frühere Sichtbarkeit je Einzelkachel (siehe DashboardViewModel.LoadAttentionFilters). public partial class AttentionFilterOption : ObservableObject { [ObservableProperty] private bool _isActive = true; public AttentionKind Kind { get; } public string Label { get; } public Action? OnChanged { get; set; } public AttentionFilterOption(AttentionKind kind, string label) { Kind = kind; Label = label; } partial void OnIsActiveChanged(bool value) => OnChanged?.Invoke(); }