Klassenlehrer-Tab: restliche Quick-Wins (responsive Balken, Tagesüberblick-Chart, Tooltips, Status-Symbol)

Balkenbreiten hingen bisher an einer im ViewModel hart codierten Pixelkonstante;
Grid.ColumnDefinitions ließ sich dafür nicht binden (AVLN3000, kein Setter bei
kompilierten Bindings), deshalb neuer FractionWidthConverter (MultiBinding
gegen die gerenderte Breite einer Track-Border statt Grid-Sternspalten).
Tagesüberblick zeigt jetzt denselben gestapelten Balken statt vier
Einzelzeilen. AbsenceTooltip und TodayUnexcusedPercent waren berechnet aber
ungebunden, jetzt sichtbar. Status-Zeilen bekommen zusätzlich zur Farbe ein
vorangestelltes Symbol (Barrierefreiheit).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 13:25:32 +02:00
co-authored by Claude Sonnet 5
parent 9d375caf14
commit b3b86f0cf4
6 changed files with 291 additions and 29 deletions
+39 -4
View File
@@ -1403,10 +1403,11 @@ eigenen Unterricht abfragt und deshalb mit den regulären Lehrkraft-Rechten funk
lieferte bisher `AlertBarWidth`/`UnexcusedBarWidth`/`LateBarWidth`, jede für sich auf dasselbe
Maximum normiert — das suggerierte drei unabhängige Größen, obwohl Unentschuldigt und
Verspätet Teilmengen von Alerts sind. Jetzt drei überschneidungsfreie Segmente (Unentschuldigt
hat Vorrang vor Verspätet, gleiche Priorisierung wie `ClassTeacherRosterRow.AttentionRank`),
deren Breiten sich exakt zu `TotalBarWidth` summieren; in XAML als `Border ClipToBounds="True"`
mit `CornerRadius` um eine horizontale `StackPanel` aus drei quadratischen Segmenten gerendert,
damit nur die äußeren Kanten abgerundet sind.
hat Vorrang vor Verspätet, gleiche Priorisierung wie `ClassTeacherRosterRow.AttentionRank`);
in XAML als `Border ClipToBounds="True"` mit `CornerRadius` um eine horizontale `StackPanel`
aus drei Segmenten gerendert, damit nur die äußeren Kanten abgerundet sind. Wie die
Segmentbreiten selbst berechnet werden, hat sich im Nachtrag unten noch einmal geändert
siehe dort.
- **Trend über die letzten 7 Schultage statt Kalendertage:** an zwei von sieben Tagen war der
Balken bislang systematisch leer, weil `start.AddDays(offset)` Wochenenden mitzählte. Neues
`ClassTeacherOverviewViewModel.LastSchoolDays` überspringt Samstag/Sonntag — bewusst ohne
@@ -1423,6 +1424,40 @@ eigenen Unterricht abfragt und deshalb mit den regulären Lehrkraft-Rechten funk
Klassenbucheinträgen zu cachen wäre unnötiges Datenvolumen).
Neue `SchoolYearService`-Abhängigkeit in `ClassTeacherOverviewViewModel` (Konstruktor-Injection,
Service war bereits als Singleton registriert).
- [x] **"Klassenlehrer"-Feature — restliche Quick-Wins (August 2026):** Die vier verbliebenen
Punkte aus derselben Vorschlagsliste wie oben.
- **Balkenbreiten responsiv statt fester Pixelkonstante:** `BuildTrend` rechnete bisher mit
einer im ViewModel hart codierten Pixelbreite (`112d`), die mit der tatsächlichen Breite der
Seitenspalte in XAML synchron gehalten werden musste. Erster Versuch — `Grid.ColumnDefinitions`
per `{Binding}` auf einen "N*,N*,…"-String setzen, wie es die eingebaute XAML-Stringsyntax
erlaubt — scheiterte an `AVLN3000` ("Unable to find suitable setter"): `ColumnDefinitions` hat
bei kompilierten Bindings (`x:DataType`) keinen normalen Property-Setter, auch nicht über einen
`IValueConverter`. Stattdessen liefert `ClassTeacherTrendDay`/`ClassTeacherOverviewViewModel`
jetzt Anteile 0…1 (`UnexcusedFraction`/`LateExcusedFraction`/`ExcusedFraction` bzw.
`Present-/Late-/ExcusedAbsence-/UnexcusedAbsenceFraction`), und die View multipliziert sie per
`MultiBinding` mit der tatsächlich gerenderten Breite einer benannten, unsichtbaren
Track-`Border` (`ElementName=…, Path=Bounds.Width`) — neuer
[FractionWidthConverter.cs](LehrerApp.Desktop/Converters/FractionWidthConverter.cs)
(`IMultiValueConverter`). Bleibt dadurch korrekt, unabhängig davon, wie breit die Seitenspalte
gerade ist, ohne dass View und ViewModel einen Pixelwert teilen müssten.
- **Tagesüberblick als gestapelter 100-%-Balken statt vier Einzelzeilen:** neue `Grid` mit
demselben Track-`Border`/`MultiBinding`/`FractionWidthConverter`-Muster wie beim Trend, direkt
über der (weiterhin vorhandenen, jetzt kompakteren) Legende. Die vier Kategorien sind exklusiv
und summieren sich exakt zu `StudentCount`, brauchen also anders als beim Trend keine
Rest-Kategorie für den Sonderfall "unter dem Maximum".
- **`AbsenceTooltip` und `TodayUnexcusedPercent` gebunden:** beide wurden berechnet, aber nie
angezeigt. `AbsenceTooltip` hängt jetzt als `ToolTip.Tip` am Avatar-Kreis jeder Roster-Zeile;
`TodayUnexcusedPercent` steckt in einem neuen `TodayUnexcusedSummaryLabel` unter der
"unentschuldigt"-Kennzahlkarte oben. Die vier vormals ungenutzten Prozent-Properties
(`Present-/Late-/ExcusedAbsence-/UnexcusedAbsencePercent`) sind jetzt ebenfalls in
Summary-Labels der neuen Tagesüberblick-Legende eingebettet, statt einer eigenen
rechtsbündigen Spalte wie zuvor.
- **Symbol zusätzlich zur Farbe (Barrierefreiheit):** der Status einer Roster-Zeile hing zuvor
an der Farbe der linken 4-px-Leiste plus reinem Text ohne visuellen Vorrang. Neues
`ClassTeacherRosterRow.StatusTextWithGlyph` stellt "✕ " (Gefahr) bzw. "△ " (Warnung) voran —
dieselben Symbole wie in den Kennzahlkarten oben, damit sich die Bedeutung nicht neu erlernen
lässt. `StatusText` selbst bleibt unverändert (bestehende Tests/Bindings), das Symbol ist eine
zusätzliche, separat getestete Property.
### 4.4 Wochen-/Tagesansicht