Unterrichtsplanung: Einheiten, Verlaufsplan-Editor, Kürzel-Katalog (Kapitel 4.1/4.2)

Neuer Tab "Planung" in GroupDetailView ersetzt den Platzhalter: Einheiten anlegen/bearbeiten/
als Vorlage in andere Gruppe kopieren, Stunden je Einheit mit Verschieben (inkl. Nachrücken
der Folgestunden). Stundeneditor als tabellarischer Verlaufsplan (Phase/Dauer/Tätigkeit/
Material/Kurzsymbol je Zeile, Uhrzeit aus optionalem Stundenbeginn abgeleitet) statt eines
einzelnen Phase-Felds mit Methoden-/Materialien-Chips — Kurzsymbol als Freitext mit
Vorschlägen aus neuem Kürzel-Katalog (Einstellungen) plus bisher verwendeten Werten.
Schema-Migrationen v1-v3 überführen bestehende Daten verlustfrei. 4.2.5 bewusst offen
gelassen (hängt an Stundenplan, Kapitel 4.3).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-14 00:50:57 +02:00
co-authored by Claude Sonnet 5
parent 27359794f7
commit de6ea001e7
28 changed files with 2372 additions and 32 deletions
@@ -0,0 +1,130 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
x:Class="LehrerApp.Desktop.Views.Groups.LessonDialog"
x:DataType="vm:LessonDialogViewModel"
Title="{Binding DialogTitle}"
Width="960" Height="760" MinWidth="720" MinHeight="480"
CanResize="True" WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="*,Auto" Margin="24">
<ScrollViewer Grid.Row="0">
<StackPanel Spacing="14" Margin="0,0,12,0">
<TextBlock Text="{Binding DialogTitle}" Classes="dialogtitle"/>
<Grid ColumnDefinitions="*,12,*,12,*,12,*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Datum *" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ"/>
<TextBlock Text="{Binding DateTextError}" Foreground="Red" FontSize="11"
IsVisible="{Binding DateTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="Stunde Nr." FontSize="12" Opacity="0.7"/>
<NumericUpDown Value="{Binding LessonNumber}" Minimum="1" Maximum="20" FormatString="0"
ShowButtonSpinner="False"/>
</StackPanel>
<StackPanel Grid.Column="4" Spacing="4">
<TextBlock Text="Beginn" FontSize="12" Opacity="0.7"
ToolTip.Tip="Optional. Solange es noch keinen Stundenplan gibt: von Hand eintragen, damit die Uhrzeiten je Phase unten abgeleitet werden können."/>
<TextBox Text="{Binding StartTimeText}" PlaceholderText="HH:MM"/>
<TextBlock Text="{Binding StartTimeTextError}" Foreground="Red" FontSize="11"
IsVisible="{Binding StartTimeTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<StackPanel Grid.Column="6" Spacing="4">
<TextBlock Text="Status" FontSize="12" Opacity="0.7"/>
<ComboBox ItemsSource="{Binding StatusOptions}" SelectedItem="{Binding StatusName}"
HorizontalAlignment="Stretch"/>
</StackPanel>
</Grid>
<StackPanel Spacing="4">
<TextBlock Text="Thema *" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding Topic}" PlaceholderText="z.B. Brechung an planparallelen Platten"/>
<TextBlock Text="{Binding TopicError}" Foreground="Red" FontSize="11"
IsVisible="{Binding TopicError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<Separator Margin="0,4"/>
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="10" VerticalAlignment="Center">
<TextBlock Text="Verlaufsplan" FontSize="14" FontWeight="SemiBold"/>
<TextBlock Text="{Binding TotalDurationDisplay}" FontSize="12" Opacity="0.6"/>
</StackPanel>
<Button Grid.Column="1" Content=" Phase" Command="{Binding AddPhaseCommand}"/>
</Grid>
<!-- Tabellenkopf -->
<Grid ColumnDefinitions="140,130,*,110,100,26,26,26" Margin="4,0,0,0">
<TextBlock Grid.Column="0" Text="Phase" FontSize="11" FontWeight="SemiBold" Opacity="0.6"/>
<TextBlock Grid.Column="1" Text="Dauer / Zeit" FontSize="11" FontWeight="SemiBold" Opacity="0.6"/>
<TextBlock Grid.Column="2" Text="Tätigkeit" FontSize="11" FontWeight="SemiBold" Opacity="0.6"/>
<TextBlock Grid.Column="3" Text="Material" FontSize="11" FontWeight="SemiBold" Opacity="0.6"/>
<TextBlock Grid.Column="4" Text="Kurzsymbol" FontSize="11" FontWeight="SemiBold" Opacity="0.6"/>
</Grid>
<Separator/>
<!-- Eine Zeile je Phase, echte Tabellenspalten nebeneinander statt gestapelter Karten. -->
<ItemsControl ItemsSource="{Binding Phases}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:PhaseStepEditItem">
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,0,1" Padding="0,8">
<Grid ColumnDefinitions="140,130,*,110,100,26,26,26">
<TextBox Grid.Column="0" Text="{Binding Name}" PlaceholderText="z.B. Erarbeitung"
VerticalAlignment="Top" Margin="0,0,6,0"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6"
VerticalAlignment="Top" Margin="0,0,6,0">
<NumericUpDown Value="{Binding DurationMinutes}" Minimum="0" Maximum="180" Width="62"
FormatString="0" ShowButtonSpinner="False" ToolTip.Tip="Dauer in Minuten"/>
<TextBlock Text="{Binding ComputedTimeDisplay}" FontSize="12" Opacity="0.6"
VerticalAlignment="Center"/>
</StackPanel>
<TextBox Grid.Column="2" Text="{Binding Activity}" AcceptsReturn="True" TextWrapping="Wrap"
Height="56" VerticalAlignment="Top" Margin="0,0,6,0"
PlaceholderText="Lehrer-/Schüler-Tätigkeit"
ToolTip.Tip="Bei mehr Text scrollt das Feld intern."/>
<AutoCompleteBox Grid.Column="3" Text="{Binding Material}"
ItemsSource="{Binding $parent[ItemsControl].((vm:LessonDialogViewModel)DataContext).MaterialSuggestions}"
FilterMode="Contains" MinimumPrefixLength="0" VerticalAlignment="Top"
Margin="0,0,6,0" PlaceholderText="z.B. AB01"/>
<AutoCompleteBox Grid.Column="4" Text="{Binding Shorthand}"
ItemsSource="{Binding $parent[ItemsControl].((vm:LessonDialogViewModel)DataContext).ShorthandSuggestions}"
FilterMode="Contains" MinimumPrefixLength="0" VerticalAlignment="Top"
Margin="0,0,6,0" PlaceholderText="z.B. AB001-&gt;S, Plenum, LDE"
ToolTip.Tip="Freitext für den schnellen Überblick — mal ein Materialfluss-Pfeil (AB001-&gt;S), mal nur eine Sozialform (Plenum, LDE)."/>
<Button Grid.Column="5" Content="↑" Command="{Binding MoveUpCommand}" Padding="4,2"
VerticalAlignment="Top" ToolTip.Tip="Nach oben"/>
<Button Grid.Column="6" Content="↓" Command="{Binding MoveDownCommand}" Padding="4,2"
VerticalAlignment="Top" Margin="2,0,0,0" ToolTip.Tip="Nach unten"/>
<Button Grid.Column="7" Content="✕" Command="{Binding RemoveCommand}" Padding="4,2"
VerticalAlignment="Top" Margin="2,0,0,0" ToolTip.Tip="Entfernen"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Separator Margin="0,4"/>
<StackPanel Spacing="4">
<TextBlock Text="Hausaufgabe" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding Homework}" AcceptsReturn="True" Height="48" TextWrapping="Wrap"/>
</StackPanel>
<StackPanel Spacing="4">
<TextBlock Text="Reflexion" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding Reflection}" AcceptsReturn="True" Height="56" TextWrapping="Wrap"
PlaceholderText="Nach der Stunde: was lief gut, was nicht?"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
<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="{Binding SaveButtonText}"
HorizontalAlignment="Stretch" Click="OnSave"/>
</Grid>
</Grid>
</Window>