Tagesflagge im Sitzplan, Leistungsüberblick mit Zielnoten-Rechner
CI / build-and-test (push) Canceled after 0s
CI / build-and-test (push) Canceled after 0s
- Mitarbeit: Tagesflagge (👑 Spitzentag / 😴 Schlaftag / ⚡ Schlechter Tag) je Schüler und Sitzung. Primär im Sitzplatz-Dialog (⇧1/2/3, ⇧X) mit Badge auf der Sitzplatz-Kachel; Fallback in der Schnelleingabe für Lerngruppen ohne Sitzplan. - Noten: neuer Dialog "Überblick" in der Notenübersicht zeigt Klausuren, Mitarbeit- und sonstige Noten eines Schülers samt berechneter Zeugnisnote. Zielnoten-Rechner (ReportGradeTargetCalculator) beantwortet "was brauche ich noch für Note X", ein Was-wäre-wenn-Rechner simuliert eine zusätzliche Klausurnote. Bewerter-/Schülermodus per Umschalter im selben Fenster — Bewertermodus zeigt zusätzlich Kursdurchschnitt je Klausur und erlaubt das Bearbeiten von Mitarbeit-/Sonstige-Noten. Klausurverlauf als Balken-Sparkline wie die bestehende Notenentwicklung. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -547,11 +547,13 @@ public partial class SeatCellViewModel : ObservableObject
|
||||
[ObservableProperty] private double _lessonOpacity = 1.0;
|
||||
[ObservableProperty] private string _attendanceBadge = "";
|
||||
[ObservableProperty] private string _homeworkBadge = "";
|
||||
[ObservableProperty] private string _dayHighlightBadge = "";
|
||||
[ObservableProperty] private int _raisedHandCount;
|
||||
[ObservableProperty] private int _calledOnCount;
|
||||
public ObservableCollection<SituationTagChoice> SituationTags { get; } = [];
|
||||
public bool HasAttendanceBadge => AttendanceBadge.Length > 0;
|
||||
public bool HasHomeworkBadge => HomeworkBadge.Length > 0;
|
||||
public bool HasDayHighlightBadge => DayHighlightBadge.Length > 0;
|
||||
public bool ShowLessonOverview => IsOccupied && !CanEdit;
|
||||
[ObservableProperty] private bool _canRecordLesson;
|
||||
public bool IsOccupied => SelectedOption.StudentId.HasValue;
|
||||
@@ -644,6 +646,7 @@ public partial class SeatCellViewModel : ObservableObject
|
||||
var attendance = entry?.Attendance;
|
||||
AttendanceBadge = attendance is null ? "" : AttendanceDisplay.ShortLabel(attendance);
|
||||
HomeworkBadge = entry is null ? "" : HomeworkDisplay.Symbol(HomeworkDisplay.Effective(entry));
|
||||
DayHighlightBadge = DayHighlightDisplay.Symbol(entry?.DayHighlight);
|
||||
RaisedHandCount = entry?.RaisedHandCount ?? 0;
|
||||
CalledOnCount = entry?.CalledOnCount ?? 0;
|
||||
LessonOpacity = attendance is not null and not AttendanceStatus.Present
|
||||
@@ -652,6 +655,7 @@ public partial class SeatCellViewModel : ObservableObject
|
||||
foreach (var choice in SituationTags) choice.IsSelected = selected.Contains(choice.Text);
|
||||
OnPropertyChanged(nameof(HasAttendanceBadge));
|
||||
OnPropertyChanged(nameof(HasHomeworkBadge));
|
||||
OnPropertyChanged(nameof(HasDayHighlightBadge));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,6 +681,7 @@ public partial class SeatAssessmentViewModel : ObservableObject
|
||||
[ObservableProperty] private int _selectedAspectIndex;
|
||||
[ObservableProperty] private string _attendanceLabel = "Noch nicht kontrolliert";
|
||||
[ObservableProperty] private string _homeworkLabel = "Keine Hausaufgabe aufgegeben";
|
||||
[ObservableProperty] private string _dayHighlightLabel = "Keine Markierung";
|
||||
|
||||
public string StudentName { get; }
|
||||
public string SessionDisplay { get; }
|
||||
@@ -687,6 +692,7 @@ public partial class SeatAssessmentViewModel : ObservableObject
|
||||
public ObservableCollection<SeatAssessmentAspectRow> AspectRows { get; } = [];
|
||||
public ObservableCollection<SeatAttendanceChoice> AttendanceChoices { get; } = [];
|
||||
public ObservableCollection<SeatHomeworkChoice> HomeworkChoices { get; } = [];
|
||||
public ObservableCollection<SeatDayHighlightChoice> DayHighlightChoices { get; } = [];
|
||||
|
||||
public SeatAssessmentViewModel(IParticipationSessionRepository sessions,
|
||||
IParticipationRepository entries, IParticipationAspectRepository aspects,
|
||||
@@ -729,6 +735,7 @@ public partial class SeatAssessmentViewModel : ObservableObject
|
||||
|
||||
BuildAttendanceChoices();
|
||||
BuildHomeworkChoices();
|
||||
BuildDayHighlightChoices();
|
||||
RefreshStatusChoices();
|
||||
SelectAspect(0);
|
||||
}
|
||||
@@ -761,6 +768,17 @@ public partial class SeatAssessmentViewModel : ObservableObject
|
||||
HomeworkChoices.Add(new("·", "Keine aufgegeben", "⌥X", null, SetHomework));
|
||||
}
|
||||
|
||||
private void BuildDayHighlightChoices()
|
||||
{
|
||||
DayHighlightChoices.Add(new(DayHighlightDisplay.Symbol(DayHighlightKind.Standout),
|
||||
DayHighlightDisplay.Label(DayHighlightKind.Standout), "⇧1", DayHighlightKind.Standout, SetDayHighlight));
|
||||
DayHighlightChoices.Add(new(DayHighlightDisplay.Symbol(DayHighlightKind.Sleepy),
|
||||
DayHighlightDisplay.Label(DayHighlightKind.Sleepy), "⇧2", DayHighlightKind.Sleepy, SetDayHighlight));
|
||||
DayHighlightChoices.Add(new(DayHighlightDisplay.Symbol(DayHighlightKind.Rough),
|
||||
DayHighlightDisplay.Label(DayHighlightKind.Rough), "⇧3", DayHighlightKind.Rough, SetDayHighlight));
|
||||
DayHighlightChoices.Add(new("·", "Keine Markierung", "⇧X", null, SetDayHighlight));
|
||||
}
|
||||
|
||||
public void SelectAspect(int index)
|
||||
{
|
||||
if (index < 0 || index >= AspectRows.Count) return;
|
||||
@@ -827,6 +845,17 @@ public partial class SeatAssessmentViewModel : ObservableObject
|
||||
if (clear || digit is 0 or 1 or 3 or 4 or 5 or 7 or 8) SetHomework(status);
|
||||
}
|
||||
|
||||
public void ApplyDayHighlightShortcut(int? digit, bool clear)
|
||||
{
|
||||
if (!CanEdit) return;
|
||||
var kind = clear ? null : digit switch
|
||||
{
|
||||
1 => DayHighlightKind.Standout, 2 => DayHighlightKind.Sleepy, 3 => DayHighlightKind.Rough,
|
||||
_ => (DayHighlightKind?)null,
|
||||
};
|
||||
if (clear || digit is 1 or 2 or 3) SetDayHighlight(kind);
|
||||
}
|
||||
|
||||
private void ApplyRating(string key, int? value)
|
||||
{
|
||||
if (!CanEdit || _entry is null) return;
|
||||
@@ -857,13 +886,23 @@ public partial class SeatAssessmentViewModel : ObservableObject
|
||||
RefreshStatusChoices();
|
||||
}
|
||||
|
||||
private void SetDayHighlight(DayHighlightKind? kind)
|
||||
{
|
||||
if (!CanEdit || _entry is null) return;
|
||||
_entry.DayHighlight = kind;
|
||||
_entries.Save(_entry);
|
||||
RefreshStatusChoices();
|
||||
}
|
||||
|
||||
private void RefreshStatusChoices()
|
||||
{
|
||||
AttendanceLabel = AttendanceDisplay.Label(_entry?.Attendance);
|
||||
HomeworkLabel = HomeworkDisplay.Label(_entry is null ? null : HomeworkDisplay.Effective(_entry));
|
||||
DayHighlightLabel = DayHighlightDisplay.Label(_entry?.DayHighlight);
|
||||
foreach (var choice in AttendanceChoices) choice.IsSelected = choice.Status == _entry?.Attendance;
|
||||
var homework = _entry is null ? null : HomeworkDisplay.Effective(_entry);
|
||||
foreach (var choice in HomeworkChoices) choice.IsSelected = choice.Status == homework;
|
||||
foreach (var choice in DayHighlightChoices) choice.IsSelected = choice.Kind == _entry?.DayHighlight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -966,6 +1005,17 @@ public partial class SeatHomeworkChoice(string symbol, string label, string shor
|
||||
[RelayCommand] private void Apply() => apply(Status);
|
||||
}
|
||||
|
||||
public partial class SeatDayHighlightChoice(string symbol, string label, string shortcut,
|
||||
DayHighlightKind? kind, Action<DayHighlightKind?> apply) : ObservableObject
|
||||
{
|
||||
public string Symbol { get; } = symbol;
|
||||
public string Label { get; } = label;
|
||||
public string Shortcut { get; } = shortcut;
|
||||
public DayHighlightKind? Kind { get; } = kind;
|
||||
[ObservableProperty] private bool _isSelected;
|
||||
[RelayCommand] private void Apply() => apply(Kind);
|
||||
}
|
||||
|
||||
public partial class SeatingPlanDialogViewModel : ObservableObject
|
||||
{
|
||||
private readonly ISeatingPlanRepository _plans;
|
||||
|
||||
Reference in New Issue
Block a user