This commit is contained in:
@@ -392,6 +392,14 @@ public sealed record ClassTeacherOpenExcuseRow(string StudentName, DateOnly Date
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>Eine einzelne, auf ein Minimum verdichtete Monatszelle im Übersichts-Widget.</summary>
|
||||
public sealed record ClassTeacherCompactCalendarDay(DateOnly Date, string SignalCode,
|
||||
string SignalColorHex, string Tooltip, bool IsToday)
|
||||
{
|
||||
public string DayNumber => Date.Day.ToString();
|
||||
public bool HasSignal => !string.IsNullOrEmpty(SignalCode);
|
||||
}
|
||||
|
||||
public partial class ClassTeacherOverviewViewModel : ObservableObject
|
||||
{
|
||||
private readonly WebUntisSettingsService _settings;
|
||||
@@ -415,6 +423,7 @@ public partial class ClassTeacherOverviewViewModel : ObservableObject
|
||||
public ObservableCollection<ClassTeacherTrendDay> TrendDays { get; } = [];
|
||||
public ObservableCollection<ClassTeacherPatternNotice> PatternNotices { get; } = [];
|
||||
public ObservableCollection<ClassTeacherOpenExcuseRow> OpenExcuses { get; } = [];
|
||||
public ObservableCollection<ClassTeacherCompactCalendarDay> CompactMonthDays { get; } = [];
|
||||
|
||||
[ObservableProperty] private string? _homeroomClassName;
|
||||
[ObservableProperty] private int _activeTabIndex;
|
||||
@@ -492,6 +501,8 @@ public partial class ClassTeacherOverviewViewModel : ObservableObject
|
||||
public double UnexcusedAbsenceFraction => StudentCount == 0 ? 0 : (double)UnexcusedAbsenceCount / StudentCount;
|
||||
public string DayOverviewTooltip => $"{PresentCount} anwesend · {LateCount} verspätet · " +
|
||||
$"{ExcusedAbsenceCount} entschuldigt · {UnexcusedAbsenceCount} unentschuldigt";
|
||||
public string CompactMonthLabel => DateOnly.FromDateTime(DateTime.Today).ToString("MMMM yyyy",
|
||||
System.Globalization.CultureInfo.GetCultureInfo("de-DE"));
|
||||
|
||||
public Func<Task>? OnNavigateToSettings { get; set; }
|
||||
public Func<Task>? OnNavigateToWorkload { get; set; }
|
||||
@@ -537,7 +548,7 @@ public partial class ClassTeacherOverviewViewModel : ObservableObject
|
||||
{
|
||||
ActiveTabIndex = 0;
|
||||
Roster.Clear(); PrimaryRoster.Clear(); SecondaryRoster.Clear(); TrendDays.Clear(); PatternNotices.Clear();
|
||||
OpenExcuses.Clear(); OpenExcuseOverflowCount = 0;
|
||||
OpenExcuses.Clear(); CompactMonthDays.Clear(); OpenExcuseOverflowCount = 0;
|
||||
}
|
||||
|
||||
// Wird beim Navigieren auf diese Seite aufgerufen statt LoadCommand: baut nur den lokalen
|
||||
@@ -676,6 +687,7 @@ public partial class ClassTeacherOverviewViewModel : ObservableObject
|
||||
UnexcusedAbsenceCount = Roster.Count(r => r.HasAbsenceToday && !r.IsLate && r.IsUnexcused);
|
||||
RecentClassRegisterCount = recentRegisterEntries.Count;
|
||||
BuildTrend(absenceDaysYear, trendDays);
|
||||
BuildCompactMonth(absenceDaysYear, classRegisterEvents, today);
|
||||
BuildPatternNotices(absenceDaysYear, sevenDayStart);
|
||||
BuildWeekdayPatternNotices(absenceDaysYear);
|
||||
BuildAttendanceParticipationNotices();
|
||||
@@ -708,6 +720,64 @@ public partial class ClassTeacherOverviewViewModel : ObservableObject
|
||||
DetailsTab.LoadCommand.Execute(null);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenMonthlyCalendar()
|
||||
{
|
||||
var today = DateOnly.FromDateTime(DateTime.Today);
|
||||
DetailsTab.StudentFilter = "";
|
||||
DetailsTab.CalendarMonth = new DateOnly(today.Year, today.Month, 1);
|
||||
ActiveTabIndex = 2;
|
||||
DetailsTab.ShowCalendarCommand.Execute(null);
|
||||
}
|
||||
|
||||
private void BuildCompactMonth(IReadOnlyList<ClassAbsenceDaySummaryRow> absences,
|
||||
IReadOnlyList<UntisForeignClassRegisterEventDto> registerEntries, DateOnly today)
|
||||
{
|
||||
CompactMonthDays.Clear();
|
||||
foreach (var day in BuildCompactMonthDays(new DateOnly(today.Year, today.Month, 1),
|
||||
absences, registerEntries, today))
|
||||
CompactMonthDays.Add(day);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<ClassTeacherCompactCalendarDay> BuildCompactMonthDays(DateOnly month,
|
||||
IReadOnlyList<ClassAbsenceDaySummaryRow> absences,
|
||||
IReadOnlyList<UntisForeignClassRegisterEventDto> registerEntries, DateOnly today)
|
||||
{
|
||||
var first = new DateOnly(month.Year, month.Month, 1);
|
||||
var registerRows = registerEntries
|
||||
.Select(e => (Entry: e, Valid: TryDate(e.Date, out var date), Date: date))
|
||||
.Where(x => x.Valid && x.Date.Year == first.Year && x.Date.Month == first.Month)
|
||||
.Select(x => new ClassTeacherClassRegisterRow(x.Date, x.Entry.Subject, x.Entry.StudentName,
|
||||
x.Entry.TeacherUsername, x.Entry.CategoryName, x.Entry.CategoryGroup, x.Entry.Text))
|
||||
.ToList();
|
||||
var result = new List<ClassTeacherCompactCalendarDay>();
|
||||
var days = DateTime.DaysInMonth(first.Year, first.Month);
|
||||
|
||||
for (var number = 1; number <= days; number++)
|
||||
{
|
||||
var date = new DateOnly(first.Year, first.Month, number);
|
||||
var events = ClassTeacherDetailsViewModel.BuildDayEvents(date, absences, registerRows,
|
||||
includeHomework: false);
|
||||
var strongest = events.OrderBy(e => SignalPriority(e.Kind)).FirstOrDefault();
|
||||
var tooltip = events.Count == 0
|
||||
? $"{date:dd.MM.yyyy}: unauffällig"
|
||||
: $"{date:dd.MM.yyyy}\n" + string.Join("\n", events.Select(e => e.Tooltip));
|
||||
result.Add(new ClassTeacherCompactCalendarDay(date, strongest?.Code ?? "",
|
||||
strongest?.ColorHex ?? "#00000000", tooltip, date == today));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int SignalPriority(ClassTeacherCalendarEventKind kind) => kind switch
|
||||
{
|
||||
ClassTeacherCalendarEventKind.Unexcused => 0,
|
||||
ClassTeacherCalendarEventKind.ClassRegister => 1,
|
||||
ClassTeacherCalendarEventKind.Absent => 2,
|
||||
ClassTeacherCalendarEventKind.Late => 3,
|
||||
ClassTeacherCalendarEventKind.Excused => 4,
|
||||
_ => 5,
|
||||
};
|
||||
|
||||
[RelayCommand]
|
||||
private void ShowDetailsForStudent(ClassTeacherRosterRow? row)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user