Notenverwaltung (Kapitel 2) und Mitarbeits-Assistent
Notenübersicht der Gruppe (Matrix, Gesamt-Spalte, Sortierung, Halbjahresfilter), Einzelnoten-Pflege samt Sammelerfassung, Gewichtungsschema mit Voreinstellung je Gruppentyp, Zeugnisnoten-Berechnung mit Übersteuern/Festschreiben/Export und Notenentwicklung im Schülerdetail. Dazu Anwesenheits-/Hausaufgaben-Tracking je Mitarbeit-Sitzung, ein neuer Mitarbeits-Assistent (Zeitleiste mit Abschnitten, automatischer Notenvorschlag, Zusammenzug zur Halbjahresnote) und eine Dashboard-Kachel für offene Entschuldigungen. Außerdem: verbliebene englische Begriffe in Auswahlfeldern und Buttons auf Deutsch umgestellt.
This commit is contained in:
@@ -28,6 +28,7 @@ public partial class ParticipationTabViewModel : ObservableObject
|
||||
public Guid GroupId => _groupId;
|
||||
public string SchoolYear => _schoolYear;
|
||||
public GradingSystem GradingSystem => _gradingSystem;
|
||||
public string GroupLabel { get; private set; } = "";
|
||||
|
||||
[ObservableProperty] private ParticipationSessionItem? _selectedSession;
|
||||
[ObservableProperty] private string _noDataText = "Keine Bewertungssitzung ausgewählt.";
|
||||
@@ -47,6 +48,7 @@ public partial class ParticipationTabViewModel : ObservableObject
|
||||
public Func<Task<ParticipationSession?>>? OnAddSession { get; set; }
|
||||
public Func<ParticipationTabViewModel, Task>? OnQuickInput { get; set; }
|
||||
public Func<ParticipationTabViewModel, Task>? OnComputeGrade { get; set; }
|
||||
public Func<ParticipationTabViewModel, Task>? OnOpenWizard { get; set; }
|
||||
|
||||
public ParticipationTabViewModel(
|
||||
IParticipationSessionRepository sessions,
|
||||
@@ -72,6 +74,7 @@ public partial class ParticipationTabViewModel : ObservableObject
|
||||
_subjectId = group?.SubjectId;
|
||||
_gradeLevel = group?.GradeLevel ?? 0;
|
||||
_gradingSystem = group?.GradingSystem ?? GradingSystem.Grades1To6;
|
||||
GroupLabel = group?.Name ?? "";
|
||||
|
||||
HasCompetencyCatalog = _subjectId.HasValue
|
||||
&& _competencyDomains.GetBySubjectAndGrade(_subjectId.Value, _gradeLevel).Count > 0;
|
||||
@@ -143,6 +146,8 @@ public partial class ParticipationTabViewModel : ObservableObject
|
||||
var row = new ParticipationStudentRow(s.Id, s.FullName, entry, Aspects.ToList(), ActiveCompetencyCodes);
|
||||
row.OnRatingChanged = (sid, key, val) => SaveRating(sessionId, sid, key, val);
|
||||
row.OnCompetencyRatingChanged = (sid, code, val) => SaveCompetencyRating(sessionId, sid, code, val);
|
||||
row.HomeworkChangedCallback = (sid, val) => SaveHomework(sessionId, sid, val);
|
||||
row.AttendanceChangedCallback = (sid, val) => SaveAttendance(sessionId, sid, val);
|
||||
StudentRows.Add(row);
|
||||
}
|
||||
QuickInputCommand.NotifyCanExecuteChanged();
|
||||
@@ -185,6 +190,22 @@ public partial class ParticipationTabViewModel : ObservableObject
|
||||
if (SelectedSession is not null) LoadGrid(SelectedSession.Id);
|
||||
}
|
||||
|
||||
private void SaveHomework(Guid sessionId, Guid studentId, bool value)
|
||||
{
|
||||
var entry = _entries.GetBySessionAndStudent(sessionId, studentId)
|
||||
?? new ParticipationEntry { SessionId = sessionId, StudentId = studentId };
|
||||
entry.HomeworkMissing = value;
|
||||
_entries.Save(entry);
|
||||
}
|
||||
|
||||
private void SaveAttendance(Guid sessionId, Guid studentId, AttendanceStatus? value)
|
||||
{
|
||||
var entry = _entries.GetBySessionAndStudent(sessionId, studentId)
|
||||
?? new ParticipationEntry { SessionId = sessionId, StudentId = studentId };
|
||||
entry.Attendance = value;
|
||||
_entries.Save(entry);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ToggleCompetencyTags() => CompetencyTagsVisible = !CompetencyTagsVisible;
|
||||
|
||||
@@ -259,6 +280,13 @@ public partial class ParticipationTabViewModel : ObservableObject
|
||||
await OnComputeGrade(this);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task OpenWizard()
|
||||
{
|
||||
if (OnOpenWizard is null) return;
|
||||
await OnOpenWizard(this);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void DeleteSession()
|
||||
{
|
||||
@@ -310,8 +338,16 @@ public partial class ParticipationStudentRow : ObservableObject
|
||||
public ObservableCollection<RatingCell> Cells { get; } = [];
|
||||
public ObservableCollection<RatingCell> CompetencyCells { get; } = [];
|
||||
|
||||
[ObservableProperty] private bool _homeworkMissing;
|
||||
[ObservableProperty] private AttendanceStatus? _attendance;
|
||||
|
||||
public string AttendanceLabel => AttendanceDisplay.ShortLabel(Attendance);
|
||||
public string AttendanceTooltip => AttendanceDisplay.Label(Attendance);
|
||||
|
||||
public Action<Guid, string, int?>? OnRatingChanged { get; set; }
|
||||
public Action<Guid, string, int?>? OnCompetencyRatingChanged { get; set; }
|
||||
public Action<Guid, bool>? HomeworkChangedCallback { get; set; }
|
||||
public Action<Guid, AttendanceStatus?>? AttendanceChangedCallback { get; set; }
|
||||
|
||||
public ParticipationStudentRow(Guid id, string name, ParticipationEntry entry,
|
||||
List<AspectColumnDef> aspects, List<string> competencyCodes)
|
||||
@@ -320,6 +356,8 @@ public partial class ParticipationStudentRow : ObservableObject
|
||||
Name = name;
|
||||
_entry = entry;
|
||||
_aspectDefs = aspects;
|
||||
_homeworkMissing = entry.HomeworkMissing;
|
||||
_attendance = entry.Attendance;
|
||||
|
||||
foreach (var a in aspects)
|
||||
{
|
||||
@@ -347,6 +385,61 @@ public partial class ParticipationStudentRow : ObservableObject
|
||||
cell?.SetValue(value);
|
||||
OnRatingChanged?.Invoke(StudentId, key, value);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ToggleHomework()
|
||||
{
|
||||
HomeworkMissing = !HomeworkMissing;
|
||||
HomeworkChangedCallback?.Invoke(StudentId, HomeworkMissing);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void CycleAttendance()
|
||||
{
|
||||
Attendance = Attendance switch
|
||||
{
|
||||
null => AttendanceStatus.ExcusePending,
|
||||
AttendanceStatus.ExcusePending => AttendanceStatus.Excused,
|
||||
AttendanceStatus.Excused => AttendanceStatus.Unexcused,
|
||||
AttendanceStatus.Unexcused => null,
|
||||
_ => null,
|
||||
};
|
||||
OnPropertyChanged(nameof(AttendanceLabel));
|
||||
OnPropertyChanged(nameof(AttendanceTooltip));
|
||||
AttendanceChangedCallback?.Invoke(StudentId, Attendance);
|
||||
}
|
||||
|
||||
// Direktes Setzen (z.B. aus dem Grading-Wizard heraus), ohne den Zyklus zu durchlaufen.
|
||||
public void SetAttendance(AttendanceStatus? value)
|
||||
{
|
||||
Attendance = value;
|
||||
OnPropertyChanged(nameof(AttendanceLabel));
|
||||
OnPropertyChanged(nameof(AttendanceTooltip));
|
||||
AttendanceChangedCallback?.Invoke(StudentId, value);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Anwesenheits-Anzeige ──────────────────────────────────────────────────────
|
||||
|
||||
public static class AttendanceDisplay
|
||||
{
|
||||
public static string Label(AttendanceStatus? s) => s switch
|
||||
{
|
||||
null => "Anwesend",
|
||||
AttendanceStatus.ExcusePending => "Krank (Entschuldigung offen)",
|
||||
AttendanceStatus.Excused => "Krank, entschuldigt",
|
||||
AttendanceStatus.Unexcused => "Krank, unentschuldigt",
|
||||
_ => "Anwesend",
|
||||
};
|
||||
|
||||
public static string ShortLabel(AttendanceStatus? s) => s switch
|
||||
{
|
||||
null => "",
|
||||
AttendanceStatus.ExcusePending => "K ?",
|
||||
AttendanceStatus.Excused => "K ✓",
|
||||
AttendanceStatus.Unexcused => "K ✗",
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
|
||||
// ── Eine Bewertungszelle ──────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user