feat: Komfort-Features für Unterrichtsplanung, Zeiterfassung und Dashboard

- Neue-Stunde-Dialog: Datum wird beim Anlegen anhand des Stundenplans
  und der letzten Stunde der Einheit vorbelegt statt auf "heute"
  (behebt eine falsch erkannte Doppelstunde, wenn "heute" nicht auf
  den passenden Wochentag fiel).
- Zeiterfassung: Button "Unterrichtszeit heute übernehmen" schlägt
  Start/Ende aus dem heutigen Stundenplan inkl. Puffer davor/danach vor.
- Dashboard: neue Kachel "Ungeplante Stunden" erinnert an Stunden ohne
  Thema für heute/morgen, mit Opt-out je Gruppe ("Benötigt
  Unterrichtsplanung"), Doppelstunden-Erkennung (keine doppelte Meldung
  für die zweite Periode) und Berücksichtigung von Stundenausfall.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 11:30:50 +02:00
co-authored by Claude Sonnet 5
parent a36b1d1d40
commit fd509fc921
17 changed files with 585 additions and 23 deletions
@@ -66,9 +66,13 @@
</Border>
<!-- Einträge / Nacherfassung (6.2.2) -->
<Grid ColumnDefinitions="*,Auto">
<Grid ColumnDefinitions="*,Auto,Auto">
<TextBlock Grid.Column="0" Text="Einträge" FontWeight="SemiBold" FontSize="14" VerticalAlignment="Center"/>
<Button Grid.Column="1" Content=" Nacherfassen" Command="{Binding AddEntryCommand}"/>
<Button Grid.Column="1" Content="🕓 Unterrichtszeit heute übernehmen" Margin="0,0,8,0"
Command="{Binding SuggestTeachingTimeCommand}"
IsVisible="{Binding HasTeachingTimeSuggestionToday}"
ToolTip.Tip="Schlägt Beginn/Ende anhand des heutigen Stundenplans vor (mit etwas Puffer davor/danach) - im Dialog vor dem Speichern noch anpassbar."/>
<Button Grid.Column="2" Content=" Nacherfassen" Command="{Binding AddEntryCommand}"/>
</Grid>
<ItemsControl ItemsSource="{Binding WeekEntries}">
@@ -14,10 +14,15 @@ public partial class TimeTrackingView : UserControl
{
base.OnDataContextChanged(e);
if (DataContext is TimeTrackingViewModel vm)
vm.OnAddEntry = ShowAddEntryDialog;
{
vm.OnAddEntry = () => ShowAddEntryDialog();
vm.OnSuggestTeachingTime = (start, end) => ShowAddEntryDialog(prefillCategory: "Unterricht",
prefillStart: start, prefillEnd: end);
}
}
private async Task<TimeEntry?> ShowAddEntryDialog()
private async Task<TimeEntry?> ShowAddEntryDialog(string? prefillCategory = null,
TimeOnly? prefillStart = null, TimeOnly? prefillEnd = null)
{
var owner = TopLevel.GetTopLevel(this) as Window;
if (owner is null) return null;
@@ -25,6 +30,9 @@ public partial class TimeTrackingView : UserControl
var tasks = App.Services.GetRequiredService<IWorkTaskRepository>()
.GetAll().Where(t => t.Status != WorkTaskStatus.Done).ToList();
var vm = new AddTimeEntryDialogViewModel(tasks);
if (prefillCategory is not null) vm.SelectedCategory = prefillCategory;
if (prefillStart is { } s) vm.StartTimeText = s.ToString("HH:mm");
if (prefillEnd is { } e) vm.EndTimeText = e.ToString("HH:mm");
var dialog = new AddTimeEntryDialog { DataContext = vm };
await dialog.ShowDialog<bool>(owner);
return vm.Result;