Klausurtermine im Kalender (4.4.3) + Stundenplan: Ausnahme eintragen, Zahnrad-Settings-Link

- 4.4.3: Box "ANSTEHENDE KLAUSUREN" im Heute-Tab, gruppenübergreifend, nächste 21 Tage.
  IExamRepository um GetAll() erweitert.
- Nutzer-Feedback: "Vertretung eintragen" deckt auch Ausfall/Sondereinsatz ab, daher
  umbenannt in "Ausnahme eintragen". "Stundenplan bearbeiten" (redundant zum Bearbeiten-Tab)
  ersetzt durch Zahnrad-Button, der direkt in die Einstellungen springt.
This commit is contained in:
2026-08-15 22:24:04 +02:00
parent d6dee72acc
commit 0800832ae5
13 changed files with 189 additions and 21 deletions
@@ -148,13 +148,15 @@ public sealed class TimetableViewModelTests
}
[Fact]
public void ShowEditor_SchaltetAufBearbeiten_Tab()
public void OpenSettings_RuftOnNavigateToSettingsAuf()
{
var vm = BuildViewModel(new FakeTimetableSlots(), new FakeGroups([]));
var called = false;
vm.OnNavigateToSettings = () => called = true;
vm.ShowEditorCommand.Execute(null);
vm.OpenSettingsCommand.Execute(null);
Assert.Equal(1, vm.ActiveTabIndex);
Assert.True(called);
}
// ── "Heute"-Ansicht: Wochenraster (Nutzer-Feedback, zweite Iteration) ────────────────────
@@ -742,4 +744,68 @@ public sealed class TimetableViewModelTests
var item = Assert.Single(vm.TodayItems);
Assert.False(item.HasLessonTopic);
}
// ── Anstehende Klausurtermine (4.4.3) ────────────────────────────────────
[Fact]
public void Load_ZeigtKlausurInnerhalbDesVorausblicks()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var exams = new FakeExams([new Exam { GroupId = group.Id, Date = today.AddDays(10), Title = "Klausur Nr. 2" }]);
var vm = BuildViewModel(new FakeTimetableSlots(), new FakeGroups([group]), exams: exams);
var item = Assert.Single(vm.UpcomingExams);
Assert.Equal("Q1 Chemie", item.GroupName);
Assert.Equal("Klausur Nr. 2", item.Title);
Assert.Equal(today.AddDays(10), item.Date);
}
[Fact]
public void Load_KlausurAusserhalbDesVorausblicks_WirdNichtGezeigt()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var exams = new FakeExams([new Exam { GroupId = group.Id, Date = today.AddDays(30), Title = "Klausur Nr. 3" }]);
var vm = BuildViewModel(new FakeTimetableSlots(), new FakeGroups([group]), exams: exams);
Assert.Empty(vm.UpcomingExams);
}
[Fact]
public void Load_VergangeneKlausur_WirdNichtGezeigt()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var exams = new FakeExams([new Exam { GroupId = group.Id, Date = today.AddDays(-1), Title = "Alte Klausur" }]);
var vm = BuildViewModel(new FakeTimetableSlots(), new FakeGroups([group]), exams: exams);
Assert.Empty(vm.UpcomingExams);
}
[Fact]
public void Load_MehrereKlausuren_SindNachDatumSortiert()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var exams = new FakeExams(
[
new Exam { GroupId = group.Id, Date = today.AddDays(15), Title = "Später" },
new Exam { GroupId = group.Id, Date = today.AddDays(3), Title = "Früher" },
]);
var vm = BuildViewModel(new FakeTimetableSlots(), new FakeGroups([group]), exams: exams);
Assert.Equal(["Früher", "Später"], vm.UpcomingExams.Select(e => e.Title));
}
[Fact]
public void Load_HeutigeKlausur_IstImVorausblickEnthalten()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var exams = new FakeExams([new Exam { GroupId = group.Id, Date = today, Title = "Heute" }]);
var vm = BuildViewModel(new FakeTimetableSlots(), new FakeGroups([group]), exams: exams);
Assert.Single(vm.UpcomingExams);
}
}