Files
LehrerApp/LehrerApp.Desktop/Views/Groups/ReportGradeAssistantDialog.axaml
T
adminandClaude Opus 5.5 d9eac0d1d2
CI / build-and-test (push) Canceled after 0s
Zwischenstand: vorläufige Noten zu Stichtag und Anlass
Ein Zwischenstand ist ein Durchgang aus Stichtag, Anlass und
Schülerauswahl (ganze Gruppe, Teilgruppe oder Einzelfall, mit
Schnellfilter für gefährdete Schüler). Der Zeugnisnoten-Assistent geht
die gewählten Schüler im Zwischenstand-Modus durch und notiert
vorläufige schriftliche, mündliche und Gesamtnote samt Notiz.

Gespeichert wird das als eigenes Modell InterimGrade, getrennt von der
Zeugnisnote. Die Berechnung endet am Stichtag und rechnet den laufenden
Mitarbeits-Abschnitt mit ein. Zwischenstände erscheinen im Assistenten
als Liste und Marker im Verlauf sowie als graue Spalte in der
Notenübersicht (nicht in "Gesamt", nicht im PDF).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:01:34 +02:00

351 lines
22 KiB
XML

<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
xmlns:views="clr-namespace:LehrerApp.Desktop.Views.Groups"
x:Class="LehrerApp.Desktop.Views.Groups.ReportGradeAssistantDialog"
x:DataType="vm:ReportGradeAssistantViewModel"
Title="{Binding WindowTitle}"
Width="1280" Height="880" MinWidth="980" MinHeight="640"
CanResize="True" WindowStartupLocation="CenterOwner">
<Grid ColumnDefinitions="250,*" RowDefinitions="*,Auto" Margin="24">
<!-- Links: Zeitraum und Schülerliste -->
<Grid Grid.Column="0" Grid.Row="0" RowDefinitions="Auto,Auto,*" Margin="0,0,18,0">
<StackPanel Grid.Row="0" Spacing="2">
<TextBlock Text="{Binding GroupLabel}" Classes="dialogtitle"/>
<TextBlock Text="{Binding SchemeSummary}" FontSize="11" Opacity="0.6" TextWrapping="Wrap"/>
</StackPanel>
<StackPanel Grid.Row="1" Spacing="6" Margin="0,12,0,10">
<ComboBox ItemsSource="{Binding PeriodOptions}" SelectedItem="{Binding SelectedPeriod}"
HorizontalAlignment="Stretch" IsVisible="{Binding IsReportMode}"/>
<TextBlock Text="{Binding InterimTitle}" FontSize="13" FontWeight="SemiBold" TextWrapping="Wrap"
Foreground="#D98200" IsVisible="{Binding IsInterimMode}"/>
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="6">
<TextBlock Grid.Column="0" Text="Rundung:" VerticalAlignment="Center" FontSize="12"/>
<ComboBox Grid.Column="1" ItemsSource="{Binding RoundingOptions}"
SelectedItem="{Binding RoundingRuleName}" HorizontalAlignment="Stretch"/>
</Grid>
<CheckBox Content="1. Halbjahr als Kontext zeigen" IsChecked="{Binding ShowPreviousHalf}"
IsVisible="{Binding CanShowPreviousHalf}" FontSize="12"
ToolTip.Tip="Zeigt Arbeiten, Noten und Mitarbeit des 1. Halbjahrs ausgegraut zum Vergleich. Sie zählen nicht in die Note des 2. Halbjahrs."/>
</StackPanel>
<ListBox Grid.Row="2" ItemsSource="{Binding Students}" SelectedItem="{Binding SelectedStudent}">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="vm:AssistantStudentItem">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Name}" FontSize="13" TextTrimming="CharacterEllipsis"/>
<TextBlock Text="{Binding StatusLabel}" FontSize="10" Foreground="{Binding StatusColorHex}"/>
</StackPanel>
<TextBlock Grid.Column="1" Text="{Binding GradeDisplay}" FontSize="15" FontWeight="SemiBold"
VerticalAlignment="Center" Margin="8,0,0,0"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
<!-- Rechts: der gewählte Schüler -->
<TextBlock Grid.Column="1" Grid.Row="0" Text="Keine Schüler im gewählten Zeitraum."
HorizontalAlignment="Center" VerticalAlignment="Center" Opacity="0.35" FontSize="14"
IsVisible="{Binding !HasStudent}"/>
<ScrollViewer Grid.Column="1" Grid.Row="0" IsVisible="{Binding HasStudent}">
<StackPanel Spacing="14" Margin="0,0,12,0">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="{Binding StudentName}" Classes="dialogtitle"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
<Button Content="◂ Zurück" Command="{Binding PreviousStudentCommand}"/>
<TextBlock Text="{Binding ProgressText}" VerticalAlignment="Center" Opacity="0.6" FontSize="12"/>
<Button Content="Weiter ▸" Command="{Binding NextStudentCommand}"/>
</StackPanel>
</Grid>
<!-- Note -->
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="7" Padding="14">
<StackPanel Spacing="10">
<Grid ColumnDefinitions="Auto,*,Auto">
<StackPanel Grid.Column="0" Margin="0,0,22,0">
<TextBlock Text="Berechnet" FontSize="11" Opacity="0.6"/>
<TextBlock Text="{Binding CalculatedDisplay}" FontSize="34" FontWeight="SemiBold"/>
<TextBlock Text="{Binding CalculationDetail}" FontSize="11" Opacity="0.6"/>
<TextBlock Text="{Binding BorderlineHint}" FontSize="11" Foreground="#D98200" FontWeight="SemiBold"
MaxWidth="190" TextWrapping="Wrap"
IsVisible="{Binding BorderlineHint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<ItemsControl Grid.Column="1" ItemsSource="{Binding Tiles}" VerticalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:AssistantTile">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="6" Padding="12,6" Margin="0,0,8,4" MinWidth="104">
<StackPanel>
<TextBlock Text="{Binding Label}" FontSize="11" Opacity="0.6"/>
<TextBlock Text="{Binding Value}" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="{Binding Hint}" FontSize="10" Opacity="0.55"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Grid.Column="2" HorizontalAlignment="Right">
<TextBlock Text="Zeugnisnote" FontSize="11" Opacity="0.6" HorizontalAlignment="Right"
IsVisible="{Binding IsReportMode}"/>
<TextBlock Text="{Binding FinalDisplay}" FontSize="34" FontWeight="SemiBold"
HorizontalAlignment="Right" IsVisible="{Binding IsReportMode}"/>
<TextBlock Text="{Binding AbsenceRateDisplay}" FontSize="11" HorizontalAlignment="Right"
Foreground="{Binding AbsenceRateColorHex}"
ToolTip.Tip="Fehlquote im gewählten Zeitraum — ab 50 % darf laut Schulrecht unabhängig von der fachlichen Leistung eine 5 vergeben werden."/>
</StackPanel>
</Grid>
<!-- Zwischenstand: vorläufige Noten zum Stichtag, getrennt von der Zeugnisnote -->
<StackPanel Spacing="6" IsVisible="{Binding IsInterimMode}">
<TextBlock FontSize="11" Opacity="0.6" TextWrapping="Wrap"
Text="Vorläufige Noten zum Stichtag — vorbelegt mit dem berechneten Stand, frei anpassbar. Die Zeugnisnote bleibt davon unberührt."/>
<Grid ColumnDefinitions="110,110,110,*" ColumnSpacing="6">
<StackPanel Grid.Column="0" Spacing="2">
<TextBlock Text="Schriftlich" FontSize="11" Opacity="0.6"/>
<TextBox Text="{Binding InterimWritten}"/>
<TextBlock Text="{Binding InterimWrittenError}" Foreground="Red" FontSize="11"
IsVisible="{Binding InterimWrittenError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2">
<TextBlock Text="Mündlich" FontSize="11" Opacity="0.6"/>
<TextBox Text="{Binding InterimOral}"/>
<TextBlock Text="{Binding InterimOralError}" Foreground="Red" FontSize="11"
IsVisible="{Binding InterimOralError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="2">
<TextBlock Text="Gesamt" FontSize="11" FontWeight="SemiBold"/>
<TextBox Text="{Binding InterimOverall}"/>
<TextBlock Text="{Binding InterimOverallError}" Foreground="Red" FontSize="11" TextWrapping="Wrap"
IsVisible="{Binding InterimOverallError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="3" Spacing="2">
<TextBlock Text="Notiz" FontSize="11" Opacity="0.6"/>
<TextBox Text="{Binding InterimNote}" PlaceholderText="z. B. was besprochen wurde"/>
</StackPanel>
</Grid>
<StackPanel Orientation="Horizontal" Spacing="6" HorizontalAlignment="Right">
<Button Content="Entfernen" Command="{Binding RemoveInterimCommand}"
IsVisible="{Binding HasInterimEntry}"/>
<Button Content="Notieren" Command="{Binding NoteInterimCommand}"/>
<Button Content="Notieren &amp; weiter" Command="{Binding NoteInterimAndNextCommand}"/>
</StackPanel>
</StackPanel>
<Grid ColumnDefinitions="150,*,Auto" ColumnSpacing="6" IsVisible="{Binding IsReportMode}">
<TextBox Grid.Column="0" Text="{Binding OverrideValue}" PlaceholderText="Übersteuern (optional)"
IsEnabled="{Binding !IsLocked}"/>
<TextBox Grid.Column="1" Text="{Binding OverrideReason}" PlaceholderText="Begründung"
IsEnabled="{Binding !IsLocked}"/>
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="6">
<Button Content="Speichern" Command="{Binding SaveCommand}" IsEnabled="{Binding !IsLocked}"/>
<Button Content="Speichern &amp; weiter" Command="{Binding SaveAndNextCommand}"
IsEnabled="{Binding !IsLocked}"/>
<Button Content="{Binding LockLabel}" Command="{Binding ToggleLockCommand}"/>
</StackPanel>
</Grid>
<StackPanel Spacing="4" IsVisible="{Binding CanEnterExamGrades}">
<TextBlock FontSize="11" Opacity="0.6" TextWrapping="Wrap"
Text="Prüfungen Klasse 10 — nur eintragen, was in diesem Fach abgelegt wurde. Die Prüfungsleistung geht mit einem Drittel in die Endnote ein."/>
<Grid ColumnDefinitions="*,*,*,*" ColumnSpacing="6">
<StackPanel Grid.Column="0" Spacing="2">
<TextBox Text="{Binding ProjectExamGrade}" PlaceholderText="Projektprüfung"
IsEnabled="{Binding !IsLocked}" ToolTip.Tip="Zählt wie ein weiteres Halbjahr."/>
<TextBlock Text="{Binding ProjectExamGradeError}" Foreground="Red" FontSize="11" TextWrapping="Wrap"
IsVisible="{Binding ProjectExamGradeError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="1" Spacing="2">
<TextBox Text="{Binding WrittenExamGrade}" PlaceholderText="Schriftliche Prüfung"
IsEnabled="{Binding !IsLocked}" ToolTip.Tip="Schriftliche Abschlussprüfung (Deutsch, Mathematik, erste Fremdsprache)."/>
<TextBlock Text="{Binding WrittenExamGradeError}" Foreground="Red" FontSize="11" TextWrapping="Wrap"
IsVisible="{Binding WrittenExamGradeError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="2">
<TextBox Text="{Binding OralExamGrade}" PlaceholderText="Mündliche Prüfung"
IsEnabled="{Binding !IsLocked}" ToolTip.Tip="Mündliche Abschlussprüfung im gewählten Fach."/>
<TextBlock Text="{Binding OralExamGradeError}" Foreground="Red" FontSize="11" TextWrapping="Wrap"
IsVisible="{Binding OralExamGradeError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="3" Spacing="2">
<TextBox Text="{Binding AdditionalOralExamGrade}" PlaceholderText="Zusätzl. mündliche Prüfung"
IsEnabled="{Binding !IsLocked}" ToolTip.Tip="Nachprüfung: im schriftlichen Prüfungsfach 1:1 mit der schriftlichen Prüfung verrechnet (ohne Rundung), sonst selbst ein Drittel der Endnote."/>
<TextBlock Text="{Binding AdditionalOralExamGradeError}" Foreground="Red" FontSize="11" TextWrapping="Wrap"
IsVisible="{Binding AdditionalOralExamGradeError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</Grid>
</StackPanel>
<TextBlock Text="{Binding OverrideReasonError}" Foreground="Red" FontSize="11"
IsVisible="{Binding OverrideReasonError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<TextBlock Text="{Binding StatusMessage}" Foreground="Green" FontSize="11"
IsVisible="{Binding StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
</Border>
<!-- Zwischenstände -->
<StackPanel Spacing="6">
<Grid ColumnDefinitions="*,Auto">
<TextBlock Grid.Column="0" Text="Zwischenstände" FontSize="13" FontWeight="SemiBold"
VerticalAlignment="Center"/>
<Button Grid.Column="1" Content="Zwischenstand notieren …" Command="{Binding StartInterimCommand}"
IsVisible="{Binding IsReportMode}" FontSize="11" Padding="8,3"
ToolTip.Tip="Vorläufige Note für diesen Schüler zu einem Stichtag und Anlass festhalten"/>
</Grid>
<TextBlock Text="Noch keine Zwischenstände notiert." FontSize="12" Opacity="0.5"
IsVisible="{Binding !HasInterimEntries}"/>
<ItemsControl ItemsSource="{Binding InterimEntries}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:AssistantInterimRow">
<Border BorderBrush="#D98200" BorderThickness="1" CornerRadius="6" Padding="10,5"
Margin="0,0,8,6" MaxWidth="320">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Title}" FontSize="12"/>
<TextBlock Text="{Binding Detail}" FontSize="10" Opacity="0.65"
IsVisible="{Binding Detail, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<TextBlock Text="{Binding Note}" FontSize="10" FontStyle="Italic" TextWrapping="Wrap"
IsVisible="{Binding Note, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<TextBlock Grid.Column="1" Text="{Binding OverallValue}" FontSize="17" FontWeight="SemiBold"
VerticalAlignment="Center" Margin="10,0,0,0"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<!-- Mitarbeit -->
<StackPanel Spacing="6">
<Grid ColumnDefinitions="Auto,*,Auto">
<TextBlock Grid.Column="0" Text="Mitarbeit" FontSize="13" FontWeight="SemiBold"
VerticalAlignment="Center"/>
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="7" VerticalAlignment="Center">
<RadioButton Content="Abschnitte" GroupName="ChartMode" IsChecked="{Binding IsSectionMode}" FontSize="12"/>
<RadioButton Content="Verlauf" GroupName="ChartMode" IsChecked="{Binding IsContinuousMode, Mode=OneWay}"
FontSize="12" Margin="0,0,10,0"/>
<TextBlock Text="Zoom" FontSize="10" Opacity="0.6" VerticalAlignment="Center"/>
<Slider Minimum="0.65" Maximum="2.25" Value="{Binding TimelineZoom}" Width="120" TickFrequency="0.1"/>
</StackPanel>
</Grid>
<Grid ColumnDefinitions="Auto,Auto,Auto,*" ColumnSpacing="8" IsVisible="{Binding IsSectionMode}">
<Button Grid.Column="0" Content="◂" Command="{Binding PreviousSectionCommand}" Padding="8,3"/>
<TextBlock Grid.Column="1" Text="{Binding SectionPosition}" VerticalAlignment="Center"
Opacity="0.6" FontSize="12"/>
<Button Grid.Column="2" Content="▸" Command="{Binding NextSectionCommand}" Padding="8,3"/>
<TextBlock Grid.Column="3" Text="{Binding SectionTitle}" VerticalAlignment="Center" FontSize="12"/>
</Grid>
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="1" CornerRadius="7" ClipToBounds="True">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<views:ParticipationTimelineChart Timeline="{Binding ChartGroups}" Zoom="{Binding TimelineZoom}"/>
</ScrollViewer>
</Border>
<ItemsControl ItemsSource="{Binding ParticipationGrades}" IsVisible="{Binding HasParticipationGrades}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:AssistantGradeRow">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}" BorderThickness="1"
CornerRadius="6" Padding="10,5" Margin="0,0,8,6" Opacity="{Binding DisplayOpacity}">
<StackPanel Orientation="Horizontal" Spacing="10">
<StackPanel>
<TextBlock Text="{Binding Label}" FontSize="12"/>
<TextBlock Text="{Binding DateDisplay}" FontSize="10" Opacity="0.6"/>
</StackPanel>
<TextBlock Text="{Binding Value}" FontSize="17" FontWeight="SemiBold" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<!-- Arbeiten -->
<StackPanel Spacing="6">
<TextBlock Text="Arbeiten" FontSize="13" FontWeight="SemiBold"/>
<TextBlock Text="Keine Arbeiten im gewählten Zeitraum." FontSize="12" Opacity="0.5"
IsVisible="{Binding !HasWorks}"/>
<ItemsControl ItemsSource="{Binding Works}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:AssistantWorkCard">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}" BorderThickness="1"
CornerRadius="6" Padding="12,8" Margin="0,0,8,8" Width="210"
Opacity="{Binding DisplayOpacity}">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="1">
<TextBlock Text="{Binding Title}" FontSize="13" FontWeight="SemiBold"
TextTrimming="CharacterEllipsis" ToolTip.Tip="{Binding Title}"/>
<TextBlock Text="{Binding KindLabel}" FontSize="10" Opacity="0.65" TextWrapping="Wrap"/>
<TextBlock Text="{Binding DateDisplay}" FontSize="10" Opacity="0.65"/>
<TextBlock Text="{Binding ClassAverageDisplay}" FontSize="10" Opacity="0.65"
IsVisible="{Binding ClassAverageDisplay, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<TextBlock Text="{Binding ContextLabel}" FontSize="10" FontStyle="Italic"
IsVisible="{Binding IsContext}"/>
</StackPanel>
<StackPanel Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center">
<TextBlock Text="{Binding GradeDisplay}" FontSize="24" FontWeight="SemiBold"
HorizontalAlignment="Right"/>
<TextBlock Text="{Binding PercentDisplay}" FontSize="10" Opacity="0.65"
HorizontalAlignment="Right"/>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<!-- Sonstige Noten -->
<StackPanel Spacing="6" IsVisible="{Binding HasOtherGrades}">
<TextBlock Text="Sonstige Noten" FontSize="13" FontWeight="SemiBold"/>
<ItemsControl ItemsSource="{Binding OtherGrades}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:AssistantGradeRow">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}" BorderThickness="1"
CornerRadius="6" Padding="10,5" Margin="0,0,8,6" Opacity="{Binding DisplayOpacity}">
<StackPanel Orientation="Horizontal" Spacing="10">
<StackPanel>
<TextBlock Text="{Binding Label}" FontSize="12"/>
<TextBlock Text="{Binding DateDisplay}" FontSize="10" Opacity="0.6"/>
</StackPanel>
<TextBlock Text="{Binding Value}" FontSize="17" FontWeight="SemiBold" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</StackPanel>
</ScrollViewer>
<Button Grid.Column="1" Grid.Row="1" Content="Schließen" HorizontalAlignment="Right"
Margin="0,14,0,0" Click="OnClose"/>
</Grid>
</Window>