Files
adminandClaude Opus 5.5 aa326cf8b6
CI / build-and-test (push) Canceled after 0s
Add warning detail popup and quick blocks for Vorgänge
Dashboard warnings (attendance, homework, lateness) get a "Details" flyout
with key figures, a list of dates and the compact month calendar from the
class teacher overview, now extracted as a shared control. The calendar
now aligns days under their weekday (Mo-So header, blank leading cells).

Creating Vorgänge and documentation is supported by quick blocks with the
current figures, dated standard phrases (e.g. "Klassenleitung informiert")
and documentation templates (status snapshot, conversation, informing the
class/subject teachers, parent call, parent letter). The class teacher
Vorgänge tab uses WebUntis figures (absences across all subjects, class
register) for the same blocks and templates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 11:16:13 +02:00

79 lines
3.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections;
using System.Collections.Specialized;
using Avalonia;
using Avalonia.Controls;
using LehrerApp.Desktop.ViewModels.ClassTeacher;
namespace LehrerApp.Desktop.Views.Shared;
/// <summary>Eine Rasterzelle des kompakten Monatskalenders; <see cref="Day"/> ist null für die
/// Leerzellen vor dem Monatsersten.</summary>
public sealed record CompactMonthCell(ClassTeacherCompactCalendarDay? Day)
{
public bool IsPlaceholder => Day is null;
public bool IsDay => Day is not null;
}
/// <summary>Kompakter Monatskalender (eine Zelle je Tag, Statuskürzel statt Tageszahl) — erwartet
/// <see cref="ClassTeacherCompactCalendarDay"/>-Einträge in <see cref="Days"/>, genau einen je
/// Kalendertag ab dem Monatsersten. Genutzt von der Klassenlehrer-Übersicht und dem Detail-Popup der
/// Dashboard-Warnungen.
/// Nutzer-Feedback: vorher begann jeder Monat oben links, der 1. stand also unabhängig vom
/// Wochentag in der Montags-Spalte. Die Ausrichtung passiert bewusst hier in der Anzeige (Leerzellen
/// vor dem Monatsersten + Kopfzeile Mo–So) statt in den beiden Buildern — deren Ergebnis bleibt
/// "ein Eintrag je Kalendertag" und damit für Tests/Aufrufer unverändert.</summary>
public partial class CompactMonthCalendar : UserControl
{
public static readonly StyledProperty<IEnumerable?> DaysProperty =
AvaloniaProperty.Register<CompactMonthCalendar, IEnumerable?>(nameof(Days));
public static readonly DirectProperty<CompactMonthCalendar, IReadOnlyList<CompactMonthCell>> CellsProperty =
AvaloniaProperty.RegisterDirect<CompactMonthCalendar, IReadOnlyList<CompactMonthCell>>(nameof(Cells), c => c.Cells);
public static string[] WeekdayHeaders { get; } = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];
private IReadOnlyList<CompactMonthCell> _cells = [];
private INotifyCollectionChanged? _observed;
public IEnumerable? Days
{
get => GetValue(DaysProperty);
set => SetValue(DaysProperty, value);
}
public IReadOnlyList<CompactMonthCell> Cells
{
get => _cells;
private set => SetAndRaise(CellsProperty, ref _cells, value);
}
public CompactMonthCalendar() => InitializeComponent();
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property != DaysProperty) return;
// Beide Aufrufer befüllen eine ObservableCollection per Clear/Add neu (Monat blättern,
// Schülerauswahl) — deshalb auf Änderungen der Sammlung selbst lauschen, nicht nur auf
// einen neuen Days-Wert.
if (_observed is not null) _observed.CollectionChanged -= OnDaysCollectionChanged;
_observed = Days as INotifyCollectionChanged;
if (_observed is not null) _observed.CollectionChanged += OnDaysCollectionChanged;
RebuildCells();
}
private void OnDaysCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) => RebuildCells();
private void RebuildCells() => Cells = BuildCells(Days?.OfType<ClassTeacherCompactCalendarDay>() ?? []);
public static IReadOnlyList<CompactMonthCell> BuildCells(IEnumerable<ClassTeacherCompactCalendarDay> days)
{
var list = days.ToList();
if (list.Count == 0) return [];
var leading = ((int)list[0].Date.DayOfWeek + 6) % 7; // Montag = 0 … Sonntag = 6
return Enumerable.Repeat(new CompactMonthCell(null), leading)
.Concat(list.Select(d => new CompactMonthCell(d)))
.ToList();
}
}