fix: Namensabgleich und Tab-Wechsel im Klassenlehrer-Bereich, Fehltag-Hervorhebung

Zwei Bugs behoben:
- Gefilterte Listen blieben nach Klick auf eine Roster-Zeile leer: WebUntis
  liefert Schülernamen je nach Bericht in unterschiedlicher Reihenfolge
  (Schülerreport "Vorname Nachname", Fehlzeiten-/Klassenbuchberichte
  "Nachname Vorname"). Neuer reihenfolge-unabhängiger Namensvergleich
  (UntisNameMatching), betraf auch den Roster-Namensabgleich der Übersicht
  selbst (Ampel-Symbole/Badges waren ohne ExternKey vermutlich fast immer
  falsch).
- Nach dem ersten Tab-Wechsel (Klick auf Roster-Zeile) blieb ein zweiter
  Klick wirkungslos, sobald man zwischendurch manuell zur Übersicht
  zurückgeklickt hatte: TabbedPage.SelectedIndex war ohne Mode=TwoWay
  gebunden. Explizit ergänzt.

Zusätzlich: Fehlzeiten-Zeilen für einen kompletten Fehltag werden jetzt
dezent hervorgehoben (Nutzer-Feedback, bisher nicht erkennbar).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 23:27:14 +02:00
co-authored by Claude Sonnet 5
parent 2b29dea824
commit 69cc16bbd2
8 changed files with 131 additions and 29 deletions
@@ -29,6 +29,10 @@ public sealed record ClassAbsenceDaySummaryRow(DateOnly Date, string StudentName
public string PeriodsLabel => string.Join(", ", PeriodNumbers.Order());
public string StatusLabel => string.Join(", ", Statuses);
public string ReasonLabel => string.Join("; ", AbsenceReasons);
/// Nutzer-Feedback: ein ganzer Fehltag ist in der Liste sonst nicht auf einen Blick erkennbar -
/// dezente Hervorhebung statt einer weiteren Text-/Icon-Spalte.
public string RowBackground => CountsAsFullDay ? "#1FFFA000" : "Transparent";
public string? FullDayTooltip => CountsAsFullDay ? "Ganzer Fehltag" : null;
public static IReadOnlyList<ClassAbsenceDaySummaryRow> GroupByStudentAndDay(
IEnumerable<UntisClassAbsenceEntryDto> entries) => entries
@@ -138,13 +142,14 @@ public partial class ClassTeacherDetailsViewModel : ObservableObject
finally { Busy = false; }
}
// WebUntis liefert Namen je nach Bericht in anderer Reihenfolge als der Schülerreport, aus dem
// StudentFilter beim Klick in der Übersicht gesetzt wird (siehe UntisNameMatching) - ein
// exakter String-Vergleich hier ließ die gefilterten Listen fälschlich leer erscheinen.
private bool MatchesStudentFilter(UntisForeignClassRegisterEventDto entry) =>
string.IsNullOrWhiteSpace(StudentFilter) ||
string.Equals(entry.StudentName, StudentFilter, StringComparison.OrdinalIgnoreCase);
string.IsNullOrWhiteSpace(StudentFilter) || UntisNameMatching.NamesMatch(entry.StudentName, StudentFilter);
private bool MatchesStudentFilter(UntisClassAbsenceEntryDto entry) =>
string.IsNullOrWhiteSpace(StudentFilter) ||
string.Equals(entry.StudentName, StudentFilter, StringComparison.OrdinalIgnoreCase);
string.IsNullOrWhiteSpace(StudentFilter) || UntisNameMatching.NamesMatch(entry.StudentName, StudentFilter);
private static bool TryDate(int value, out DateOnly date) =>
DateOnly.TryParseExact(value.ToString(), "yyyyMMdd", out date);