Stundenplan: Wochenraster, Wochennavigation, Ferien/Feiertage (Kapitel 4.3)

Neuer Stundenplan mit "Heute"-Standardansicht (Tagesliste unten angedockt,
gruppenübergreifendes Wochenraster mit Fach/Klasse/Raum/Thema, Vor-/Zurück-
Navigation zwischen Kalenderwochen) und separatem Bearbeiten-Raster für die
wöchentliche Zuordnung. Badges für Ferien-/Klausur-Nähe und ausgegraute
Ferientage direkt im Plan statt einer separaten Liste. Ferien-/Feiertage-
Pflege (Bundesland, Schulferien) sitzt jetzt in den Einstellungen statt im
Stundenplan selbst.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 02:29:18 +02:00
co-authored by Claude Sonnet 5
parent ee1a47641e
commit 99b2de6519
26 changed files with 2154 additions and 18 deletions
@@ -0,0 +1,78 @@
using LehrerApp.Core.Models;
using LehrerApp.Core.Services;
using LehrerApp.Desktop.ViewModels.Planning;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class TimetableSlotDialogViewModelTests
{
private static SchoolYearService SchoolYear() => new();
[Fact]
public void Save_OhneAusgewaehlteGruppe_SetztFehlerUndSpeichertNicht()
{
var slots = new FakeTimetableSlots();
var groups = new FakeGroups([]);
var vm = new TimetableSlotDialogViewModel(slots, groups, SchoolYear(), DayOfWeek.Monday, 1, null);
vm.SaveCommand.Execute(null);
Assert.Null(vm.Result);
Assert.NotEqual("", vm.GroupError);
}
[Fact]
public void Save_MitAusgewaehlterGruppe_LegtNeuenSlotAn()
{
var group = new LearningGroup { Name = "Q1 Chemie" };
var slots = new FakeTimetableSlots();
var groups = new FakeGroups([group]);
var vm = new TimetableSlotDialogViewModel(slots, groups, SchoolYear(), DayOfWeek.Monday, 1, null)
{
SelectedGroupName = "Q1 Chemie", Room = "R204",
};
vm.SaveCommand.Execute(null);
Assert.NotNull(vm.Result);
Assert.Equal(group.Id, vm.Result!.GroupId);
Assert.Equal("R204", vm.Result.Room);
Assert.Single(slots.GetAll());
}
[Fact]
public void Save_BelegteStunde_ZeigtFreundlicheFehlermeldungStattAbsturz()
{
var groupA = new LearningGroup { Name = "Q1 Chemie" };
var groupB = new LearningGroup { Name = "Q1 Physik" };
var slots = new FakeTimetableSlots();
slots.Add(new TimetableSlot { GroupId = groupA.Id, Weekday = DayOfWeek.Monday, PeriodNumber = 1 });
var groups = new FakeGroups([groupA, groupB]);
var vm = new TimetableSlotDialogViewModel(slots, groups, SchoolYear(), DayOfWeek.Monday, 1, null)
{
SelectedGroupName = "Q1 Physik",
};
vm.SaveCommand.Execute(null);
Assert.Null(vm.Result);
Assert.Equal("Diese Stunde ist bereits belegt.", vm.GroupError);
}
[Fact]
public void Delete_BeimBearbeitenEinesVorhandenenSlots_EntferntIhn()
{
var group = new LearningGroup { Name = "Q1 Chemie" };
var slot = new TimetableSlot { GroupId = group.Id, Weekday = DayOfWeek.Monday, PeriodNumber = 1 };
var slots = new FakeTimetableSlots();
slots.Add(slot);
var groups = new FakeGroups([group]);
var vm = new TimetableSlotDialogViewModel(slots, groups, SchoolYear(), DayOfWeek.Monday, 1, slot);
vm.DeleteCommand.Execute(null);
Assert.True(vm.Deleted);
Assert.Empty(slots.GetAll());
}
}