Files
LehrerApp/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs
T

220 lines
8.6 KiB
C#
Raw 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 CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using LehrerApp.Core.Interfaces;
using LehrerApp.Core.Models;
using LehrerApp.Core.Services;
using System.Collections.ObjectModel;
namespace LehrerApp.Desktop.ViewModels.Groups;
// ── Gruppenliste ──────────────────────────────────────────────────────────────
public partial class GroupListViewModel : ObservableObject
{
private readonly IGroupRepository _groups;
private readonly SchoolYearService _sy;
public Action<Guid, int>? OnNavigateToDetail { get; set; }
public Action? OnAddGroup { get; set; }
[ObservableProperty] private string _selectedSchoolYear = "";
[ObservableProperty] private string _searchText = "";
[ObservableProperty] private GroupListItem? _selectedGroup;
public ObservableCollection<string> SchoolYears { get; } = [];
public ObservableCollection<GroupListItem> Groups { get; } = [];
public GroupListViewModel(IGroupRepository groups, SchoolYearService sy)
{
_groups = groups; _sy = sy;
foreach (var y in sy.RecentSchoolYears()) SchoolYears.Add(y);
SelectedSchoolYear = sy.CurrentSchoolYear();
}
partial void OnSelectedSchoolYearChanged(string value) => LoadGroups();
partial void OnSearchTextChanged(string value) => LoadGroups();
partial void OnSelectedGroupChanged(GroupListItem? value) =>
NavigateToSectionCommand.NotifyCanExecuteChanged();
public void LoadGroups()
{
Groups.Clear();
var all = _groups.GetBySchoolYear(SelectedSchoolYear);
var filtered = string.IsNullOrWhiteSpace(SearchText) ? all
: all.Where(g => g.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase)
|| (g.Subject?.Contains(SearchText, StringComparison.OrdinalIgnoreCase) ?? false));
foreach (var g in filtered.OrderBy(g => g.Name))
Groups.Add(new GroupListItem(g));
}
[RelayCommand] private void AddGroup() => OnAddGroup?.Invoke();
[RelayCommand] private void Refresh() => LoadGroups();
[RelayCommand(CanExecute = nameof(HasSelectedGroup))]
private void NavigateToSection(string? tabIndex)
{
if (SelectedGroup is null || !int.TryParse(tabIndex, out var tab)) return;
OnNavigateToDetail?.Invoke(SelectedGroup.Id, tab);
}
private bool HasSelectedGroup() => SelectedGroup is not null;
}
public class GroupListItem
{
public Guid Id { get; }
public string Name { get; }
public string Subject { get; }
public string DisplayName { get; }
public string TypeLabel { get; }
public string GradingLabel { get; }
public string Subtitle { get; }
public GroupListItem(LearningGroup g)
{
Id = g.Id;
Name = g.Name;
Subject = g.Subject ?? "";
TypeLabel = g.Type == GroupType.Class ? "Klasse" : "Kurs";
GradingLabel = g.GradingSystem == GradingSystem.Grades1To6 ? "16" : "015";
DisplayName = string.IsNullOrEmpty(g.Subject) ? g.Name : $"{g.Name} · {g.Subject}";
Subtitle = $"{TypeLabel} · Stufe {g.GradeLevel} · Noten {GradingLabel} · {g.SchoolYear}";
}
}
// ── Gruppendetail ─────────────────────────────────────────────────────────────
public partial class GroupDetailViewModel : ObservableObject
{
private readonly IGroupRepository _groups;
private readonly IStudentRepository _students;
private readonly IExamRepository _exams;
private readonly IGradeRepository _grades;
[ObservableProperty] private LearningGroup? _group;
[ObservableProperty] private string _groupTitle = "";
[ObservableProperty] private string _groupSubtitle = "";
[ObservableProperty] private int _studentCount;
[ObservableProperty] private int _activeTabIndex = 0;
public ObservableCollection<StudentSummary> Students { get; } = [];
public ObservableCollection<ExamSummary> Exams { get; } = [];
public GroupDetailViewModel(IGroupRepository groups, IStudentRepository students,
IExamRepository exams, IGradeRepository grades)
{
_groups = groups; _students = students; _exams = exams; _grades = grades;
}
public void LoadGroup(Guid id)
{
Group = _groups.GetById(id);
if (Group is null) return;
GroupTitle = Group.Name;
GroupSubtitle = $"{Group.SchoolYear} · " +
$"{(Group.Type == GroupType.Class ? "Klasse" : "Kurs")} · " +
$"Stufe {Group.GradeLevel} · Noten {(Group.GradingSystem == GradingSystem.Grades1To6 ? "16" : "015")}";
Students.Clear();
var enrolled = _students.GetByGroup(Group.Id, Group.SchoolYear);
StudentCount = enrolled.Count;
foreach (var s in enrolled) Students.Add(new StudentSummary(s));
Exams.Clear();
foreach (var e in _exams.GetByGroup(Group.Id)) Exams.Add(new ExamSummary(e));
}
[RelayCommand] private void AddStudent() { /* TODO */ }
[RelayCommand] private void AddExam() { /* TODO */ }
[RelayCommand] private void Refresh() { if (Group is not null) LoadGroup(Group.Id); }
}
public class StudentSummary
{
public Guid Id { get; }
public string FullName { get; }
public StudentSummary(Core.Models.Student s) { Id = s.Id; FullName = s.FullName; }
}
public class ExamSummary
{
public Guid Id { get; }
public string Title { get; }
public string Date { get; }
public string StatusLabel { get; }
public ExamSummary(Core.Models.Exam e)
{
Id = e.Id; Title = e.Title; Date = e.Date.ToString("dd.MM.yyyy");
StatusLabel = e.Status switch
{
ExamStatus.Planned => "Geplant",
ExamStatus.Conducted => "Durchgeführt",
ExamStatus.Graded => "Korrigiert",
ExamStatus.Returned => "Zurückgegeben",
_ => "",
};
}
}
// ── Dialog: Neue Lerngruppe anlegen ──────────────────────────────────────────
public partial class AddGroupDialogViewModel : ObservableObject
{
private readonly IGroupRepository _groups;
private readonly SchoolYearService _sy;
public List<string> TypeOptions { get; } = ["Klasse", "Kurs"];
[ObservableProperty] private string _selectedTypeName = "Kurs";
public bool IsKurs => SelectedTypeName == "Kurs";
public string NameLabel => IsKurs ? "Kursname *" : "Klassenname *";
public string NameHint => IsKurs ? "z.B. Q1, LK, GK" : "z.B. 10E, 5a, 11b";
partial void OnSelectedTypeNameChanged(string value)
{
OnPropertyChanged(nameof(IsKurs));
OnPropertyChanged(nameof(NameLabel));
OnPropertyChanged(nameof(NameHint));
}
[ObservableProperty] private string _name = "";
[ObservableProperty] private string _subject = "";
[ObservableProperty] private int _gradeLevel = 10;
[ObservableProperty] private GradingSystem _gradingSystem = GradingSystem.Grades1To6;
[ObservableProperty] private string _selectedSchoolYear = "";
[ObservableProperty] private string _validationMessage = "";
public List<string> SchoolYears { get; }
public LearningGroup? Result { get; private set; }
public AddGroupDialogViewModel(IGroupRepository groups, SchoolYearService sy)
{
_groups = groups; _sy = sy;
SchoolYears = sy.RecentSchoolYears(3);
SelectedSchoolYear = sy.CurrentSchoolYear();
PropertyChanged += (_, e) =>
{
if (e.PropertyName == nameof(GradeLevel))
GradingSystem = GradeLevel >= 11 ? GradingSystem.Points0To15
: GradingSystem.Grades1To6;
};
}
[RelayCommand]
private void Save()
{
if (string.IsNullOrWhiteSpace(Name)) { ValidationMessage = "Bezeichnung erforderlich."; return; }
if (GradeLevel is < 1 or > 13) { ValidationMessage = "Klassenstufe 113."; return; }
Result = new LearningGroup
{
Name = Name.Trim(),
Subject = IsKurs && !string.IsNullOrWhiteSpace(Subject) ? Subject.Trim() : null,
Type = IsKurs ? GroupType.Course : GroupType.Class,
GradeLevel = GradeLevel,
GradingSystem = GradingSystem,
SchoolYear = SelectedSchoolYear,
};
_groups.Save(Result);
}
}