Details Lerngruppe, Archiv, Stub Import

This commit is contained in:
2026-08-11 17:54:10 +02:00
parent 7a1f89cd4a
commit fd715dd5a5
11 changed files with 281 additions and 40 deletions
+2 -2
View File
@@ -13,8 +13,8 @@ public interface IStudentRepository
public interface IGroupRepository public interface IGroupRepository
{ {
LearningGroup? GetById(Guid id); LearningGroup? GetById(Guid id);
List<LearningGroup> GetAll(); List<LearningGroup> GetAll(bool includeInactive = false);
List<LearningGroup> GetBySchoolYear(string schoolYear); List<LearningGroup> GetBySchoolYear(string schoolYear, bool includeInactive = false);
void Save(LearningGroup group); void Save(LearningGroup group);
void Delete(Guid id); void Delete(Guid id);
} }
+1
View File
@@ -11,6 +11,7 @@ public class LearningGroup
public int GradeLevel { get; set; } public int GradeLevel { get; set; }
public GradingSystem GradingSystem { get; set; } public GradingSystem GradingSystem { get; set; }
public int? HoursPerWeek { get; set; } public int? HoursPerWeek { get; set; }
public bool IsActive { get; set; } = true;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
} }
+15
View File
@@ -16,6 +16,7 @@ public class LiteDbContext : IDisposable
{ {
Connection = ConnectionType.Shared, Connection = ConnectionType.Shared,
}); });
MigrateExistingData();
EnsureIndexes(); EnsureIndexes();
} }
@@ -38,11 +39,25 @@ public class LiteDbContext : IDisposable
public void Checkpoint() => _db.Checkpoint(); public void Checkpoint() => _db.Checkpoint();
private void MigrateExistingData()
{
var groups = _db.GetCollection<BsonDocument>("groups");
var missingArchiveState = groups.FindAll()
.Where(g => !g.ContainsKey(nameof(LearningGroup.IsActive)))
.ToList();
foreach (var group in missingArchiveState)
{
group[nameof(LearningGroup.IsActive)] = true;
groups.Update(group);
}
}
private void EnsureIndexes() private void EnsureIndexes()
{ {
Students.EnsureIndex(x => x.LastName); Students.EnsureIndex(x => x.LastName);
Students.EnsureIndex(x => x.IsActive); Students.EnsureIndex(x => x.IsActive);
Groups.EnsureIndex(x => x.SchoolYear); Groups.EnsureIndex(x => x.SchoolYear);
Groups.EnsureIndex(x => x.IsActive);
Enrollments.EnsureIndex(x => x.StudentId); Enrollments.EnsureIndex(x => x.StudentId);
Enrollments.EnsureIndex(x => x.GroupId); Enrollments.EnsureIndex(x => x.GroupId);
Enrollments.EnsureIndex(x => x.SchoolYear); Enrollments.EnsureIndex(x => x.SchoolYear);
+45 -5
View File
@@ -23,12 +23,52 @@ public class StudentRepository(LiteDbContext db) : IStudentRepository
public class GroupRepository(LiteDbContext db) : IGroupRepository public class GroupRepository(LiteDbContext db) : IGroupRepository
{ {
public LearningGroup? GetById(Guid id) => db.Groups.FindById(id); public LearningGroup? GetById(Guid id) => db.Groups.FindById(id);
public List<LearningGroup> GetAll() => public List<LearningGroup> GetAll(bool includeInactive = false) =>
db.Groups.FindAll().OrderBy(g => g.SchoolYear).ThenBy(g => g.Name).ToList(); (includeInactive ? db.Groups.FindAll() : db.Groups.Find(g => g.IsActive))
public List<LearningGroup> GetBySchoolYear(string schoolYear) => .OrderBy(g => g.SchoolYear).ThenBy(g => g.Name).ToList();
db.Groups.Find(g => g.SchoolYear == schoolYear).OrderBy(g => g.Name).ToList(); public List<LearningGroup> GetBySchoolYear(string schoolYear, bool includeInactive = false) =>
(includeInactive
? db.Groups.Find(g => g.SchoolYear == schoolYear)
: db.Groups.Find(g => g.SchoolYear == schoolYear && g.IsActive))
.OrderBy(g => g.Name).ToList();
public void Save(LearningGroup g) { g.UpdatedAt = DateTime.UtcNow; db.Groups.Upsert(g); } public void Save(LearningGroup g) { g.UpdatedAt = DateTime.UtcNow; db.Groups.Upsert(g); }
public void Delete(Guid id) => db.Groups.Delete(id); public void Delete(Guid id)
{
foreach (var enrollment in db.Enrollments.Find(e => e.GroupId == id).ToList())
db.Enrollments.Delete(enrollment.Id);
foreach (var exam in db.Exams.Find(e => e.GroupId == id).ToList())
{
foreach (var result in db.ExamResults.Find(r => r.ExamId == exam.Id).ToList())
db.ExamResults.Delete(result.Id);
db.Exams.Delete(exam.Id);
}
foreach (var grade in db.Grades.Find(g => g.GroupId == id).ToList())
db.Grades.Delete(grade.Id);
foreach (var unit in db.Units.Find(u => u.GroupId == id).ToList())
{
foreach (var lesson in db.Lessons.Find(l => l.UnitId == unit.Id).ToList())
db.Lessons.Delete(lesson.Id);
db.Units.Delete(unit.Id);
}
foreach (var lesson in db.Lessons.Find(l => l.GroupId == id).ToList())
db.Lessons.Delete(lesson.Id);
foreach (var session in db.ParticipationSessions.Find(s => s.GroupId == id).ToList())
{
foreach (var entry in db.ParticipationEntries.Find(e => e.SessionId == session.Id).ToList())
db.ParticipationEntries.Delete(entry.Id);
db.ParticipationSessions.Delete(session.Id);
}
foreach (var aspect in db.ParticipationAspects.Find(a => a.GroupId == id).ToList())
db.ParticipationAspects.Delete(aspect.Id);
db.Groups.Delete(id);
}
} }
public class EnrollmentRepository(LiteDbContext db) : IEnrollmentRepository public class EnrollmentRepository(LiteDbContext db) : IEnrollmentRepository
@@ -16,13 +16,23 @@ public partial class GroupListViewModel : ObservableObject
public Action<Guid, int>? OnNavigateToDetail { get; set; } public Action<Guid, int>? OnNavigateToDetail { get; set; }
public Func<Task>? OnAddGroup { get; set; } public Func<Task>? OnAddGroup { get; set; }
public Func<Guid, Task>? OnEditGroup { get; set; }
public Func<GroupListItem, Task<bool>>? OnConfirmDelete { get; set; }
[ObservableProperty] private string _selectedSchoolYear = ""; [ObservableProperty] private string _selectedSchoolYear = "";
[ObservableProperty] private string _searchText = ""; [ObservableProperty] private string _searchText = "";
[ObservableProperty] private GroupListItem? _selectedGroup; [ObservableProperty] private GroupListItem? _selectedGroup;
[ObservableProperty] private bool _showArchived;
public string SelectedGroupDisplayName => SelectedGroup?.DisplayName ?? ""; public string SelectedGroupDisplayName => SelectedGroup?.DisplayName ?? "";
public string SelectedGroupSubtitle => SelectedGroup?.Subtitle ?? ""; public string SelectedGroupSubtitle => SelectedGroup?.Subtitle ?? "";
public string ListSummary => ShowArchived
? $"{Groups.Count} archivierte Gruppen · {SelectedSchoolYear}"
: $"{Groups.Count} aktive Gruppen · {SelectedSchoolYear}";
public bool HasNoGroups => Groups.Count == 0;
public string EmptyListMessage => ShowArchived
? "Keine archivierten Lerngruppen in diesem Schuljahr."
: "Noch keine aktiven Lerngruppen in diesem Schuljahr.";
public ObservableCollection<string> SchoolYears { get; } = []; public ObservableCollection<string> SchoolYears { get; } = [];
public ObservableCollection<GroupListItem> Groups { get; } = []; public ObservableCollection<GroupListItem> Groups { get; } = [];
@@ -36,22 +46,32 @@ public partial class GroupListViewModel : ObservableObject
partial void OnSelectedSchoolYearChanged(string value) => LoadGroups(); partial void OnSelectedSchoolYearChanged(string value) => LoadGroups();
partial void OnSearchTextChanged(string value) => LoadGroups(); partial void OnSearchTextChanged(string value) => LoadGroups();
partial void OnShowArchivedChanged(bool value) => LoadGroups();
partial void OnSelectedGroupChanged(GroupListItem? value) partial void OnSelectedGroupChanged(GroupListItem? value)
{ {
OnPropertyChanged(nameof(SelectedGroupDisplayName)); OnPropertyChanged(nameof(SelectedGroupDisplayName));
OnPropertyChanged(nameof(SelectedGroupSubtitle)); OnPropertyChanged(nameof(SelectedGroupSubtitle));
NavigateToSectionCommand.NotifyCanExecuteChanged(); NavigateToSectionCommand.NotifyCanExecuteChanged();
EditGroupCommand.NotifyCanExecuteChanged();
ToggleArchiveCommand.NotifyCanExecuteChanged();
DeleteGroupCommand.NotifyCanExecuteChanged();
} }
public void LoadGroups() public void LoadGroups()
{ {
var selectedId = SelectedGroup?.Id;
Groups.Clear(); Groups.Clear();
var all = _groups.GetBySchoolYear(SelectedSchoolYear); var all = _groups.GetBySchoolYear(SelectedSchoolYear, includeInactive: ShowArchived)
.Where(g => g.IsActive != ShowArchived);
var filtered = string.IsNullOrWhiteSpace(SearchText) ? all var filtered = string.IsNullOrWhiteSpace(SearchText) ? all
: all.Where(g => g.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase) : all.Where(g => g.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase)
|| (g.Subject?.Contains(SearchText, StringComparison.OrdinalIgnoreCase) ?? false)); || (g.Subject?.Contains(SearchText, StringComparison.OrdinalIgnoreCase) ?? false));
foreach (var g in filtered.OrderBy(g => g.Name)) foreach (var g in filtered.OrderBy(g => g.Name))
Groups.Add(new GroupListItem(g)); Groups.Add(new GroupListItem(g));
SelectedGroup = Groups.FirstOrDefault(g => g.Id == selectedId);
OnPropertyChanged(nameof(ListSummary));
OnPropertyChanged(nameof(HasNoGroups));
OnPropertyChanged(nameof(EmptyListMessage));
} }
[RelayCommand] [RelayCommand]
@@ -63,6 +83,37 @@ public partial class GroupListViewModel : ObservableObject
} }
[RelayCommand] private void Refresh() => LoadGroups(); [RelayCommand] private void Refresh() => LoadGroups();
[RelayCommand(CanExecute = nameof(HasSelectedGroup))]
private async Task EditGroup()
{
if (SelectedGroup is null || OnEditGroup is null) return;
var id = SelectedGroup.Id;
await OnEditGroup(id);
LoadGroups();
SelectedGroup = Groups.FirstOrDefault(g => g.Id == id);
}
[RelayCommand(CanExecute = nameof(HasSelectedGroup))]
private void ToggleArchive()
{
if (SelectedGroup is null) return;
var group = _groups.GetById(SelectedGroup.Id);
if (group is null) return;
group.IsActive = !group.IsActive;
_groups.Save(group);
LoadGroups();
}
[RelayCommand(CanExecute = nameof(HasSelectedGroup))]
private async Task DeleteGroup()
{
if (SelectedGroup is null || OnConfirmDelete is null) return;
var selected = SelectedGroup;
if (!await OnConfirmDelete(selected)) return;
_groups.Delete(selected.Id);
LoadGroups();
}
[RelayCommand(CanExecute = nameof(HasSelectedGroup))] [RelayCommand(CanExecute = nameof(HasSelectedGroup))]
private void NavigateToSection(string? tabIndex) private void NavigateToSection(string? tabIndex)
{ {
@@ -82,10 +133,13 @@ public class GroupListItem
public string TypeLabel { get; } public string TypeLabel { get; }
public string GradingLabel { get; } public string GradingLabel { get; }
public string Subtitle { get; } public string Subtitle { get; }
public bool IsActive { get; }
public string ArchiveActionLabel => IsActive ? "Archivieren" : "Wieder aktivieren";
public GroupListItem(LearningGroup g) public GroupListItem(LearningGroup g)
{ {
Id = g.Id; Id = g.Id;
IsActive = g.IsActive;
Name = g.Name; Name = g.Name;
Subject = g.Subject ?? ""; Subject = g.Subject ?? "";
TypeLabel = g.Type == GroupType.Class ? "Klasse" : "Kurs"; TypeLabel = g.Type == GroupType.Class ? "Klasse" : "Kurs";
@@ -340,7 +394,10 @@ public partial class AddGroupDialogViewModel : ObservableObject
private readonly IGroupRepository _groups; private readonly IGroupRepository _groups;
private readonly ISubjectRepository _subjects; private readonly ISubjectRepository _subjects;
private readonly SchoolYearService _sy; private readonly SchoolYearService _sy;
private readonly IEnrollmentRepository _enrollments;
private List<Subject> _allSubjects = []; private List<Subject> _allSubjects = [];
private LearningGroup? _editingGroup;
private string? _originalSchoolYear;
public List<string> TypeOptions { get; } = ["Klasse", "Kurs"]; public List<string> TypeOptions { get; } = ["Klasse", "Kurs"];
[ObservableProperty] private string _selectedTypeName = "Kurs"; [ObservableProperty] private string _selectedTypeName = "Kurs";
@@ -359,17 +416,22 @@ public partial class AddGroupDialogViewModel : ObservableObject
[ObservableProperty] private string _name = ""; [ObservableProperty] private string _name = "";
[ObservableProperty] private string _subject = ""; [ObservableProperty] private string _subject = "";
[ObservableProperty] private int _gradeLevel = 10; [ObservableProperty] private int _gradeLevel = 10;
[ObservableProperty] private GradingSystem _gradingSystem = GradingSystem.Grades1To6; [ObservableProperty] private string _selectedGradingName = "Noten 16";
[ObservableProperty] private string _selectedSchoolYear = ""; [ObservableProperty] private string _selectedSchoolYear = "";
[ObservableProperty] private int? _hoursPerWeek;
[ObservableProperty] private string _validationMessage = ""; [ObservableProperty] private string _validationMessage = "";
public List<string> SchoolYears { get; } public List<string> SchoolYears { get; }
public List<string> GradingOptions { get; } = ["Noten 16", "Punkte 015"];
public List<string> KnownSubjectNames { get; private set; } = []; public List<string> KnownSubjectNames { get; private set; } = [];
public LearningGroup? Result { get; private set; } public LearningGroup? Result { get; private set; }
public string DialogTitle => _editingGroup is null ? "Neue Lerngruppe anlegen" : "Lerngruppe bearbeiten";
public string SaveButtonText => _editingGroup is null ? "Anlegen" : "Speichern";
public AddGroupDialogViewModel(IGroupRepository groups, ISubjectRepository subjects, SchoolYearService sy) public AddGroupDialogViewModel(IGroupRepository groups, ISubjectRepository subjects,
SchoolYearService sy, IEnrollmentRepository enrollments)
{ {
_groups = groups; _subjects = subjects; _sy = sy; _groups = groups; _subjects = subjects; _sy = sy; _enrollments = enrollments;
_allSubjects = subjects.GetAll(); _allSubjects = subjects.GetAll();
KnownSubjectNames = _allSubjects.Select(s => s.Name).ToList(); KnownSubjectNames = _allSubjects.Select(s => s.Name).ToList();
SchoolYears = sy.RecentSchoolYears(3); SchoolYears = sy.RecentSchoolYears(3);
@@ -377,11 +439,26 @@ public partial class AddGroupDialogViewModel : ObservableObject
PropertyChanged += (_, e) => PropertyChanged += (_, e) =>
{ {
if (e.PropertyName == nameof(GradeLevel)) if (e.PropertyName == nameof(GradeLevel))
GradingSystem = GradeLevel >= 11 ? GradingSystem.Points0To15 SelectedGradingName = GradeLevel >= 11 ? "Punkte 015" : "Noten 16";
: GradingSystem.Grades1To6;
}; };
} }
public void LoadForEdit(LearningGroup group)
{
_editingGroup = group;
_originalSchoolYear = group.SchoolYear;
SelectedTypeName = group.Type == GroupType.Class ? "Klasse" : "Kurs";
Name = group.Name;
Subject = group.Subject ?? "";
GradeLevel = group.GradeLevel;
SelectedGradingName = group.GradingSystem == GradingSystem.Grades1To6
? "Noten 16" : "Punkte 015";
SelectedSchoolYear = group.SchoolYear;
HoursPerWeek = group.HoursPerWeek;
OnPropertyChanged(nameof(DialogTitle));
OnPropertyChanged(nameof(SaveButtonText));
}
[RelayCommand] [RelayCommand]
private void Save() private void Save()
{ {
@@ -407,16 +484,25 @@ public partial class AddGroupDialogViewModel : ObservableObject
} }
} }
Result = new LearningGroup Result = _editingGroup ?? new LearningGroup();
{ Result.Name = Name.Trim();
Name = Name.Trim(), Result.Subject = subjectName;
Subject = subjectName, Result.SubjectId = subjectId;
SubjectId = subjectId, Result.Type = IsKurs ? GroupType.Course : GroupType.Class;
Type = IsKurs ? GroupType.Course : GroupType.Class, Result.GradeLevel = GradeLevel;
GradeLevel = GradeLevel, Result.GradingSystem = SelectedGradingName == "Punkte 015"
GradingSystem = GradingSystem, ? GradingSystem.Points0To15 : GradingSystem.Grades1To6;
SchoolYear = SelectedSchoolYear, Result.SchoolYear = SelectedSchoolYear;
}; Result.HoursPerWeek = HoursPerWeek;
_groups.Save(Result); _groups.Save(Result);
if (_editingGroup is not null && _originalSchoolYear != SelectedSchoolYear)
{
foreach (var enrollment in _enrollments.GetByGroup(Result.Id))
{
enrollment.SchoolYear = SelectedSchoolYear;
_enrollments.Save(enrollment);
}
}
} }
} }
@@ -34,7 +34,7 @@ public partial class MainWindowViewModel : ObservableObject
ActiveNavItem = item; ActiveNavItem = item;
CurrentPage = item switch CurrentPage = item switch
{ {
NavItem.Dashboard => _services.GetRequiredService<DashboardViewModel>(), NavItem.Dashboard => GetDashboard(),
NavItem.Groups => _services.GetRequiredService<GroupListViewModel>(), NavItem.Groups => _services.GetRequiredService<GroupListViewModel>(),
NavItem.Students => _services.GetRequiredService<StudentListViewModel>(), NavItem.Students => _services.GetRequiredService<StudentListViewModel>(),
NavItem.Exams => new PlaceholderViewModel { Title = "Klausuren", Icon = "📝" }, NavItem.Exams => new PlaceholderViewModel { Title = "Klausuren", Icon = "📝" },
@@ -45,6 +45,13 @@ public partial class MainWindowViewModel : ObservableObject
}; };
} }
private DashboardViewModel GetDashboard()
{
var dashboard = _services.GetRequiredService<DashboardViewModel>();
dashboard.RefreshCommand.Execute(null);
return dashboard;
}
public void NavigateToGroupDetail(Guid groupId, int initialTab = 0) public void NavigateToGroupDetail(Guid groupId, int initialTab = 0)
{ {
ActiveNavItem = NavItem.Groups; ActiveNavItem = NavItem.Groups;
@@ -3,13 +3,13 @@
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups" xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
x:Class="LehrerApp.Desktop.Views.Groups.AddGroupDialog" x:Class="LehrerApp.Desktop.Views.Groups.AddGroupDialog"
x:DataType="vm:AddGroupDialogViewModel" x:DataType="vm:AddGroupDialogViewModel"
Title="Neue Lerngruppe" Title="{Binding DialogTitle}"
Width="420" SizeToContent="Height" Width="420" SizeToContent="Height"
CanResize="False" WindowStartupLocation="CenterOwner"> CanResize="False" WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="*,Auto" Margin="24"> <Grid RowDefinitions="*,Auto" Margin="24">
<StackPanel Grid.Row="0" Spacing="14"> <StackPanel Grid.Row="0" Spacing="14">
<TextBlock Text="Neue Lerngruppe anlegen" FontSize="18" FontWeight="SemiBold"/> <TextBlock Text="{Binding DialogTitle}" FontSize="18" FontWeight="SemiBold"/>
<!-- Typ: Klasse oder Kurs --> <!-- Typ: Klasse oder Kurs -->
<StackPanel Spacing="4"> <StackPanel Spacing="4">
@@ -49,13 +49,28 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Bewertungssystem" FontSize="12" Opacity="0.7"/>
<ComboBox ItemsSource="{Binding GradingOptions}"
SelectedItem="{Binding SelectedGradingName}"
HorizontalAlignment="Stretch"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="Wochenstunden (optional)" FontSize="12" Opacity="0.7"/>
<NumericUpDown Value="{Binding HoursPerWeek}" Minimum="1" Maximum="40" FormatString="0"
HorizontalAlignment="Stretch"/>
</StackPanel>
</Grid>
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12" <TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/> IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel> </StackPanel>
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0"> <Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0">
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/> <Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
<Button Grid.Column="2" Content="Anlegen" HorizontalAlignment="Stretch" Click="OnSave"/> <Button Grid.Column="2" Content="{Binding SaveButtonText}"
HorizontalAlignment="Stretch" Click="OnSave"/>
</Grid> </Grid>
</Grid> </Grid>
</Window> </Window>
@@ -0,0 +1,20 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="LehrerApp.Desktop.Views.Groups.DeleteGroupDialog"
x:CompileBindings="False"
Title="Lerngruppe löschen"
Width="430" SizeToContent="Height"
CanResize="False" WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="*,Auto" Margin="24">
<StackPanel Grid.Row="0" Spacing="12">
<TextBlock Text="Lerngruppe wirklich löschen?" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="{Binding}" FontSize="15" FontWeight="SemiBold" TextWrapping="Wrap"/>
<TextBlock Text="Dabei werden auch Einschreibungen, Klausuren, Noten, Unterrichtsplanung und Mitarbeitseinträge dieser Lerngruppe dauerhaft gelöscht. Wenn du die Gruppe nur ausblenden möchtest, nutze stattdessen das Archiv."
TextWrapping="Wrap" Opacity="0.7"/>
</StackPanel>
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0">
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
<Button Grid.Column="2" Content="Endgültig löschen" HorizontalAlignment="Stretch" Click="OnDelete"/>
</Grid>
</Grid>
</Window>
@@ -0,0 +1,12 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace LehrerApp.Desktop.Views.Groups;
public partial class DeleteGroupDialog : Window
{
public DeleteGroupDialog() => InitializeComponent();
private void OnDelete(object? sender, RoutedEventArgs e) => Close(true);
private void OnCancel(object? sender, RoutedEventArgs e) => Close(false);
}
@@ -13,11 +13,7 @@
<Grid ColumnDefinitions="*,Auto,Auto"> <Grid ColumnDefinitions="*,Auto,Auto">
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0">
<TextBlock Text="Lerngruppen" FontSize="22" FontWeight="SemiBold"/> <TextBlock Text="Lerngruppen" FontSize="22" FontWeight="SemiBold"/>
<TextBlock FontSize="12" Opacity="0.5"> <TextBlock Text="{Binding ListSummary}" FontSize="12" Opacity="0.5"/>
<Run Text="{Binding Groups.Count}"/>
<Run Text=" Gruppen · "/>
<Run Text="{Binding SelectedSchoolYear}"/>
</TextBlock>
</StackPanel> </StackPanel>
<ComboBox Grid.Column="1" ItemsSource="{Binding SchoolYears}" <ComboBox Grid.Column="1" ItemsSource="{Binding SchoolYears}"
SelectedItem="{Binding SelectedSchoolYear}" SelectedItem="{Binding SelectedSchoolYear}"
@@ -35,8 +31,13 @@
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}" BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,1,0"> BorderThickness="0,0,1,0">
<DockPanel> <DockPanel>
<TextBox DockPanel.Dock="Top" Text="{Binding SearchText}" <StackPanel DockPanel.Dock="Top" Margin="12,8" Spacing="8">
PlaceholderText="Suchen…" Margin="12,8"/> <TextBox Text="{Binding SearchText}" PlaceholderText="Suchen…"/>
<ToggleSwitch Content="Archiv anzeigen" IsChecked="{Binding ShowArchived}"/>
</StackPanel>
<TextBlock Text="{Binding EmptyListMessage}" TextWrapping="Wrap"
Margin="16,12" FontSize="12" Opacity="0.45"
IsVisible="{Binding HasNoGroups}"/>
<ListBox ItemsSource="{Binding Groups}" <ListBox ItemsSource="{Binding Groups}"
SelectedItem="{Binding SelectedGroup}"> SelectedItem="{Binding SelectedGroup}">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
@@ -79,12 +80,31 @@
<StackPanel Margin="28,24" Spacing="20"> <StackPanel Margin="28,24" Spacing="20">
<!-- Gruppenname und Kurzinfos --> <!-- Gruppenname und Kurzinfos -->
<StackPanel Spacing="4"> <Grid ColumnDefinitions="*,Auto">
<TextBlock Text="{Binding SelectedGroupDisplayName}" <StackPanel Grid.Column="0" Spacing="4">
FontSize="24" FontWeight="SemiBold" TextWrapping="Wrap"/> <TextBlock Text="{Binding SelectedGroupDisplayName}"
<TextBlock Text="{Binding SelectedGroupSubtitle}" FontSize="24" FontWeight="SemiBold" TextWrapping="Wrap"/>
FontSize="12" Opacity="0.55"/> <TextBlock Text="{Binding SelectedGroupSubtitle}"
</StackPanel> FontSize="12" Opacity="0.55"/>
</StackPanel>
<Button Grid.Column="1" Content="⋯ Verwalten" VerticalAlignment="Top"
Margin="16,0,0,0">
<Button.Flyout>
<MenuFlyout>
<MenuItem Header="Details bearbeiten"
Command="{Binding EditGroupCommand}"/>
<MenuItem Header="{Binding SelectedGroup.ArchiveActionLabel}"
Command="{Binding ToggleArchiveCommand}"/>
<Separator/>
<MenuItem Header="Teilnehmer importieren (bald)" IsEnabled="False"
ToolTip.Tip="Import aus dem Teilnehmerexport der Lernplattform folgt."/>
<Separator/>
<MenuItem Header="Lerngruppe löschen"
Command="{Binding DeleteGroupCommand}"/>
</MenuFlyout>
</Button.Flyout>
</Button>
</Grid>
<Separator/> <Separator/>
@@ -12,7 +12,11 @@ public partial class GroupListView : UserControl
{ {
base.OnDataContextChanged(e); base.OnDataContextChanged(e);
if (DataContext is GroupListViewModel vm) if (DataContext is GroupListViewModel vm)
{
vm.OnAddGroup = ShowAddGroupDialog; vm.OnAddGroup = ShowAddGroupDialog;
vm.OnEditGroup = ShowEditGroupDialog;
vm.OnConfirmDelete = ShowDeleteGroupDialog;
}
} }
private async Task ShowAddGroupDialog() private async Task ShowAddGroupDialog()
@@ -23,4 +27,25 @@ public partial class GroupListView : UserControl
if (owner is not null) if (owner is not null)
await dialog.ShowDialog(owner); await dialog.ShowDialog(owner);
} }
private async Task ShowEditGroupDialog(Guid groupId)
{
var group = App.Services.GetRequiredService<LehrerApp.Core.Interfaces.IGroupRepository>()
.GetById(groupId);
if (group is null) return;
var dialogVm = App.Services.GetRequiredService<AddGroupDialogViewModel>();
dialogVm.LoadForEdit(group);
var dialog = new AddGroupDialog { DataContext = dialogVm };
var owner = TopLevel.GetTopLevel(this) as Window;
if (owner is not null)
await dialog.ShowDialog<bool>(owner);
}
private async Task<bool> ShowDeleteGroupDialog(GroupListItem group)
{
var dialog = new DeleteGroupDialog { DataContext = group.DisplayName };
var owner = TopLevel.GetTopLevel(this) as Window;
return owner is not null && await dialog.ShowDialog<bool>(owner);
}
} }