feat: Abwesenheits-Hinweise, Fehlquote bei Zeugnisnoten, Gruppen-Dokumentation

- Schnellbewerten-Dialog: abwesende Schüler werden gedimmt und mit ihrem
  Anwesenheitsstatus statt der Aspektbeschriftung angezeigt, damit keine
  Mitarbeitsnote für nicht anwesende Schüler vergeben wird.
- Zeugnisnoten-Dialog: zeigt je Schüler die Fehlquote im gewählten
  Zeitraum, ab 50 % hervorgehoben (informativ, keine automatische
  Notenänderung).
- Gruppen-Tab "Dokumentation" (bisher Platzhalter) implementiert: listet
  alle Dokumentationseinträge der Gruppen-Schüler, mit Schüler-Filter und
  optionalem "Nur dieser Unterricht"-Schalter. Einträge aus anderen
  Lerngruppen werden standardmäßig mitangezeigt, aber gedimmt. Der
  Dokumentationsdialog bekommt dafür einen optionalen Schüler-Picker.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 19:45:01 +02:00
co-authored by Claude Sonnet 5
parent f2cb3c98c6
commit a0f44f1b25
19 changed files with 725 additions and 26 deletions
@@ -361,6 +361,9 @@ public partial class ParticipationStudentRow : ObservableObject
public string AttendanceLabel => AttendanceDisplay.ShortLabel(Attendance);
public string AttendanceTooltip => AttendanceDisplay.Label(Attendance);
/// Abwesend im Sinne der Mitarbeitsbewertung: eine Bewertung ergibt für diese Stunde keinen
/// Sinn, unabhängig davon, ob die Abwesenheit entschuldigt ist oder noch geklärt werden muss.
public bool IsAbsent => Attendance is not null and not AttendanceStatus.Present;
public string HomeworkSymbol => HomeworkDisplay.Symbol(Homework);
public string HomeworkTooltip => HomeworkDisplay.Label(Homework);
@@ -442,6 +445,7 @@ public partial class ParticipationStudentRow : ObservableObject
};
OnPropertyChanged(nameof(AttendanceLabel));
OnPropertyChanged(nameof(AttendanceTooltip));
OnPropertyChanged(nameof(IsAbsent));
AttendanceChangedCallback?.Invoke(StudentId, Attendance);
}
@@ -451,6 +455,7 @@ public partial class ParticipationStudentRow : ObservableObject
Attendance = value;
OnPropertyChanged(nameof(AttendanceLabel));
OnPropertyChanged(nameof(AttendanceTooltip));
OnPropertyChanged(nameof(IsAbsent));
AttendanceChangedCallback?.Invoke(StudentId, value);
}
}
@@ -727,6 +732,13 @@ public partial class QuickInputViewModel : ObservableObject
[ObservableProperty] private string _currentAspectLabel = "";
[ObservableProperty] private string _currentValueLabel = "";
[ObservableProperty] private string _progressText = "";
[ObservableProperty] private bool _currentStudentIsAbsent;
[ObservableProperty] private string _currentStudentAttendanceLabel = "";
/// Dimmt Name/Aspektliste, wenn der aktuelle Schüler abwesend ist — kein Blockieren der
/// Eingabe (manche Bewertungssysteme wollen trotzdem einen Eintrag, z.B. "0 Punkte"), nur ein
/// visueller Hinweis, dass eine Bewertung hier normalerweise keinen Sinn ergibt.
public double CurrentStudentContentOpacity => CurrentStudentIsAbsent ? 0.4 : 1.0;
public ObservableCollection<QuickAspectRow> AspectRows { get; } = [];
@@ -758,6 +770,7 @@ public partial class QuickInputViewModel : ObservableObject
}
partial void OnAspectIndexChanged(int value) => OnPropertyChanged(nameof(HotkeyLegend));
partial void OnCurrentStudentIsAbsentChanged(bool value) => OnPropertyChanged(nameof(CurrentStudentContentOpacity));
private AspectValueType CurrentAspectType() =>
_aspects.Count == 0 ? AspectValueType.Scale5 : _aspects[Math.Clamp(AspectIndex, 0, _aspects.Count - 1)].ValueType;
@@ -771,6 +784,8 @@ public partial class QuickInputViewModel : ObservableObject
var row = _rows[index];
StudentName = row.Name;
ProgressText = $"{index + 1} / {_rows.Count}";
CurrentStudentIsAbsent = row.IsAbsent;
CurrentStudentAttendanceLabel = row.AttendanceTooltip;
AspectRows.Clear();
foreach (var (a, i) in _aspects.Select((a, i) => (a, i)))