diff --git a/LehrerApp.Api.Tests/AttachmentStoreTests.cs b/LehrerApp.Api.Tests/AttachmentStoreTests.cs index 85e4b90..cd0d4c1 100644 --- a/LehrerApp.Api.Tests/AttachmentStoreTests.cs +++ b/LehrerApp.Api.Tests/AttachmentStoreTests.cs @@ -38,7 +38,8 @@ public sealed class AttachmentStoreTests await store.StoreAsync("user-1", "shared-id", new MemoryStream([1])); Assert.Null(store.OpenRead("user-2", "shared-id")); - Assert.NotNull(store.OpenRead("user-1", "shared-id")); + using var user1Attachment = store.OpenRead("user-1", "shared-id"); + Assert.NotNull(user1Attachment); } [Fact] diff --git a/LehrerApp.Core/Models/Workload.cs b/LehrerApp.Core/Models/Workload.cs index 430065c..2ef47b0 100644 --- a/LehrerApp.Core/Models/Workload.cs +++ b/LehrerApp.Core/Models/Workload.cs @@ -5,6 +5,10 @@ public class Documentation public Guid Id { get; set; } = Guid.NewGuid(); public Guid StudentId { get; set; } public Guid? GroupId { get; set; } + /// Unterrichtssitzung, in der die Beobachtung entstanden ist. + public Guid? ParticipationSessionId { get; set; } + /// Optionaler Bezug auf die konkrete geplante Stunde. + public Guid? LessonId { get; set; } public DocumentationType Type { get; set; } public DateOnly Date { get; set; } public string Title { get; set; } = ""; @@ -17,6 +21,8 @@ public class Documentation public List Attachments { get; set; } = []; /// Freie Labels zur Nachverfolgung, z.B. "Kritisch", "Nacharbeiten" — siehe `DocumentationTagDisplay`. public List Tags { get; set; } = []; + /// Im Unterricht schnell erfasst und noch inhaltlich nachzuarbeiten. + public bool IsDraft { get; set; } public bool IsConfidential { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; diff --git a/LehrerApp.Desktop.Tests/DocumentationDialogViewModelTests.cs b/LehrerApp.Desktop.Tests/DocumentationDialogViewModelTests.cs index c04ac1d..676ae0e 100644 --- a/LehrerApp.Desktop.Tests/DocumentationDialogViewModelTests.cs +++ b/LehrerApp.Desktop.Tests/DocumentationDialogViewModelTests.cs @@ -137,6 +137,24 @@ public sealed class DocumentationDialogViewModelTests Assert.Equal("Gut verlaufen", vm.Result.ParentCallData.Impressions); } + [Fact] + public void Save_SitzplanEntwurf_WirdAbgeschlossenUndBehaeltStundenbezug() + { + var sessionId = Guid.NewGuid(); + var existing = new Documentation + { + StudentId = Guid.NewGuid(), Type = DocumentationType.Incident, + Date = DateOnly.FromDateTime(DateTime.Today), Title = "Streit/Konflikt", + IsDraft = true, ParticipationSessionId = sessionId, Tags = ["Streit/Konflikt"], + }; + var vm = new DocumentationDialogViewModel(existing.StudentId, existing, new FakeAttachmentStorage()); + + vm.SaveCommand.Execute(null); + + Assert.False(vm.Result!.IsDraft); + Assert.Equal(sessionId, vm.Result.ParticipationSessionId); + } + [Fact] public void Save_Elternbrief_UebernimmtVersandUndRueckmeldung() { diff --git a/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs b/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs index 106a5fc..9146bca 100644 --- a/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs +++ b/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs @@ -146,6 +146,66 @@ public sealed class SeatingPlanViewModelTests Assert.All(vm.Seats, seat => Assert.True(seat.CanEdit)); } + [Fact] + public void Ansichtsmodus_ZeigtAnwesenheitUndHausaufgabeUndBlendetAbwesendeAb() + { + var groupId = Guid.NewGuid(); + var student = new Student { FirstName = "Anna", LastName = "A" }; + var session = new ParticipationSession { GroupId = groupId, Date = DateOnly.FromDateTime(DateTime.Today) }; + var entries = new FakeEntries(); + entries.Add(new ParticipationEntry + { + SessionId = session.Id, StudentId = student.Id, + Attendance = AttendanceStatus.Excused, Homework = HomeworkStatus.MissingOpen, + }); + var plan = new SeatingPlan + { + GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1, + Assignments = [new SeatAssignment { StudentId = student.Id }], + }; + var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]), + new FakeMemberships([new GroupMembership { GroupId = groupId, StudentId = student.Id }]), + new FakeSessions([session]), entries, new FakeAspects()); + + vm.Initialize(groupId, isReadOnly: false); + + var seat = Assert.Single(vm.Seats); + Assert.True(seat.HasAttendanceBadge); + Assert.True(seat.HasHomeworkBadge); + Assert.Equal(0.42, seat.LessonOpacity); + } + + [Fact] + public void SituationsTags_WerdenProSchuelerUndSitzungInEinemEntwurfZusammengefuehrt() + { + var groupId = Guid.NewGuid(); + var student = new Student { FirstName = "Anna", LastName = "A" }; + var session = new ParticipationSession + { + GroupId = groupId, Date = DateOnly.FromDateTime(DateTime.Today), LessonId = Guid.NewGuid(), + }; + var docs = new FakeDocumentation(); + var plan = new SeatingPlan + { + GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1, + Assignments = [new SeatAssignment { StudentId = student.Id }], + }; + var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]), + new FakeMemberships([new GroupMembership { GroupId = groupId, StudentId = student.Id }]), + new FakeSessions([session]), new FakeEntries(), new FakeAspects(), docs); + vm.Initialize(groupId, isReadOnly: false); + var seat = Assert.Single(vm.Seats); + + seat.SituationTags.Single(t => t.Text == "Mitarbeit verweigert").ToggleCommand.Execute(null); + seat.SituationTags.Single(t => t.Text == "Material vergessen").ToggleCommand.Execute(null); + + var draft = Assert.Single(docs.GetByStudent(student.Id)); + Assert.True(draft.IsDraft); + Assert.Equal(session.Id, draft.ParticipationSessionId); + Assert.Equal(session.LessonId, draft.LessonId); + Assert.Equal(["Mitarbeit verweigert", "Material vergessen"], draft.Tags); + } + [Fact] public void Tischabstaende_WerdenBeimBearbeitenProSpaltengrenzeGespeichert() { diff --git a/LehrerApp.Desktop/App.axaml.cs b/LehrerApp.Desktop/App.axaml.cs index 41c380a..9ba92b6 100644 --- a/LehrerApp.Desktop/App.axaml.cs +++ b/LehrerApp.Desktop/App.axaml.cs @@ -9,6 +9,7 @@ using LehrerApp.Desktop.ViewModels.Groups; using LehrerApp.Desktop.ViewModels.Planning; using LehrerApp.Desktop.ViewModels.Students; using LehrerApp.Desktop.Views; +using LehrerApp.Sync; using Microsoft.Extensions.DependencyInjection; namespace LehrerApp.Desktop; @@ -66,6 +67,8 @@ public class App : Application var mainVm = Services.GetRequiredService(); WireCallbacks(mainVm); var main = new MainWindow { DataContext = mainVm }; + if (Services.GetService() is { } syncEngine) + main.EnableFinalSync(syncEngine); desktop.MainWindow = main; if (showImmediately) main.Show(); } diff --git a/LehrerApp.Desktop/ViewModels/Groups/GroupDocumentationViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/GroupDocumentationViewModels.cs index 6b33731..9dac71e 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/GroupDocumentationViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/GroupDocumentationViewModels.cs @@ -31,6 +31,7 @@ public partial class GroupDocumentationTabViewModel : ObservableObject [ObservableProperty] private StudentOption _selectedStudentFilter = AllStudentsOption; [ObservableProperty] private bool _onlyThisGroup; + [ObservableProperty] private int _draftCount; public Func, Documentation?, Task>? OnEditDocumentation { get; set; } public Func>? OnConfirmDeleteDocumentation { get; set; } @@ -80,7 +81,10 @@ public partial class GroupDocumentationTabViewModel : ObservableObject var all = relevantStudentIds .SelectMany(id => _docs.GetByStudent(id)) .Where(d => !OnlyThisGroup || d.GroupId == _groupId) - .OrderByDescending(d => d.Date); + .OrderByDescending(d => d.IsDraft) + .ThenByDescending(d => d.Date) + .ToList(); + DraftCount = all.Count(d => d.IsDraft && (d.GroupId is null || d.GroupId == _groupId)); foreach (var d in all) { @@ -91,6 +95,8 @@ public partial class GroupDocumentationTabViewModel : ObservableObject } } + public void Refresh() => Load(); + [RelayCommand] private async Task AddDocumentation() { diff --git a/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs index aee4a25..7c0fa49 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs @@ -250,6 +250,7 @@ public partial class GroupDetailViewModel : ObservableObject ParticipationTab.LoadSessions(); ParticipationTab.RefreshCurrentGrid(); }; + SeatingPlanTab.OnDocumentationChanged = GroupDocumentationTab.Refresh; } public void LoadGroup(Guid id) diff --git a/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs index f6c5a75..48099c5 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs @@ -15,6 +15,7 @@ public partial class SeatingPlanTabViewModel : ObservableObject private readonly IParticipationSessionRepository _sessions; private readonly IParticipationRepository _participation; private readonly IParticipationAspectRepository _aspects; + private readonly IDocumentationRepository? _documentation; private Guid _groupId; private SeatingPlan? _currentPlan; private bool _isReadOnly; @@ -28,11 +29,13 @@ public partial class SeatingPlanTabViewModel : ObservableObject [ObservableProperty] private bool _isBoardAtBottom; [ObservableProperty] private IReadOnlyList _columnGapWidths = []; [ObservableProperty] private bool _isEditMode; + [ObservableProperty] private ParticipationSessionOption? _selectedSession; public ObservableCollection Plans { get; } = []; public ObservableCollection Seats { get; } = []; public ObservableCollection StudentOptions { get; } = []; public ObservableCollection UnassignedStudents { get; } = []; + public ObservableCollection TodaySessions { get; } = []; public bool HasPlans => Plans.Count > 0; public bool HasSelectedPlan => _currentPlan is not null; @@ -42,10 +45,12 @@ public partial class SeatingPlanTabViewModel : ObservableObject public Func>? OnConfirmDelete { get; set; } public Func? OnAssessStudent { get; set; } public Action? OnAssessmentChanged { get; set; } + public Action? OnDocumentationChanged { get; set; } public SeatingPlanTabViewModel(ISeatingPlanRepository plans, IStudentRepository students, IGroupMembershipRepository memberships, IParticipationSessionRepository sessions, - IParticipationRepository participation, IParticipationAspectRepository aspects) + IParticipationRepository participation, IParticipationAspectRepository aspects, + IDocumentationRepository? documentation = null) { _plans = plans; _students = students; @@ -53,6 +58,7 @@ public partial class SeatingPlanTabViewModel : ObservableObject _sessions = sessions; _participation = participation; _aspects = aspects; + _documentation = documentation; } public SeatingPlanDialogViewModel CreateDialogViewModel(SeatingPlan? plan) => @@ -63,12 +69,31 @@ public partial class SeatingPlanTabViewModel : ObservableObject _groupId = groupId; _isReadOnly = isReadOnly; IsEditMode = false; + LoadTodaySessions(); LoadStudentOptions(); ReloadPlans(); OnPropertyChanged(nameof(IsEditable)); NotifyCommands(); } + private void LoadTodaySessions() + { + TodaySessions.Clear(); + var today = DateOnly.FromDateTime(DateTime.Today); + var sessions = _sessions.GetByGroup(_groupId).Where(s => s.Date == today) + .OrderBy(s => s.CreatedAt).ToList(); + if (sessions.Count == 0 && !_isReadOnly) + { + var created = new ParticipationSession { GroupId = _groupId, Date = today, Comment = "Sitzplan" }; + _sessions.Save(created); + sessions.Add(created); + } + foreach (var session in sessions) TodaySessions.Add(new ParticipationSessionOption(session)); + SelectedSession = TodaySessions.LastOrDefault(); + } + + partial void OnSelectedSessionChanged(ParticipationSessionOption? value) => RefreshSeatLessonData(); + private void LoadStudentOptions() { StudentOptions.Clear(); @@ -133,14 +158,78 @@ public partial class SeatingPlanTabViewModel : ObservableObject ? StudentSeatOption.Empty : StudentOptions.FirstOrDefault(o => o.StudentId == assignment.StudentId) ?? StudentSeatOption.Empty; - Seats.Add(new SeatCellViewModel(row, column, StudentOptions, option, OnSeatChanged, CanEditLayout)); + Seats.Add(new SeatCellViewModel(row, column, StudentOptions, option, OnSeatChanged, + CanEditLayout, ToggleSituationTag, IsEditable)); } UpdateAssignmentSummary(); + RefreshSeatLessonData(); } OnPropertyChanged(nameof(HasSelectedPlan)); NotifyCommands(); } + private void RefreshSeatLessonData() + { + if (SelectedSession is null) + { + foreach (var seat in Seats) seat.SetLessonData(null, []); + return; + } + var entries = _participation.GetBySession(SelectedSession.Id) + .ToDictionary(e => e.StudentId); + foreach (var seat in Seats) + { + if (seat.SelectedOption.StudentId is not Guid studentId) + { + seat.SetLessonData(null, []); + continue; + } + entries.TryGetValue(studentId, out var entry); + var tags = _documentation?.GetByStudent(studentId) + .FirstOrDefault(d => d.IsDraft && d.ParticipationSessionId == SelectedSession.Id)?.Tags ?? []; + seat.SetLessonData(entry, tags); + } + } + + private void ToggleSituationTag(SeatCellViewModel seat, string tag) + { + if (!IsEditable || _documentation is null || SelectedSession is null || + seat.SelectedOption.StudentId is not Guid studentId) return; + var draft = _documentation.GetByStudent(studentId) + .FirstOrDefault(d => d.IsDraft && d.ParticipationSessionId == SelectedSession.Id); + if (draft is null) + { + draft = new Documentation + { + StudentId = studentId, GroupId = _groupId, + ParticipationSessionId = SelectedSession.Id, + LessonId = SelectedSession.LessonId, + Type = DocumentationType.Incident, + Date = SelectedSession.Date, + Title = tag, + IsDraft = true, + Tags = [tag], + }; + } + else if (draft.Tags.Contains(tag)) + { + draft.Tags.Remove(tag); + if (draft.Tags.Count == 0) + { + _documentation.Delete(draft.Id); + RefreshSeatLessonData(); + OnDocumentationChanged?.Invoke(); + return; + } + draft.Title = draft.Tags[0]; + } + else draft.Tags.Add(tag); + draft.UpdatedAt = DateTime.UtcNow; + _documentation.Save(draft); + RefreshSeatLessonData(); + OnDocumentationChanged?.Invoke(); + } + private void OnSeatChanged(SeatCellViewModel changed) { if (_currentPlan is null || !CanEditLayout) return; @@ -209,8 +298,10 @@ public partial class SeatingPlanTabViewModel : ObservableObject { if (!seat.SelectedOption.StudentId.HasValue || OnAssessStudent is null) return; var assessment = new SeatAssessmentViewModel(_sessions, _participation, _aspects, - _groupId, seat.SelectedOption.StudentId.Value, seat.SelectedOption.DisplayName, IsEditable); + _groupId, seat.SelectedOption.StudentId.Value, seat.SelectedOption.DisplayName, IsEditable, + SelectedSession?.Id); await OnAssessStudent(assessment); + RefreshSeatLessonData(); OnAssessmentChanged?.Invoke(); } @@ -241,7 +332,11 @@ public partial class SeatingPlanTabViewModel : ObservableObject partial void OnIsEditModeChanged(bool value) { OnPropertyChanged(nameof(CanEditLayout)); - foreach (var seat in Seats) seat.CanEdit = CanEditLayout; + foreach (var seat in Seats) + { + seat.CanEdit = CanEditLayout; + seat.CanRecordLesson = IsEditable && !value; + } NotifyCommands(); } @@ -275,10 +370,21 @@ public sealed record StudentSeatOption(Guid? StudentId, string DisplayName) public static StudentSeatOption Empty { get; } = new(null, "— frei —"); } +public sealed class ParticipationSessionOption(ParticipationSession session) +{ + public Guid Id => session.Id; + public Guid? LessonId => session.LessonId; + public DateOnly Date => session.Date; + public string DisplayName => string.IsNullOrWhiteSpace(session.Comment) + ? $"{session.Date:dd.MM.yyyy}" + : $"{session.Date:dd.MM.yyyy} · {session.Comment}"; +} + public partial class SeatCellViewModel : ObservableObject { private readonly Action _onChanged; private bool _suppressChange; + private readonly Action _toggleSituationTag; [ObservableProperty] private StudentSeatOption _selectedOption; [ObservableProperty] private bool _isDropTarget; @@ -287,11 +393,20 @@ public partial class SeatCellViewModel : ObservableObject public string PositionLabel => $"Reihe {Row + 1} · Platz {Column + 1}"; public ObservableCollection Options { get; } [ObservableProperty] private bool _canEdit; + [ObservableProperty] private double _lessonOpacity = 1.0; + [ObservableProperty] private string _attendanceBadge = ""; + [ObservableProperty] private string _homeworkBadge = ""; + public ObservableCollection SituationTags { get; } = []; + public bool HasAttendanceBadge => AttendanceBadge.Length > 0; + public bool HasHomeworkBadge => HomeworkBadge.Length > 0; + public bool ShowLessonOverview => IsOccupied && !CanEdit; + [ObservableProperty] private bool _canRecordLesson; public bool IsOccupied => SelectedOption.StudentId.HasValue; public string StudentName => IsOccupied ? SelectedOption.DisplayName : "Freier Platz"; public SeatCellViewModel(int row, int column, ObservableCollection options, - StudentSeatOption selectedOption, Action onChanged, bool canEdit) + StudentSeatOption selectedOption, Action onChanged, bool canEdit, + Action? toggleSituationTag = null, bool canRecordLesson = false) { Row = row; Column = column; @@ -299,21 +414,54 @@ public partial class SeatCellViewModel : ObservableObject _selectedOption = selectedOption; _onChanged = onChanged; _canEdit = canEdit; + _toggleSituationTag = toggleSituationTag ?? ((_, _) => { }); + _canRecordLesson = canRecordLesson; + foreach (var tag in SituationTagChoice.DefaultTags) + SituationTags.Add(new SituationTagChoice(tag, false, value => _toggleSituationTag(this, value))); } partial void OnSelectedOptionChanged(StudentSeatOption value) { OnPropertyChanged(nameof(IsOccupied)); OnPropertyChanged(nameof(StudentName)); + OnPropertyChanged(nameof(ShowLessonOverview)); if (!_suppressChange) _onChanged(this); } + partial void OnCanEditChanged(bool value) => OnPropertyChanged(nameof(ShowLessonOverview)); + public void SetSelectionSilently(StudentSeatOption option) { _suppressChange = true; SelectedOption = option; _suppressChange = false; } + + public void SetLessonData(ParticipationEntry? entry, IEnumerable tags) + { + var attendance = entry?.Attendance; + AttendanceBadge = attendance is null ? "" : AttendanceDisplay.ShortLabel(attendance); + HomeworkBadge = entry is null ? "" : HomeworkDisplay.Symbol(HomeworkDisplay.Effective(entry)); + LessonOpacity = attendance is not null and not AttendanceStatus.Present + and not AttendanceStatus.Late and not AttendanceStatus.SignificantlyLate ? 0.42 : 1.0; + var selected = tags.ToHashSet(StringComparer.OrdinalIgnoreCase); + foreach (var choice in SituationTags) choice.IsSelected = selected.Contains(choice.Text); + OnPropertyChanged(nameof(HasAttendanceBadge)); + OnPropertyChanged(nameof(HasHomeworkBadge)); + } +} + +public partial class SituationTagChoice(string text, bool isSelected, Action toggle) : ObservableObject +{ + public static readonly string[] DefaultTags = + [ + "Mitarbeit verweigert", "Unterricht gestört", "Streit/Konflikt", + "Langer Toilettengang", "Material vergessen", "Handynutzung", + "Besonders hilfsbereit", "Sehr gute Mitarbeit", "Gespräch erforderlich", + ]; + public string Text { get; } = text; + [ObservableProperty] private bool _isSelected = isSelected; + [RelayCommand] private void Toggle() => toggle(Text); } public partial class SeatAssessmentViewModel : ObservableObject @@ -338,13 +486,14 @@ public partial class SeatAssessmentViewModel : ObservableObject public SeatAssessmentViewModel(IParticipationSessionRepository sessions, IParticipationRepository entries, IParticipationAspectRepository aspects, - Guid groupId, Guid studentId, string studentName, bool canEdit) + Guid groupId, Guid studentId, string studentName, bool canEdit, Guid? sessionId = null) { _entries = entries; _canEdit = canEdit; StudentName = studentName; var today = DateOnly.FromDateTime(DateTime.Today); - var session = sessions.GetByGroup(groupId).FirstOrDefault(s => s.Date == today); + var session = sessionId.HasValue ? sessions.GetById(sessionId.Value) : null; + session ??= sessions.GetByGroup(groupId).FirstOrDefault(s => s.Date == today); if (session is null && canEdit) { session = new ParticipationSession diff --git a/LehrerApp.Desktop/ViewModels/Students/DocumentationViewModels.cs b/LehrerApp.Desktop/ViewModels/Students/DocumentationViewModels.cs index 32cd0b1..e1b15ae 100644 --- a/LehrerApp.Desktop/ViewModels/Students/DocumentationViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Students/DocumentationViewModels.cs @@ -339,6 +339,9 @@ public partial class DocumentationDialogViewModel : ObservableObject Result.Date = date; Result.Title = Title.Trim(); Result.Content = (Content ?? "").Trim(); + // Das bewusste Speichern im vollständigen Dialog schließt einen im Sitzplan erzeugten + // Schnellentwurf ab. Stunden- und Lesson-Bezug bleiben am bestehenden Objekt erhalten. + Result.IsDraft = false; Result.IsConfidential = IsConfidential; Result.Participants = type == DocumentationType.Conversation ? Participants.ToList() : []; Result.AbsenceData = type == DocumentationType.Absence @@ -421,6 +424,7 @@ public partial class DocumentationItem : ObservableObject public bool IsConfidential { get; } public bool IsParentCall { get; } public bool HasAttachments { get; } + public bool IsDraft { get; } public string StatusLabel { get; } public List TagChips { get; } /// Nur im Gruppen-Tab (5.1, GroupDocumentationTabViewModel) gefüllt — die Schüler-Detailansicht @@ -446,6 +450,7 @@ public partial class DocumentationItem : ObservableObject IsRevealed = !d.IsConfidential; IsParentCall = d.Type == DocumentationType.ParentCall; HasAttachments = d.Attachments.Count > 0; + IsDraft = d.IsDraft; StatusLabel = BuildStatusLabel(d); TagChips = d.Tags.Select(t => new TagChip(t)).ToList(); StudentName = studentName; @@ -455,6 +460,7 @@ public partial class DocumentationItem : ObservableObject private static string BuildStatusLabel(Documentation d) => d.Type switch { + _ when d.IsDraft => "Nacharbeiten", DocumentationType.ParentCall when d.ParentCallData is { IsConducted: true } pc => $"Durchgeführt am {pc.ConductedDate:dd.MM.yyyy}", DocumentationType.ParentCall => "Noch nicht durchgeführt", diff --git a/LehrerApp.Desktop/Views/Groups/GroupDocumentationTabView.axaml b/LehrerApp.Desktop/Views/Groups/GroupDocumentationTabView.axaml index 2f37531..7c06e9b 100644 --- a/LehrerApp.Desktop/Views/Groups/GroupDocumentationTabView.axaml +++ b/LehrerApp.Desktop/Views/Groups/GroupDocumentationTabView.axaml @@ -7,7 +7,7 @@ - + -