feat: Stundenplan-Badge für unkontrollierte Hausaufgaben (4.5.4)

Lesson bekommt HomeworkChecked/HomeworkCheckDismissed. Der Stundenplan
(Tagesliste und Wochenraster im "Heute"-Tab) zeigt ein 📓-Badge, wenn die
letzte Stunde einer Gruppe eine Hausaufgabe hatte, die noch nicht
kontrolliert oder bewusst übersprungen wurde. Umschaltbar über zwei sich
gegenseitig ausschließende Checkboxen ("Kontrolliert"/"Nicht
kontrollieren") im Verlaufsplan-Editor, direkt neben dem
Hausaufgabenfeld.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 20:52:22 +02:00
co-authored by Claude Sonnet 5
parent 462080ab92
commit 41bf2c0756
8 changed files with 215 additions and 10 deletions
@@ -179,6 +179,59 @@ public sealed class LessonDialogViewModelTests
Assert.Single(lessons.GetByUnit(unitId));
}
[Fact]
public void HasHomeworkText_OhneHausaufgabe_IstFalse()
{
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid());
Assert.False(vm.HasHomeworkText);
vm.Homework = " ";
Assert.False(vm.HasHomeworkText);
vm.Homework = "S. 42";
Assert.True(vm.HasHomeworkText);
}
[Fact]
public void Save_UebernimmtHomeworkCheckedUndDismissed()
{
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid());
vm.Topic = "Brechung"; vm.DateText = "01.09.2025";
vm.Homework = "S. 42"; vm.HomeworkChecked = true;
vm.SaveCommand.Execute(null);
Assert.True(vm.Result!.HomeworkChecked);
Assert.False(vm.Result.HomeworkCheckDismissed);
}
[Fact]
public void HomeworkChecked_UndHomeworkCheckDismissed_SchliessenSichGegenseitigAus()
{
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid());
vm.HomeworkChecked = true;
Assert.False(vm.HomeworkCheckDismissed);
vm.HomeworkCheckDismissed = true;
Assert.False(vm.HomeworkChecked);
}
[Fact]
public void Bearbeiten_UebernimmtGespeicherteHomeworkFlags()
{
var editing = new Lesson
{
Topic = "Alt", Date = new DateOnly(2025, 9, 1), Homework = "S. 42",
HomeworkCheckDismissed = true,
};
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid(), editing);
Assert.True(vm.HomeworkCheckDismissed);
Assert.False(vm.HomeworkChecked);
}
[Fact]
public void HasAlternativePath_AngehaktOeffnetZuweisungUndUebernimmtErgebnis()
{
@@ -132,6 +132,88 @@ public sealed class TimetableViewModelTests
Assert.True(item.HasExam);
}
[Fact]
public void Load_HeutigeStunde_VorherigeUnkontrollierteHausaufgabe_ZeigtBadge()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var slots = new FakeTimetableSlots();
slots.Add(new TimetableSlot { GroupId = group.Id, Weekday = today.DayOfWeek, PeriodNumber = 1 });
var lessons = new FakeLessons();
lessons.Add(new Lesson { GroupId = group.Id, Date = today.AddDays(-3), Homework = "S. 42, Aufgabe 3" });
var vm = BuildViewModel(slots, new FakeGroups([group]), lessons: lessons);
var item = Assert.Single(vm.TodayItems);
Assert.True(item.HasUnhandledHomework);
}
[Fact]
public void Load_HeutigeStunde_HausaufgabeKontrolliert_KeinBadge()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var slots = new FakeTimetableSlots();
slots.Add(new TimetableSlot { GroupId = group.Id, Weekday = today.DayOfWeek, PeriodNumber = 1 });
var lessons = new FakeLessons();
lessons.Add(new Lesson
{
GroupId = group.Id, Date = today.AddDays(-3), Homework = "S. 42, Aufgabe 3", HomeworkChecked = true,
});
var vm = BuildViewModel(slots, new FakeGroups([group]), lessons: lessons);
var item = Assert.Single(vm.TodayItems);
Assert.False(item.HasUnhandledHomework);
}
[Fact]
public void Load_HeutigeStunde_HausaufgabenKontrolleBewusstAbgeschaltet_KeinBadge()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var slots = new FakeTimetableSlots();
slots.Add(new TimetableSlot { GroupId = group.Id, Weekday = today.DayOfWeek, PeriodNumber = 1 });
var lessons = new FakeLessons();
lessons.Add(new Lesson
{
GroupId = group.Id, Date = today.AddDays(-3), Homework = "S. 42, Aufgabe 3",
HomeworkCheckDismissed = true,
});
var vm = BuildViewModel(slots, new FakeGroups([group]), lessons: lessons);
var item = Assert.Single(vm.TodayItems);
Assert.False(item.HasUnhandledHomework);
}
[Fact]
public void Load_HeutigeStunde_VorherigeStundeOhneHausaufgabe_KeinBadge()
{
var today = DateOnly.FromDateTime(DateTime.Today);
var group = new LearningGroup { Name = "Q1 Chemie" };
var slots = new FakeTimetableSlots();
slots.Add(new TimetableSlot { GroupId = group.Id, Weekday = today.DayOfWeek, PeriodNumber = 1 });
var lessons = new FakeLessons();
lessons.Add(new Lesson { GroupId = group.Id, Date = today.AddDays(-3) });
var vm = BuildViewModel(slots, new FakeGroups([group]), lessons: lessons);
var item = Assert.Single(vm.TodayItems);
Assert.False(item.HasUnhandledHomework);
}
[Fact]
public void Load_Wochenkachel_VorherigeUnkontrollierteHausaufgabe_ZeigtBadge()
{
var group = new LearningGroup { Name = "Q1 Chemie" };
var date = DateInCurrentWeek(DayOfWeek.Wednesday);
var slots = new FakeTimetableSlots();
slots.Add(new TimetableSlot { GroupId = group.Id, Weekday = DayOfWeek.Wednesday, PeriodNumber = 1 });
var lessons = new FakeLessons();
lessons.Add(new Lesson { GroupId = group.Id, Date = date.AddDays(-2), Homework = "Vokabeln lernen" });
var vm = BuildViewModel(slots, new FakeGroups([group]), lessons: lessons);
var cell = vm.WeekItems.Single(c => c.IsSlotCell && c.Weekday == DayOfWeek.Wednesday && c.PeriodNumber == 1);
Assert.True(cell.HasUnhandledHomework);
}
[Fact]
public void OpenGroup_RuftOnNavigateToGroupMitDerGroupIdAuf()
{