Files
LehrerApp/LehrerApp.Desktop/Views/Settings/SettingsView.axaml
T
admin 0800832ae5 Klausurtermine im Kalender (4.4.3) + Stundenplan: Ausnahme eintragen, Zahnrad-Settings-Link
- 4.4.3: Box "ANSTEHENDE KLAUSUREN" im Heute-Tab, gruppenübergreifend, nächste 21 Tage.
  IExamRepository um GetAll() erweitert.
- Nutzer-Feedback: "Vertretung eintragen" deckt auch Ausfall/Sondereinsatz ab, daher
  umbenannt in "Ausnahme eintragen". "Stundenplan bearbeiten" (redundant zum Bearbeiten-Tab)
  ersetzt durch Zahnrad-Button, der direkt in die Einstellungen springt.
2026-08-15 22:24:04 +02:00

636 lines
35 KiB
XML
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.
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Settings"
xmlns:shared="clr-namespace:LehrerApp.Desktop.Views.Shared"
x:Class="LehrerApp.Desktop.Views.Settings.SettingsView"
x:DataType="vm:SettingsViewModel">
<Grid RowDefinitions="Auto,*">
<shared:PageHeader Grid.Row="0" Title="Einstellungen" Margin="32,28,32,0"/>
<TabbedPage Grid.Row="1" TabPlacement="Top" SelectedIndex="{Binding ActiveTabIndex}">
<!-- Tab: Fächer -->
<ContentPage Header="Fächer">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="640">
<ItemsControl ItemsSource="{Binding Subjects}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:SubjectListItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,7">
<Grid ColumnDefinitions="*,80,Auto">
<TextBlock Grid.Column="0" Text="{Binding Name}"
VerticalAlignment="Center" FontSize="14"/>
<TextBlock Grid.Column="1" Text="{Binding ShortName}"
VerticalAlignment="Center" Opacity="0.5" FontSize="13"/>
<Button Grid.Column="2" Content="Löschen" FontSize="12" Padding="10,4"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).DeleteSubjectCommand}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,12">
<StackPanel Spacing="10">
<TextBlock Text="Neues Fach" FontSize="12" FontWeight="SemiBold" Opacity="0.7"/>
<Grid ColumnDefinitions="*,12,100,12,Auto">
<TextBox Grid.Column="0" Text="{Binding NewName}"
PlaceholderText="Name (z.B. Chemie)"/>
<TextBox Grid.Column="2" Text="{Binding NewShort}"
PlaceholderText="Kürzel (z.B. Ch)"/>
<Button Grid.Column="4" Content="Hinzufügen"
Command="{Binding AddSubjectCommand}"/>
</Grid>
<TextBlock Text="{Binding NewNameError}" Foreground="Red" FontSize="12"
IsVisible="{Binding NewNameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Kürzel-Katalog -->
<ContentPage Header="Kürzel-Katalog">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="640">
<TextBlock Text="Kürzel für den Stundenverlaufsplan (Kapitel 4.2), z.B. Tb = Tafelbild. Im Stundeneditor werden Von/Nach aus diesen Kürzeln zu einem Kurzsymbol wie &quot;Tb-&gt;SH&quot; kombiniert."
FontSize="12" Opacity="0.6" TextWrapping="Wrap"/>
<ItemsControl ItemsSource="{Binding ShorthandCodes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:ShorthandCodeListItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,7">
<Grid ColumnDefinitions="80,*,Auto">
<TextBlock Grid.Column="0" Text="{Binding Code}"
VerticalAlignment="Center" FontSize="14" FontWeight="SemiBold"/>
<TextBlock Grid.Column="1" Text="{Binding Label}"
VerticalAlignment="Center" Opacity="0.7" FontSize="13"/>
<Button Grid.Column="2" Content="Löschen" FontSize="12" Padding="10,4"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).DeleteShorthandCodeCommand}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,12">
<StackPanel Spacing="10">
<TextBlock Text="Neues Kürzel" FontSize="12" FontWeight="SemiBold" Opacity="0.7"/>
<Grid ColumnDefinitions="100,12,*,12,Auto">
<TextBox Grid.Column="0" Text="{Binding NewShorthandCode}"
PlaceholderText="Kürzel (z.B. Tb)"/>
<TextBox Grid.Column="2" Text="{Binding NewShorthandLabel}"
PlaceholderText="Bedeutung (z.B. Tafelbild)"/>
<Button Grid.Column="4" Content="Hinzufügen"
Command="{Binding AddShorthandCodeCommand}"/>
</Grid>
<TextBlock Text="{Binding NewShorthandCodeError}" Foreground="Red" FontSize="12"
IsVisible="{Binding NewShorthandCodeError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Kompetenzen -->
<ContentPage Header="Kompetenzen">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="640">
<!-- Fach + Klassenstufe Auswahl + Import/Export -->
<Grid ColumnDefinitions="*,12,120,12,Auto,8,Auto">
<ComboBox Grid.Column="0"
ItemsSource="{Binding Subjects}"
SelectedItem="{Binding CatalogSubject}"
PlaceholderText="Fach auswählen"
HorizontalAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate DataType="vm:SubjectListItem">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<NumericUpDown Grid.Column="2"
Value="{Binding CatalogGradeLevel}"
Minimum="1" Maximum="13" FormatString="0"/>
<Button Grid.Column="4" Content="JSON importieren" Click="OnImportClick"
IsEnabled="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<Button Grid.Column="6" Content="JSON exportieren" Click="OnExportClick"
IsEnabled="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNotNull}}"/>
</Grid>
<!-- Katalog-Validierungsmeldung -->
<TextBlock Text="{Binding CatalogValidation}" Foreground="Red" FontSize="12"
IsVisible="{Binding CatalogValidation, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<!-- Leerer Zustand -->
<TextBlock Text="Kein Fach ausgewählt." Classes="emptyhint"
IsVisible="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNull}}"/>
<!-- Domain-Liste -->
<ItemsControl ItemsSource="{Binding Domains}"
IsVisible="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNotNull}}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:DomainEditItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="6" Margin="0,0,0,8" Padding="14,12">
<StackPanel Spacing="8">
<!-- Bereichs-Header -->
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="{Binding DisplayName}"
FontWeight="SemiBold" FontSize="14" VerticalAlignment="Center"/>
<Button Grid.Column="1" Content="Bereich löschen" FontSize="12" Padding="10,4"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).DeleteDomainCommand}"
CommandParameter="{Binding}"/>
</Grid>
<!-- Kompetenz-Items -->
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:CompetencyItemVm">
<Grid ColumnDefinitions="*,Auto" Margin="0,3">
<TextBlock Grid.Column="0" Text="{Binding Display}"
TextWrapping="Wrap" VerticalAlignment="Center"
FontSize="13"/>
<Button Grid.Column="1" Content="×" Padding="7,2" FontSize="13"
Command="{Binding DeleteCommand}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Kompetenz hinzufügen -->
<Grid ColumnDefinitions="80,8,*,8,Auto">
<TextBox Grid.Column="0" Text="{Binding NewItemCode}"
PlaceholderText="EG1" FontSize="12"/>
<TextBox Grid.Column="2" Text="{Binding NewItemDesc}"
PlaceholderText="Kompetenz-Beschreibung" FontSize="12"/>
<Button Grid.Column="4" Content=""
Command="{Binding AddItemCommand}"/>
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Neuen Bereich hinzufügen -->
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,12"
IsVisible="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel Spacing="10">
<TextBlock Text="Neuer Bereich" FontSize="12" FontWeight="SemiBold" Opacity="0.7"/>
<Grid ColumnDefinitions="*,12,90,12,Auto">
<TextBox Grid.Column="0" Text="{Binding NewDomainName}"
PlaceholderText="Bereichsname (z.B. Erkenntnisgewinnung)"/>
<TextBox Grid.Column="2" Text="{Binding NewDomainCode}"
PlaceholderText="Kürzel (z.B. EG)"/>
<Button Grid.Column="4" Content="Hinzufügen"
Command="{Binding AddDomainCommand}"/>
</Grid>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Notenschlüssel-Vorlagen -->
<ContentPage Header="Notenschlüssel-Vorlagen">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="640">
<TextBlock Text="Noch keine Vorlagen angelegt." Classes="emptyhint"
IsVisible="{Binding !GradingKeyTemplateList.Count}"/>
<ItemsControl ItemsSource="{Binding GradingKeyTemplateList}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:GradingKeyTemplateEditItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,9">
<Grid ColumnDefinitions="*,Auto,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" FontSize="14"/>
<TextBlock FontSize="12" Opacity="0.5">
<Run Text="{Binding GradingSystemLabel}"/>
<Run Text=" · "/>
<Run Text="{Binding Entries.Count}"/>
<Run Text=" Stufen"/>
</TextBlock>
<TextBlock Text="{Binding CompletenessWarning}" Foreground="Red" FontSize="11"
TextWrapping="Wrap"
IsVisible="{Binding CompletenessWarning, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<Button Grid.Column="1" Content="Bearbeiten" FontSize="12" Padding="10,4"
Margin="8,0,0,0" Tag="{Binding}" Click="OnEditGradingKeyTemplateClick"/>
<Button Grid.Column="2" Content="Löschen" FontSize="12" Padding="10,4"
Margin="8,0,0,0"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).DeleteGradingKeyTemplateCommand}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Neue Vorlage anlegen -->
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,12">
<StackPanel Spacing="10">
<TextBlock Text="Neue Vorlage" FontSize="12" FontWeight="SemiBold" Opacity="0.7"/>
<Grid ColumnDefinitions="*,12,140,12,Auto">
<TextBox Grid.Column="0" Text="{Binding NewTemplateName}"
PlaceholderText="Vorlagenname (z.B. Standard Oberstufe)"/>
<ComboBox Grid.Column="2" ItemsSource="{Binding GradingSystemOptions}"
SelectedItem="{Binding NewTemplateGradingSystemName}"
HorizontalAlignment="Stretch"/>
<Button Grid.Column="4" Content="Anlegen"
Command="{Binding AddGradingKeyTemplateCommand}"/>
</Grid>
<TextBlock Text="{Binding NewTemplateNameError}" Foreground="Red" FontSize="12"
IsVisible="{Binding NewTemplateNameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Notenschema -->
<ContentPage Header="Notenschema">
<ContentPage.Resources>
<DataTemplate x:Key="GradingSchemeTemplate" DataType="vm:GradingSchemeEditItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,12">
<StackPanel Spacing="8">
<TextBlock Text="{Binding Label}" FontWeight="SemiBold" FontSize="14"/>
<Grid ColumnDefinitions="Auto,90,Auto,90,Auto,90" ColumnSpacing="6">
<TextBlock Grid.Column="0" Text="Klausuren %" VerticalAlignment="Center" FontSize="12"/>
<NumericUpDown Grid.Column="1" Value="{Binding ExamsPercent}" Minimum="0" Maximum="100"
FormatString="0.#" ShowButtonSpinner="False"/>
<TextBlock Grid.Column="2" Text="Mitarbeit %" VerticalAlignment="Center" FontSize="12"/>
<NumericUpDown Grid.Column="3" Value="{Binding ParticipationPercent}" Minimum="0" Maximum="100"
FormatString="0.#" ShowButtonSpinner="False"/>
<TextBlock Grid.Column="4" Text="Sonstige %" VerticalAlignment="Center" FontSize="12"/>
<NumericUpDown Grid.Column="5" Value="{Binding OtherPercent}" Minimum="0" Maximum="100"
FormatString="0.#" ShowButtonSpinner="False"/>
</Grid>
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="{Binding StatusMessage}" Foreground="Green" FontSize="12"
VerticalAlignment="Center"
IsVisible="{Binding StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Button Grid.Column="1" Content="Speichern" Command="{Binding SaveCommand}"/>
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ContentPage.Resources>
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="480">
<TextBlock Text="Voreinstellung der Gewichtung für die Zeugnisnote (Klausuren / Mitarbeit / Sonstige), je Gruppentyp. Kann pro Lerngruppe überschrieben werden."
FontSize="12" Opacity="0.6" TextWrapping="Wrap"/>
<ContentControl Content="{Binding ClassScheme}" ContentTemplate="{StaticResource GradingSchemeTemplate}"/>
<ContentControl Content="{Binding CourseScheme}" ContentTemplate="{StaticResource GradingSchemeTemplate}"/>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Sicherheit (13.3) -->
<ContentPage Header="Sicherheit">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="24" MaxWidth="560">
<!-- Datensicherung -->
<StackPanel Spacing="10">
<TextBlock Text="Datensicherung" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Bei jedem Start wird automatisch ein Backup der Datenbank angelegt (die letzten 10 werden behalten)."
FontSize="12" Opacity="0.6" TextWrapping="Wrap"/>
<Button Content="Jetzt sichern" Command="{Binding CreateBackupNowCommand}"
HorizontalAlignment="Left"/>
<TextBlock Text="{Binding BackupStatus}" Foreground="Green" FontSize="12"
IsVisible="{Binding BackupStatus, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<ItemsControl ItemsSource="{Binding Backups}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:BackupListItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,7">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="{Binding Display}"
VerticalAlignment="Center" FontSize="13"/>
<Button Grid.Column="1" Content="Wiederherstellen" FontSize="12" Padding="10,4"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).RestoreBackupCommand}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Text="Noch keine Backups vorhanden." Classes="emptyhint"
IsVisible="{Binding !Backups.Count}"/>
</StackPanel>
<Separator/>
<!-- Datenbank-Verschlüsselung -->
<StackPanel Spacing="10">
<TextBlock Text="Datenbank-Verschlüsselung" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Schützt die Datenbankdatei auf der Festplatte mit einem Passwort. Ohne das Passwort kann die App die Datenbank beim Start nicht öffnen — bei Verlust sind die Daten nicht mehr zugänglich."
FontSize="12" Opacity="0.6" TextWrapping="Wrap"/>
<TextBlock FontSize="13" FontWeight="SemiBold">
<Run Text="Status: "/>
<Run Text="{Binding DbEncryptionStatusLabel}"/>
</TextBlock>
<StackPanel Spacing="4" IsVisible="{Binding IsDbEncrypted}">
<TextBlock Text="Aktuelles Passwort" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding CurrentDbPassword}" PasswordChar="●"/>
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Neues Passwort" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding NewDbPassword}" PasswordChar="●"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="Wiederholen" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding NewDbPasswordConfirm}" PasswordChar="●"/>
</StackPanel>
</Grid>
<TextBlock Text="{Binding DbPasswordError}" Foreground="Red" FontSize="12"
IsVisible="{Binding DbPasswordError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Passwort speichern" Command="{Binding SaveDbPasswordCommand}"/>
<Button Content="Verschlüsselung entfernen" Command="{Binding RemoveDbPasswordCommand}"
IsVisible="{Binding IsDbEncrypted}"/>
</StackPanel>
<TextBlock Text="Nach dem Ändern wird die App automatisch neu gestartet."
FontSize="11" Opacity="0.5"/>
</StackPanel>
<Separator/>
<!-- App-Sperre nach Inaktivität -->
<StackPanel Spacing="10">
<TextBlock Text="App-Sperre nach Inaktivität" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Sperrt die Oberfläche nach einer Zeit ohne Maus-/Tastatureingabe. Eigenes Passwort, unabhängig von der Datenbank-Verschlüsselung."
FontSize="12" Opacity="0.6" TextWrapping="Wrap"/>
<CheckBox Content="App-Sperre aktivieren" IsChecked="{Binding AppLockEnabled}"/>
<StackPanel Spacing="4" MaxWidth="200">
<TextBlock Text="Zeit bis zur Sperre (Minuten)" FontSize="12" Opacity="0.7"/>
<NumericUpDown Value="{Binding AppLockTimeoutMinutes}" Minimum="1" Maximum="120" FormatString="0"/>
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Passwort (leer lassen, um es zu behalten)" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding AppLockNewPassword}" PasswordChar="●"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="Wiederholen" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding AppLockNewPasswordConfirm}" PasswordChar="●"/>
</StackPanel>
</Grid>
<TextBlock Text="{Binding AppLockPasswordError}" Foreground="Red" FontSize="12"
IsVisible="{Binding AppLockPasswordError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Button Content="Speichern" Command="{Binding SaveAppLockSettingsCommand}" HorizontalAlignment="Left"/>
<TextBlock Text="{Binding AppLockStatus}" Foreground="Green" FontSize="12"
IsVisible="{Binding AppLockStatus, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Datenschutz (5.4.2) -->
<ContentPage Header="Datenschutz">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="640">
<TextBlock Text="Löschfristen für Dokumentationseinträge" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Einträge werden nie automatisch gelöscht — hier abgelaufene Einträge nur zur manuellen Prüfung anzeigen."
FontSize="12" Opacity="0.6" TextWrapping="Wrap"/>
<Grid ColumnDefinitions="140,Auto">
<NumericUpDown Grid.Column="0" Value="{Binding RetentionYears}" Minimum="1" Maximum="20" FormatString="0"/>
<Button Grid.Column="1" Content="Speichern" Margin="8,0,0,0"
Command="{Binding SaveRetentionYearsCommand}"/>
</Grid>
<TextBlock Text="{Binding RetentionStatus}" Foreground="Green" FontSize="12"
IsVisible="{Binding RetentionStatus, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Separator Margin="0,4"/>
<TextBlock Text="Abgelaufene Einträge" FontSize="14" FontWeight="SemiBold"/>
<ItemsControl ItemsSource="{Binding ExpiredDocuments}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:ExpiredDocumentItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,7">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock FontSize="13">
<Run Text="{Binding StudentName}"/>
<Run Text=" — "/>
<Run Text="{Binding Title}"/>
</TextBlock>
<TextBlock FontSize="11" Opacity="0.5">
<Run Text="erfasst am "/>
<Run Text="{Binding CreatedAtDisplay}"/>
</TextBlock>
</StackPanel>
<Button Grid.Column="1" Content="Endgültig löschen" FontSize="12" Padding="10,4"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).HardDeleteDocumentCommand}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Text="Keine abgelaufenen Einträge." Classes="emptyhint"
IsVisible="{Binding !ExpiredDocuments.Count}"/>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Ferien & Feiertage (4.3.5) -->
<ContentPage Header="Ferien &amp; Feiertage">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="480">
<StackPanel Spacing="4">
<TextBlock Text="Bundesland (für Feiertage)" FontSize="13" FontWeight="SemiBold"/>
<ComboBox ItemsSource="{Binding StateOptions}" SelectedItem="{Binding SelectedStateName}"
HorizontalAlignment="Stretch"/>
</StackPanel>
<Separator Margin="0,4"/>
<TextBlock Text="Schulferien" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Werden im Stundenplan als unterrichtsfreie Tage angezeigt."
FontSize="12" Opacity="0.6" TextWrapping="Wrap"/>
<ItemsControl ItemsSource="{Binding SchoolHolidayEntries}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:SchoolHolidayItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,7">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Name}" FontSize="13" FontWeight="SemiBold"/>
<TextBlock Text="{Binding RangeDisplay}" FontSize="12" Opacity="0.6"/>
</StackPanel>
<Button Grid.Column="1" Content="×" FontSize="14" Padding="9,3"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).RemoveSchoolHolidayCommand}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Text="Noch keine Schulferien hinterlegt." Classes="emptyhint"
IsVisible="{Binding !SchoolHolidayEntries.Count}"/>
<Separator Margin="0,4"/>
<StackPanel Spacing="4">
<TextBox Text="{Binding NewHolidayName}" PlaceholderText="Name (z.B. Sommerferien)"/>
<TextBlock Text="{Binding HolidayNameError}" Foreground="Red" FontSize="11"
IsVisible="{Binding HolidayNameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Grid ColumnDefinitions="*,8,*">
<TextBox Grid.Column="0" Text="{Binding NewHolidayStartText}" PlaceholderText="Beginn TT.MM.JJJJ"/>
<TextBox Grid.Column="2" Text="{Binding NewHolidayEndText}" PlaceholderText="Ende TT.MM.JJJJ"/>
</Grid>
<TextBlock Text="{Binding HolidayDateError}" Foreground="Red" FontSize="11"
IsVisible="{Binding HolidayDateError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Button Content=" Schulferien hinzufügen" Command="{Binding AddSchoolHolidayCommand}"
HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Stundenraster (4.2.2 Nachtrag) -->
<ContentPage Header="Stundenraster">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="420">
<TextBlock Text="Uhrzeiten der Einzelstunden" FontSize="16" FontWeight="SemiBold"/>
<TextBlock FontSize="12" Opacity="0.6" TextWrapping="Wrap"
Text="Grundlage für die Zeitbedarf-Rückmeldung im Verlaufsplan-Editor. Nicht alle Stunden müssen eingetragen sein — für unkonfigurierte Stunden bleibt die Rückmeldung dort einfach aus."/>
<Grid ColumnDefinitions="70,*,8,*" Margin="0,4,0,0">
<TextBlock Grid.Column="1" Text="Beginn" FontSize="11" FontWeight="Bold" Opacity="0.5"/>
<TextBlock Grid.Column="3" Text="Ende" FontSize="11" FontWeight="Bold" Opacity="0.5"/>
</Grid>
<ItemsControl ItemsSource="{Binding PeriodTimes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:PeriodTimeEditItem">
<Grid ColumnDefinitions="70,*,8,*" Margin="0,3">
<TextBlock Grid.Column="0" Text="{Binding PeriodLabel}" FontSize="13" VerticalAlignment="Center"/>
<TextBox Grid.Column="1" Text="{Binding StartText}" PlaceholderText="HH:MM"/>
<TextBox Grid.Column="3" Text="{Binding EndText}" PlaceholderText="HH:MM"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Text="{Binding PeriodTimesError}" Foreground="Red" FontSize="12"
IsVisible="{Binding PeriodTimesError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Button Content="Speichern" Command="{Binding SavePeriodTimesCommand}" HorizontalAlignment="Left"/>
<TextBlock Text="{Binding PeriodTimesStatus}" Foreground="Green" FontSize="12"
IsVisible="{Binding PeriodTimesStatus, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</ScrollViewer>
</ContentPage>
<!-- Tab: Aufsichten (4.3 Nachtrag) -->
<ContentPage Header="Aufsichten">
<ScrollViewer>
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="480">
<TextBlock Text="Wiederkehrende Pausenaufsicht" FontSize="16" FontWeight="SemiBold"/>
<TextBlock FontSize="12" Opacity="0.6" TextWrapping="Wrap"
Text="Wird im Stundenplan zwischen den betroffenen Stunden angezeigt. Einmalige Vertretungsaufsichten trägst du direkt im Stundenplan (Heute-Ansicht) ein, nicht hier."/>
<ItemsControl ItemsSource="{Binding SupervisionDuties}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:SupervisionDutyItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,7">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock FontSize="13" FontWeight="SemiBold">
<Run Text="{Binding WeekdayLabel}"/><Run Text=" — "/><Run Text="{Binding PeriodLabel}"/>
</TextBlock>
<TextBlock Text="{Binding Location}" FontSize="12" Opacity="0.6"/>
</StackPanel>
<Button Grid.Column="1" Content="×" FontSize="14" Padding="9,3"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).RemoveSupervisionDutyCommand}"
CommandParameter="{Binding}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Text="Noch keine Aufsicht hinterlegt." Classes="emptyhint"
IsVisible="{Binding !SupervisionDuties.Count}"/>
<Separator Margin="0,4"/>
<Grid ColumnDefinitions="*,8,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Wochentag" FontSize="12" Opacity="0.7"/>
<ComboBox ItemsSource="{Binding WeekdayOptions}" SelectedItem="{Binding NewDutyWeekdayName}"
HorizontalAlignment="Stretch"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="Nach Stunde (0 = davor)" FontSize="12" Opacity="0.7"/>
<NumericUpDown Value="{Binding NewDutyAfterPeriod}" Minimum="0" Maximum="10" FormatString="0"
Width="140" ShowButtonSpinner="True"/>
</StackPanel>
</Grid>
<StackPanel Spacing="4">
<TextBlock Text="Ort / Bezeichnung" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding NewDutyLocation}" PlaceholderText="z.B. Pausenhof"/>
</StackPanel>
<TextBlock Text="{Binding NewDutyError}" Foreground="Red" FontSize="12"
IsVisible="{Binding NewDutyError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Button Content=" Aufsicht hinzufügen" Command="{Binding AddSupervisionDutyCommand}"
HorizontalAlignment="Left"/>
</StackPanel>
</ScrollViewer>
</ContentPage>
</TabbedPage>
</Grid>
</UserControl>