diff --git a/LehrerApp.Desktop/ViewModels/ClassTeacher/ClassTeacherDetailsViewModel.cs b/LehrerApp.Desktop/ViewModels/ClassTeacher/ClassTeacherDetailsViewModel.cs index 8c8e847..e4e5629 100644 --- a/LehrerApp.Desktop/ViewModels/ClassTeacher/ClassTeacherDetailsViewModel.cs +++ b/LehrerApp.Desktop/ViewModels/ClassTeacher/ClassTeacherDetailsViewModel.cs @@ -149,8 +149,8 @@ public partial class ClassTeacherDetailsViewModel : ObservableObject public ObservableCollection CategoryAggregates { get; } = []; public ObservableCollection OwnDocumentationEntries { get; } = []; - [ObservableProperty] private DateTimeOffset _startDate = DateTimeOffset.Now.AddDays(-6); - [ObservableProperty] private DateTimeOffset _endDate = DateTimeOffset.Now; + [ObservableProperty] private DateTimeOffset? _startDate = DateTimeOffset.Now.AddDays(-6); + [ObservableProperty] private DateTimeOffset? _endDate = DateTimeOffset.Now; [ObservableProperty] private string _status = "Zeitraum wählen und laden."; [ObservableProperty] private bool _busy; /// Von der Übersicht gesetzt (Klick auf eine Roster-Zeile) - leer zeigt alle Schüler*innen. @@ -231,8 +231,8 @@ public partial class ClassTeacherDetailsViewModel : ObservableObject private async Task LoadInternal(bool forceRefresh) { - var start = DateOnly.FromDateTime(StartDate.LocalDateTime); - var end = DateOnly.FromDateTime(EndDate.LocalDateTime); + var start = DateOnly.FromDateTime((StartDate ?? DateTimeOffset.Now).LocalDateTime); + var end = DateOnly.FromDateTime((EndDate ?? DateTimeOffset.Now).LocalDateTime); if (end < start) { Status = "Das Enddatum darf nicht vor dem Startdatum liegen."; return; } if (string.IsNullOrWhiteSpace(_className)) { Status = "Keine Klasse ausgewählt."; return; } diff --git a/LehrerApp.Desktop/ViewModels/Groups/WebUntisLessonAbsenceComparisonViewModel.cs b/LehrerApp.Desktop/ViewModels/Groups/WebUntisLessonAbsenceComparisonViewModel.cs index 41ea98a..296aa0e 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/WebUntisLessonAbsenceComparisonViewModel.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/WebUntisLessonAbsenceComparisonViewModel.cs @@ -48,8 +48,8 @@ public partial class WebUntisLessonAbsenceComparisonViewModel : ObservableObject new Dictionary(); public ObservableCollection Rows { get; } = []; - [ObservableProperty] private DateTimeOffset _startDate = DateTimeOffset.Now.AddMonths(-2); - [ObservableProperty] private DateTimeOffset _endDate = DateTimeOffset.Now; + [ObservableProperty] private DateTimeOffset? _startDate = DateTimeOffset.Now.AddMonths(-2); + [ObservableProperty] private DateTimeOffset? _endDate = DateTimeOffset.Now; [ObservableProperty] private string _status = "Zeitraum wählen und Fehlzeiten laden."; [ObservableProperty] private bool _busy; [ObservableProperty] private bool _markUnknownAsPresent; @@ -73,8 +73,8 @@ public partial class WebUntisLessonAbsenceComparisonViewModel : ObservableObject return; } - var start = DateOnly.FromDateTime(StartDate.LocalDateTime); - var end = DateOnly.FromDateTime(EndDate.LocalDateTime); + var start = DateOnly.FromDateTime((StartDate ?? DateTimeOffset.Now).LocalDateTime); + var end = DateOnly.FromDateTime((EndDate ?? DateTimeOffset.Now).LocalDateTime); if (end < start) { Status = "Das Enddatum darf nicht vor dem Startdatum liegen."; return; } Busy = true; Rows.Clear(); try diff --git a/LehrerApp.Desktop/ViewModels/Planning/WebUntisTimetableImportViewModel.cs b/LehrerApp.Desktop/ViewModels/Planning/WebUntisTimetableImportViewModel.cs index 367a9dd..517796b 100644 --- a/LehrerApp.Desktop/ViewModels/Planning/WebUntisTimetableImportViewModel.cs +++ b/LehrerApp.Desktop/ViewModels/Planning/WebUntisTimetableImportViewModel.cs @@ -37,7 +37,7 @@ public partial class WebUntisTimetableImportViewModel : ObservableObject public ObservableCollection Teachers { get; } = []; public ObservableCollection Rows { get; } = []; [ObservableProperty] private UntisTeacherDto? _selectedTeacher; - [ObservableProperty] private DateTimeOffset _weekDate = DateTimeOffset.Now; + [ObservableProperty] private DateTimeOffset? _weekDate = DateTimeOffset.Now; [ObservableProperty] private string _status = "Lehrkraft auswählen und Untis-Woche laden."; [ObservableProperty] private bool _busy; public bool Saved { get; private set; } @@ -71,7 +71,7 @@ public partial class WebUntisTimetableImportViewModel : ObservableObject Busy = true; Rows.Clear(); try { - var selected = DateOnly.FromDateTime(WeekDate.LocalDateTime); + var selected = DateOnly.FromDateTime((WeekDate ?? DateTimeOffset.Now).LocalDateTime); var monday = selected.AddDays(-(((int)selected.DayOfWeek + 6) % 7)); var periods = await _untis.GetTimetableAsync(SelectedTeacher.UntisId, monday, monday.AddDays(6)); var grid = await _untis.GetTimeGridAsync(); diff --git a/LehrerApp.Desktop/ViewModels/Students/WebUntisDocumentationComparisonViewModel.cs b/LehrerApp.Desktop/ViewModels/Students/WebUntisDocumentationComparisonViewModel.cs index 2f6af27..e43fcd9 100644 --- a/LehrerApp.Desktop/ViewModels/Students/WebUntisDocumentationComparisonViewModel.cs +++ b/LehrerApp.Desktop/ViewModels/Students/WebUntisDocumentationComparisonViewModel.cs @@ -58,8 +58,8 @@ public partial class WebUntisDocumentationComparisonViewModel : ObservableObject public ObservableCollection Rows { get; } = []; public ObservableCollection LocalOnlyRows { get; } = []; - [ObservableProperty] private DateTimeOffset _startDate = DateTimeOffset.Now.AddDays(-7); - [ObservableProperty] private DateTimeOffset _endDate = DateTimeOffset.Now; + [ObservableProperty] private DateTimeOffset? _startDate = DateTimeOffset.Now.AddDays(-7); + [ObservableProperty] private DateTimeOffset? _endDate = DateTimeOffset.Now; [ObservableProperty] private string _status = "Zeitraum wählen und Klassenbucheinträge laden."; [ObservableProperty] private bool _busy; @@ -74,8 +74,8 @@ public partial class WebUntisDocumentationComparisonViewModel : ObservableObject [RelayCommand] private async Task Load() { - var start = DateOnly.FromDateTime(StartDate.LocalDateTime); - var end = DateOnly.FromDateTime(EndDate.LocalDateTime); + var start = DateOnly.FromDateTime((StartDate ?? DateTimeOffset.Now).LocalDateTime); + var end = DateOnly.FromDateTime((EndDate ?? DateTimeOffset.Now).LocalDateTime); if (end < start) { Status = "Das Enddatum darf nicht vor dem Startdatum liegen."; return; } Busy = true; Rows.Clear(); LocalOnlyRows.Clear(); try diff --git a/TODO.md b/TODO.md index ccaf6e2..e092169 100644 --- a/TODO.md +++ b/TODO.md @@ -1405,6 +1405,17 @@ Bestätigungsschritt zu verlangen. Betroffen: [WebUntisLessonAbsenceComparisonDi [WebUntisTimetableImportDialog.axaml](LehrerApp.Desktop/Views/Planning/WebUntisTimetableImportDialog.axaml) und [WebUntisDocumentationComparisonDialog.axaml](LehrerApp.Desktop/Views/Students/WebUntisDocumentationComparisonDialog.axaml). +**Nachtrag (September 2026, Nutzer-Feedback) — `CalendarDatePicker` blieb nach der Umstellung leer +und warf beim Auswählen einen Konvertierungsfehler:** `CalendarDatePicker.SelectedDate` ist +`DateTimeOffset?`, die fünf oben umgestellten ViewModel-Eigenschaften (`StartDate`/`EndDate` in +`ClassTeacherDetailsViewModel`, `WebUntisLessonAbsenceComparisonViewModel`, +`WebUntisDocumentationComparisonViewModel`, `WeekDate` in `WebUntisTimetableImportViewModel`) +waren aber als nicht-nullbares `DateTimeOffset` deklariert — anders als `WithdrawStudentDialog` +und `CreateLetterDialog`, deren Datumsfelder von Anfang an `DateTimeOffset?` sind. Der alte +`DatePicker` toleriert diese Abweichung stillschweigend, `CalendarDatePicker`s Bindung nicht. Alle +fünf Eigenschaften auf `DateTimeOffset?` umgestellt (Fallback `?? DateTimeOffset.Now` an den +wenigen Leseseiten), damit sie exakt zum Steuerelement passen. + **Nachtrag zu 4.3, Fehlzeiten je Unterricht (August 2026):** Der ursprüngliche Fehlzeitenabgleich rief `getTimetableWithAbsences` ohne Element auf und bekam damit den kompletten Lehrer-Stundenplan zurück (einmal pro Kursmitglied, siehe damalige Ineffizienz-Korrektur) — das erfordert mehr