Initial
This commit is contained in:
115
LehrerApp.Desktop/Views/DashboardView.axaml
Normal file
115
LehrerApp.Desktop/Views/DashboardView.axaml
Normal file
@@ -0,0 +1,115 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||||
x:Class="LehrerApp.Desktop.Views.DashboardView"
|
||||
x:DataType="vm:DashboardViewModel">
|
||||
|
||||
<ScrollViewer Padding="24">
|
||||
<StackPanel Spacing="20">
|
||||
|
||||
<!-- Header -->
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Greeting}" FontSize="14" Opacity="0.6" />
|
||||
<TextBlock Text="{Binding CurrentDate}" FontSize="24" FontWeight="SemiBold" />
|
||||
</StackPanel>
|
||||
|
||||
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto,Auto" >
|
||||
|
||||
<!-- Heutige Stunden -->
|
||||
<Border Grid.Column="0" Grid.Row="0"
|
||||
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="8" Padding="16" Margin="0,0,8,8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="HEUTE" FontSize="11" FontWeight="Bold"
|
||||
Opacity="0.5" Margin="0,0,0,12"/>
|
||||
<ItemsControl ItemsSource="{Binding TodaysLessons}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:LessonItem">
|
||||
<Border Padding="0,6" BorderThickness="0,0,0,1"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}">
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<Border Grid.Column="0" Width="4" CornerRadius="2"
|
||||
Background="{DynamicResource SystemAccentColor}"
|
||||
Margin="0,0,10,0"/>
|
||||
<StackPanel Grid.Column="1">
|
||||
<TextBlock Text="{Binding GroupName}"
|
||||
FontWeight="SemiBold" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Topic}"
|
||||
FontSize="12" Opacity="0.7"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock Text="Keine Stunden heute" FontSize="13" Opacity="0.5"
|
||||
IsVisible="{Binding !TodaysLessons.Count}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Offene Aufgaben -->
|
||||
<Border Grid.Column="1" Grid.Row="0"
|
||||
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="8" Padding="16" Margin="8,0,0,8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="OFFENE AUFGABEN" FontSize="11" FontWeight="Bold"
|
||||
Opacity="0.5" Margin="0,0,0,12"/>
|
||||
<ItemsControl ItemsSource="{Binding OpenTasks}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:TaskItem">
|
||||
<Grid ColumnDefinitions="*,Auto" Margin="0,4">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="{Binding Title}"
|
||||
FontSize="13" TextTrimming="CharacterEllipsis"/>
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="1" Text="{Binding DueDate}"
|
||||
FontSize="12" Opacity="0.6" Margin="8,0,0,0"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock Text="Keine offenen Aufgaben" FontSize="13" Opacity="0.5"
|
||||
IsVisible="{Binding !OpenTasks.Count}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Meine Lerngruppen -->
|
||||
<Border Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"
|
||||
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="8" Padding="16">
|
||||
<StackPanel>
|
||||
<TextBlock Text="MEINE LERNGRUPPEN" FontSize="11" FontWeight="Bold"
|
||||
Opacity="0.5" Margin="0,0,0,12"/>
|
||||
<ItemsControl ItemsSource="{Binding CurrentGroups}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:GroupChip">
|
||||
<Border Background="{DynamicResource SystemAccentColorLight2}"
|
||||
CornerRadius="6" Padding="12,6" Margin="0,0,8,8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Name}"
|
||||
FontWeight="SemiBold" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Subject}"
|
||||
FontSize="11" Opacity="0.7"
|
||||
IsVisible="{Binding Subject, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock Text="Noch keine Lerngruppen für dieses Schuljahr"
|
||||
FontSize="13" Opacity="0.5"
|
||||
IsVisible="{Binding !CurrentGroups.Count}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</UserControl>
|
||||
38
LehrerApp.Desktop/Views/DataTemplates.axaml
Normal file
38
LehrerApp.Desktop/Views/DataTemplates.axaml
Normal file
@@ -0,0 +1,38 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||||
xmlns:vmg="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
|
||||
xmlns:vms="clr-namespace:LehrerApp.Desktop.ViewModels.Students"
|
||||
xmlns:vg="clr-namespace:LehrerApp.Desktop.Views.Groups"
|
||||
xmlns:vs="clr-namespace:LehrerApp.Desktop.Views.Students"
|
||||
xmlns:v="clr-namespace:LehrerApp.Desktop.Views">
|
||||
|
||||
<!-- Dashboard -->
|
||||
<DataTemplate DataType="vm:DashboardViewModel">
|
||||
<v:DashboardView/>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Platzhalter -->
|
||||
<DataTemplate DataType="vm:PlaceholderViewModel">
|
||||
<v:PlaceholderView/>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Gruppen -->
|
||||
<DataTemplate DataType="vmg:GroupListViewModel">
|
||||
<vg:GroupListView/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="vmg:GroupDetailViewModel">
|
||||
<vg:GroupDetailView/>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Schüler -->
|
||||
<DataTemplate DataType="vms:StudentListViewModel">
|
||||
<vs:StudentListView/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="vms:StudentDetailViewModel">
|
||||
<vs:StudentDetailView/>
|
||||
</DataTemplate>
|
||||
|
||||
</ResourceDictionary>
|
||||
185
LehrerApp.Desktop/Views/DevicePairingDialog.axaml
Normal file
185
LehrerApp.Desktop/Views/DevicePairingDialog.axaml
Normal file
@@ -0,0 +1,185 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||||
x:Class="LehrerApp.Desktop.Views.DevicePairingDialog"
|
||||
x:DataType="vm:DevicePairingViewModel"
|
||||
Title="Gerät einrichten"
|
||||
Width="480" Height="420"
|
||||
CanResize="False"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid Margin="28">
|
||||
|
||||
<!-- ── Modus: Auswahl ──────────────────────────────────────────────────── -->
|
||||
<StackPanel Spacing="16"
|
||||
IsVisible="{Binding Mode,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:PairingMode.SelectMode}}">
|
||||
|
||||
<TextBlock Text="Gerät einrichten"
|
||||
FontSize="20" FontWeight="SemiBold"/>
|
||||
<TextBlock TextWrapping="Wrap" Opacity="0.7">
|
||||
Möchtest du ein neues Gerät mit deinem bestehenden Datenbestand
|
||||
verbinden, oder dieses Gerät als erstes Gerät einrichten?
|
||||
</TextBlock>
|
||||
|
||||
<Button Content="Daten auf dieses Gerät übertragen"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding SelectReceiverCommand}"
|
||||
Padding="12,10"/>
|
||||
|
||||
<Button Content="Von diesem Gerät Daten übertragen"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding SelectSenderCommand}"
|
||||
Padding="12,10"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Modus: Sender ───────────────────────────────────────────────────── -->
|
||||
<StackPanel Spacing="16"
|
||||
IsVisible="{Binding Mode,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:PairingMode.Sender}}">
|
||||
|
||||
<TextBlock Text="Daten übertragen"
|
||||
FontSize="20" FontWeight="SemiBold"/>
|
||||
<TextBlock TextWrapping="Wrap" Opacity="0.7">
|
||||
Es wird ein verschlüsselter Snapshot deiner lokalen Datenbank erstellt
|
||||
und kurzzeitig auf dem Server hinterlegt. Du erhältst einen Einmal-Code
|
||||
der 24 Stunden gültig ist.
|
||||
</TextBlock>
|
||||
|
||||
<!-- Fortschritt -->
|
||||
<ProgressBar Value="{Binding ProgressPercent}"
|
||||
Maximum="100" Height="6" CornerRadius="3"
|
||||
IsVisible="{Binding IsBusy}"/>
|
||||
<TextBlock Text="{Binding StatusMessage}"
|
||||
FontSize="12" Opacity="0.7"
|
||||
IsVisible="{Binding IsBusy}"/>
|
||||
|
||||
<!-- Fehler -->
|
||||
<Border Background="#22FF0000" CornerRadius="6" Padding="12"
|
||||
IsVisible="{Binding IsError}">
|
||||
<TextBlock Text="{Binding StatusMessage}"
|
||||
TextWrapping="Wrap" Foreground="Red"/>
|
||||
</Border>
|
||||
|
||||
<Grid ColumnDefinitions="*,8,Auto" Margin="0,8,0,0">
|
||||
<Button Grid.Column="0"
|
||||
Content="← Zurück"
|
||||
Command="{Binding BackCommand}"
|
||||
IsEnabled="{Binding !IsBusy}"/>
|
||||
<Button Grid.Column="2"
|
||||
Content="Snapshot erstellen"
|
||||
Command="{Binding CreateSnapshotCommand}"
|
||||
IsEnabled="{Binding !IsBusy}"
|
||||
Padding="16,8"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Modus: Sender zeigt Code ────────────────────────────────────────── -->
|
||||
<StackPanel Spacing="16"
|
||||
IsVisible="{Binding Mode,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:PairingMode.SenderShowCode}}">
|
||||
|
||||
<TextBlock Text="Code bereit" FontSize="20" FontWeight="SemiBold"/>
|
||||
<TextBlock TextWrapping="Wrap" Opacity="0.7">
|
||||
Gib diesen Code auf dem Zielgerät ein. Der Code ist einmalig verwendbar.
|
||||
</TextBlock>
|
||||
|
||||
<!-- Der Code prominent anzeigen -->
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="10" Padding="24,20">
|
||||
<StackPanel HorizontalAlignment="Center" Spacing="8">
|
||||
<TextBlock Text="{Binding GeneratedCode}"
|
||||
FontSize="32" FontWeight="Bold"
|
||||
FontFamily="Cascadia Code, Consolas, monospace"
|
||||
HorizontalAlignment="Center"
|
||||
LetterSpacing="4"/>
|
||||
<TextBlock Text="{Binding CodeExpiresText}"
|
||||
FontSize="12" Opacity="0.5"
|
||||
HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.6">
|
||||
Der Code wird nach dem ersten Abruf automatisch ungültig.
|
||||
Der Server speichert nur verschlüsselte Daten – kein Klartext.
|
||||
</TextBlock>
|
||||
|
||||
<Button Content="Fertig" HorizontalAlignment="Right"
|
||||
Click="OnClose" Padding="16,8"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Modus: Empfänger – Code eingeben ────────────────────────────────── -->
|
||||
<StackPanel Spacing="16"
|
||||
IsVisible="{Binding Mode,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:PairingMode.Receiver}}">
|
||||
|
||||
<TextBlock Text="Code eingeben"
|
||||
FontSize="20" FontWeight="SemiBold"/>
|
||||
<TextBlock TextWrapping="Wrap" Opacity="0.7">
|
||||
Gib den Code ein der auf dem Quellgerät angezeigt wird.
|
||||
Format: WORT-ZZ-WORT (z.B. TIGER-42-BLAU)
|
||||
</TextBlock>
|
||||
|
||||
<TextBox Text="{Binding InputCode}"
|
||||
Watermark="TIGER-42-BLAU"
|
||||
FontSize="20"
|
||||
FontFamily="Cascadia Code, Consolas, monospace"
|
||||
TextAlignment="Center"
|
||||
CharacterCasing="Upper"/>
|
||||
|
||||
<!-- Fortschritt -->
|
||||
<ProgressBar Value="{Binding ProgressPercent}"
|
||||
Maximum="100" Height="6" CornerRadius="3"
|
||||
IsVisible="{Binding IsBusy}"/>
|
||||
<TextBlock Text="{Binding StatusMessage}"
|
||||
FontSize="12" Opacity="0.7"
|
||||
IsVisible="{Binding IsBusy}"/>
|
||||
|
||||
<!-- Fehler -->
|
||||
<Border Background="#22FF0000" CornerRadius="6" Padding="12"
|
||||
IsVisible="{Binding IsError}">
|
||||
<TextBlock Text="{Binding StatusMessage}"
|
||||
TextWrapping="Wrap" Foreground="Red"/>
|
||||
</Border>
|
||||
|
||||
<Grid ColumnDefinitions="*,8,Auto">
|
||||
<Button Grid.Column="0" Content="← Zurück"
|
||||
Command="{Binding BackCommand}"
|
||||
IsEnabled="{Binding !IsBusy}"/>
|
||||
<Button Grid.Column="2"
|
||||
Content="Wiederherstellen"
|
||||
Click="OnRestore"
|
||||
IsEnabled="{Binding !IsBusy}"
|
||||
Padding="16,8"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Modus: Empfänger – Fertig ───────────────────────────────────────── -->
|
||||
<StackPanel Spacing="16" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding Mode,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:PairingMode.ReceiverDone}}">
|
||||
|
||||
<TextBlock Text="✓" FontSize="48" HorizontalAlignment="Center"
|
||||
Foreground="Green"/>
|
||||
<TextBlock Text="Erfolgreich übertragen!"
|
||||
FontSize="20" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding StatusMessage}"
|
||||
Opacity="0.7" HorizontalAlignment="Center"
|
||||
TextWrapping="Wrap" TextAlignment="Center"/>
|
||||
<Button Content="App neu starten"
|
||||
HorizontalAlignment="Center"
|
||||
Click="OnRestartRequested"
|
||||
Padding="16,8" Margin="0,8,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
34
LehrerApp.Desktop/Views/DevicePairingDialog.axaml.cs
Normal file
34
LehrerApp.Desktop/Views/DevicePairingDialog.axaml.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using LehrerApp.Desktop.ViewModels;
|
||||
|
||||
namespace LehrerApp.Desktop.Views;
|
||||
|
||||
public partial class DevicePairingDialog : Window
|
||||
{
|
||||
// Wird von außen gesetzt – Pfad zur lokalen DB
|
||||
public string TargetDbPath { get; set; } = "";
|
||||
|
||||
// Signal: App-Neustart nötig
|
||||
public bool RestartRequested { get; private set; }
|
||||
|
||||
public DevicePairingDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnClose(object? sender, RoutedEventArgs e) =>
|
||||
Close();
|
||||
|
||||
private async void OnRestore(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is DevicePairingViewModel vm)
|
||||
await vm.RestoreCommand.ExecuteAsync(TargetDbPath);
|
||||
}
|
||||
|
||||
private void OnRestartRequested(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
RestartRequested = true;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
109
LehrerApp.Desktop/Views/Groups/AddGroupDialog.axaml
Normal file
109
LehrerApp.Desktop/Views/Groups/AddGroupDialog.axaml
Normal file
@@ -0,0 +1,109 @@
|
||||
<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.AddGroupDialog"
|
||||
x:DataType="vm:AddGroupDialogViewModel"
|
||||
Title="Neue Lerngruppe"
|
||||
Width="420" Height="480"
|
||||
CanResize="False"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="*,Auto" Margin="24">
|
||||
|
||||
<StackPanel Grid.Row="0" Spacing="16">
|
||||
|
||||
<TextBlock Text="Neue Lerngruppe anlegen"
|
||||
FontSize="18" FontWeight="SemiBold"/>
|
||||
|
||||
<!-- Name -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Name *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Name}"
|
||||
Watermark="z.B. 10E, Q1 Chemie, 5a"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Fach -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Fach" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Subject}"
|
||||
Watermark="z.B. Chemie, Mathematik"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Typ und Klassenstufe nebeneinander -->
|
||||
<Grid ColumnDefinitions="*,12,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Typ" FontSize="12" Opacity="0.7"/>
|
||||
<ComboBox ItemsSource="{Binding GroupTypes}"
|
||||
SelectedItem="{Binding Type}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:GroupTypeItem">
|
||||
<TextBlock Text="{Binding Label}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Klassenstufe *" FontSize="12" Opacity="0.7"/>
|
||||
<NumericUpDown Value="{Binding GradeLevel}"
|
||||
Minimum="1" Maximum="13"
|
||||
FormatString="0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Notensystem und Schuljahr -->
|
||||
<Grid ColumnDefinitions="*,12,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Notensystem" FontSize="12" Opacity="0.7"/>
|
||||
<ComboBox ItemsSource="{Binding GradingSystems}"
|
||||
SelectedItem="{Binding GradingSystem}"
|
||||
HorizontalAlignment="Stretch">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:GradingSystemItem">
|
||||
<TextBlock Text="{Binding Label}" TextWrapping="Wrap"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Schuljahr" FontSize="12" Opacity="0.7"/>
|
||||
<ComboBox ItemsSource="{Binding SchoolYears}"
|
||||
SelectedItem="{Binding SelectedSchoolYear}"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Wochenstunden -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Wochenstunden (optional)" FontSize="12" Opacity="0.7"/>
|
||||
<NumericUpDown Value="{Binding HoursPerWeek}"
|
||||
Minimum="1" Maximum="20"
|
||||
FormatString="0"
|
||||
AllowSpin="True"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Validierungsfehler -->
|
||||
<TextBlock Text="{Binding ValidationMessage}"
|
||||
Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage,
|
||||
Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Buttons ──────────────────────────────────────────────────────── -->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,16,0,0">
|
||||
<Button Grid.Column="0"
|
||||
Content="Abbrechen"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="OnCancel"/>
|
||||
<Button Grid.Column="2"
|
||||
Content="Anlegen"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="OnSave"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Window>
|
||||
33
LehrerApp.Desktop/Views/Groups/AddGroupDialog.axaml.cs
Normal file
33
LehrerApp.Desktop/Views/Groups/AddGroupDialog.axaml.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Groups;
|
||||
|
||||
public partial class AddGroupDialog : Window
|
||||
{
|
||||
public bool Saved { get; private set; }
|
||||
|
||||
public AddGroupDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnSave(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Groups.AddGroupDialogViewModel vm)
|
||||
{
|
||||
if (vm.SaveCommand.CanExecute(null))
|
||||
{
|
||||
vm.SaveCommand.Execute(null);
|
||||
if (vm.Result is not null)
|
||||
{
|
||||
Saved = true;
|
||||
Close(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCancel(object? sender, RoutedEventArgs e) =>
|
||||
Close(false);
|
||||
}
|
||||
129
LehrerApp.Desktop/Views/Groups/GroupDetailView.axaml
Normal file
129
LehrerApp.Desktop/Views/Groups/GroupDetailView.axaml
Normal file
@@ -0,0 +1,129 @@
|
||||
<UserControl 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.GroupDetailView"
|
||||
x:DataType="vm:GroupDetailViewModel">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
|
||||
<!-- ── Header ──────────────────────────────────────────────────────── -->
|
||||
<Border Grid.Row="0" Padding="20,16"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="{Binding GroupTitle}"
|
||||
FontSize="22" FontWeight="SemiBold"/>
|
||||
<TextBlock FontSize="12" Opacity="0.5">
|
||||
<Run Text="{Binding StudentCount}"/>
|
||||
<Run Text="Schüler"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
|
||||
<Button Content="+ Schüler"
|
||||
Command="{Binding AddStudentCommand}"/>
|
||||
<Button Content="+ Klausur"
|
||||
Command="{Binding AddExamCommand}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Tab-Leiste ──────────────────────────────────────────────────── -->
|
||||
<Border Grid.Row="1"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Padding="16,0">
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<Button Content="Übersicht"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:GroupTab.Overview}"
|
||||
Classes.active="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:GroupTab.Overview}}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
<Button Content="Schüler"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:GroupTab.Students}"
|
||||
Classes.active="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:GroupTab.Students}}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
<Button Content="Klausuren"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:GroupTab.Exams}"
|
||||
Classes.active="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:GroupTab.Exams}}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
<Button Content="Noten"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:GroupTab.Grades}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
<Button Content="Planung"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:GroupTab.Planner}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
<Button Content="Dokumentation"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:GroupTab.Documentation}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ── Tab-Inhalt ──────────────────────────────────────────────────── -->
|
||||
<ScrollViewer Grid.Row="2" Padding="20">
|
||||
|
||||
<!-- Schülerliste -->
|
||||
<DataGrid ItemsSource="{Binding Students}"
|
||||
IsVisible="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:GroupTab.Students}}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Name"
|
||||
Binding="{Binding FullName}"
|
||||
Width="*"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<!-- Klausuren -->
|
||||
<DataGrid ItemsSource="{Binding Exams}"
|
||||
IsVisible="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:GroupTab.Exams}}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserReorderColumns="False">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Datum"
|
||||
Binding="{Binding Date}"
|
||||
Width="100"/>
|
||||
<DataGridTextColumn Header="Titel"
|
||||
Binding="{Binding Title}"
|
||||
Width="*"/>
|
||||
<DataGridTextColumn Header="Status"
|
||||
Binding="{Binding Status}"
|
||||
Width="120"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<!-- Übersicht (Platzhalter) -->
|
||||
<StackPanel IsVisible="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:GroupTab.Overview}}"
|
||||
Spacing="12">
|
||||
<TextBlock Text="Übersicht" FontSize="16" FontWeight="SemiBold"/>
|
||||
<TextBlock Text="Hier erscheint eine Zusammenfassung der Lerngruppe."
|
||||
Opacity="0.5"/>
|
||||
</StackPanel>
|
||||
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
100
LehrerApp.Desktop/Views/Groups/GroupListView.axaml
Normal file
100
LehrerApp.Desktop/Views/Groups/GroupListView.axaml
Normal file
@@ -0,0 +1,100 @@
|
||||
<UserControl 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.GroupListView"
|
||||
x:DataType="vm:GroupListViewModel">
|
||||
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
|
||||
<!-- ── Toolbar ─────────────────────────────────────────────────────── -->
|
||||
<Border Grid.Row="0" Padding="20,16"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="*,Auto,Auto">
|
||||
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="Lerngruppen" FontSize="22" FontWeight="SemiBold"/>
|
||||
<TextBlock FontSize="12" Opacity="0.5">
|
||||
<Run Text="{Binding Groups.Count}"/>
|
||||
<Run Text="Gruppen ·"/>
|
||||
<Run Text="{Binding SelectedSchoolYear}"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Schuljahr-Auswahl -->
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding SchoolYears}"
|
||||
SelectedItem="{Binding SelectedSchoolYear}"
|
||||
Width="100" Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<!-- Neue Gruppe -->
|
||||
<Button Grid.Column="2"
|
||||
Content="+ Neue Gruppe"
|
||||
Command="{Binding AddGroupCommand}"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Inhalt ──────────────────────────────────────────────────────── -->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="260,*">
|
||||
|
||||
<!-- Suchliste links -->
|
||||
<Border Grid.Column="0"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,1,0">
|
||||
<DockPanel>
|
||||
<TextBox DockPanel.Dock="Top"
|
||||
Text="{Binding SearchText}"
|
||||
Watermark="Suchen…"
|
||||
Margin="12,8"/>
|
||||
<ListBox ItemsSource="{Binding Groups}"
|
||||
SelectedItem="{Binding SelectedGroup}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:GroupListItem">
|
||||
<Grid ColumnDefinitions="4,*" Margin="0,4">
|
||||
<Border Grid.Column="0" Width="4" CornerRadius="2"
|
||||
Background="{DynamicResource SystemAccentColor}"
|
||||
Margin="0,0,10,0"/>
|
||||
<StackPanel Grid.Column="1">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding Name}"
|
||||
FontWeight="SemiBold" FontSize="13"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding TypeLabel}"
|
||||
FontSize="11" Opacity="0.5"/>
|
||||
</Grid>
|
||||
<TextBlock Text="{Binding Subject}"
|
||||
FontSize="12" Opacity="0.65"
|
||||
IsVisible="{Binding Subject,
|
||||
Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<TextBlock Text="{Binding GradingLabel}"
|
||||
FontSize="11" Opacity="0.4"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Detail rechts – Platzhalter bis Gruppe gewählt -->
|
||||
<Border Grid.Column="1">
|
||||
<StackPanel HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8"
|
||||
IsVisible="{Binding !SelectedGroup}">
|
||||
<TextBlock Text="Keine Gruppe ausgewählt"
|
||||
FontSize="16" Opacity="0.4"
|
||||
HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="Wähle eine Gruppe aus der Liste oder lege eine neue an."
|
||||
FontSize="12" Opacity="0.3"
|
||||
HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
13
LehrerApp.Desktop/Views/Groups/GroupViews.cs
Normal file
13
LehrerApp.Desktop/Views/Groups/GroupViews.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Groups;
|
||||
|
||||
public partial class GroupListView : UserControl
|
||||
{
|
||||
public GroupListView() => InitializeComponent();
|
||||
}
|
||||
|
||||
public partial class GroupDetailView : UserControl
|
||||
{
|
||||
public GroupDetailView() => InitializeComponent();
|
||||
}
|
||||
108
LehrerApp.Desktop/Views/MainWindow.axaml
Normal file
108
LehrerApp.Desktop/Views/MainWindow.axaml
Normal file
@@ -0,0 +1,108 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||||
xmlns:views="clr-namespace:LehrerApp.Desktop.Views"
|
||||
x:Class="LehrerApp.Desktop.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Title="LehrerApp"
|
||||
Width="1280" Height="800"
|
||||
MinWidth="900" MinHeight="600">
|
||||
|
||||
<Grid ColumnDefinitions="220,*">
|
||||
|
||||
<!-- ── Sidebar ───────────────────────────────────────────────────────── -->
|
||||
<Border Grid.Column="0"
|
||||
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,1,0">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<!-- Header -->
|
||||
<Border DockPanel.Dock="Top" Padding="16,20,16,12"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<StackPanel>
|
||||
<TextBlock Text="LehrerApp"
|
||||
FontSize="20" FontWeight="SemiBold" />
|
||||
<TextBlock Text="{Binding CurrentSchoolYear, FallbackValue=''}"
|
||||
FontSize="12" Opacity="0.6" Margin="0,2,0,0"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Sync-Status unten -->
|
||||
<Border DockPanel.Dock="Bottom" Padding="12,8"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,1,0,0">
|
||||
<views:SyncStatusBar />
|
||||
</Border>
|
||||
|
||||
<!-- Nav-Items -->
|
||||
<StackPanel Margin="8,12">
|
||||
<views:NavButton Icon="" Label="Dashboard"
|
||||
Item="Dashboard"
|
||||
ActiveItem="{Binding ActiveNavItem}"
|
||||
Command="{Binding NavigateToCommand}"
|
||||
CommandParameter="{x:Static vm:NavItem.Dashboard}" />
|
||||
|
||||
<TextBlock Text="UNTERRICHT" FontSize="10" FontWeight="Bold"
|
||||
Opacity="0.4" Margin="8,16,0,4" />
|
||||
|
||||
<views:NavButton Icon="" Label="Lerngruppen"
|
||||
Item="Groups"
|
||||
ActiveItem="{Binding ActiveNavItem}"
|
||||
Command="{Binding NavigateToCommand}"
|
||||
CommandParameter="{x:Static vm:NavItem.Groups}" />
|
||||
|
||||
<views:NavButton Icon="" Label="Schüler"
|
||||
Item="Students"
|
||||
ActiveItem="{Binding ActiveNavItem}"
|
||||
Command="{Binding NavigateToCommand}"
|
||||
CommandParameter="{x:Static vm:NavItem.Students}" />
|
||||
|
||||
<views:NavButton Icon="" Label="Klausuren"
|
||||
Item="Exams"
|
||||
ActiveItem="{Binding ActiveNavItem}"
|
||||
Command="{Binding NavigateToCommand}"
|
||||
CommandParameter="{x:Static vm:NavItem.Exams}" />
|
||||
|
||||
<views:NavButton Icon="" Label="Planung"
|
||||
Item="Planner"
|
||||
ActiveItem="{Binding ActiveNavItem}"
|
||||
Command="{Binding NavigateToCommand}"
|
||||
CommandParameter="{x:Static vm:NavItem.Planner}" />
|
||||
|
||||
<TextBlock Text="VERWALTUNG" FontSize="10" FontWeight="Bold"
|
||||
Opacity="0.4" Margin="8,16,0,4" />
|
||||
|
||||
<views:NavButton Icon="" Label="Arbeitszeit"
|
||||
Item="Workload"
|
||||
ActiveItem="{Binding ActiveNavItem}"
|
||||
Command="{Binding NavigateToCommand}"
|
||||
CommandParameter="{x:Static vm:NavItem.Workload}" />
|
||||
|
||||
<views:NavButton Icon="" Label="Einstellungen"
|
||||
Item="Settings"
|
||||
ActiveItem="{Binding ActiveNavItem}"
|
||||
Command="{Binding NavigateToCommand}"
|
||||
CommandParameter="{x:Static vm:NavItem.Settings}" />
|
||||
</StackPanel>
|
||||
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ── Hauptinhalt ───────────────────────────────────────────────────── -->
|
||||
<ContentControl Grid.Column="1"
|
||||
Content="{Binding CurrentPage}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="vm:DashboardViewModel">
|
||||
<views:DashboardView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type vm:PlaceholderViewModel}">
|
||||
<views:PlaceholderView />
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
11
LehrerApp.Desktop/Views/MainWindow.axaml.cs
Normal file
11
LehrerApp.Desktop/Views/MainWindow.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace LehrerApp.Desktop.Views;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
38
LehrerApp.Desktop/Views/NavButton.axaml
Normal file
38
LehrerApp.Desktop/Views/NavButton.axaml
Normal file
@@ -0,0 +1,38 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||||
x:Class="LehrerApp.Desktop.Views.NavButton">
|
||||
|
||||
<Button Command="{Binding Command, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding CommandParameter, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Padding="10,8"
|
||||
CornerRadius="6"
|
||||
Background="Transparent">
|
||||
|
||||
<Grid ColumnDefinitions="24,*">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding Icon, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="14"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Opacity="0.7"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding Label, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
FontSize="13"
|
||||
VerticalAlignment="Center"
|
||||
Margin="8,0,0,0"/>
|
||||
</Grid>
|
||||
|
||||
<Button.Styles>
|
||||
<Style Selector="Button:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource SystemControlBackgroundListLowBrush}"/>
|
||||
</Style>
|
||||
</Button.Styles>
|
||||
|
||||
</Button>
|
||||
|
||||
</UserControl>
|
||||
69
LehrerApp.Desktop/Views/NavButton.axaml.cs
Normal file
69
LehrerApp.Desktop/Views/NavButton.axaml.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using System.Windows.Input;
|
||||
using LehrerApp.Desktop.ViewModels;
|
||||
|
||||
namespace LehrerApp.Desktop.Views;
|
||||
|
||||
public partial class NavButton : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<string> IconProperty =
|
||||
AvaloniaProperty.Register<NavButton, string>(nameof(Icon), "");
|
||||
|
||||
public static readonly StyledProperty<string> LabelProperty =
|
||||
AvaloniaProperty.Register<NavButton, string>(nameof(Label), "");
|
||||
|
||||
public static readonly StyledProperty<NavItem> ItemProperty =
|
||||
AvaloniaProperty.Register<NavButton, NavItem>(nameof(Item));
|
||||
|
||||
public static readonly StyledProperty<NavItem> ActiveItemProperty =
|
||||
AvaloniaProperty.Register<NavButton, NavItem>(nameof(ActiveItem));
|
||||
|
||||
public static readonly StyledProperty<ICommand?> CommandProperty =
|
||||
AvaloniaProperty.Register<NavButton, ICommand?>(nameof(Command));
|
||||
|
||||
public static readonly StyledProperty<object?> CommandParameterProperty =
|
||||
AvaloniaProperty.Register<NavButton, object?>(nameof(CommandParameter));
|
||||
|
||||
public string Icon
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
}
|
||||
|
||||
public string Label
|
||||
{
|
||||
get => GetValue(LabelProperty);
|
||||
set => SetValue(LabelProperty, value);
|
||||
}
|
||||
|
||||
public NavItem Item
|
||||
{
|
||||
get => GetValue(ItemProperty);
|
||||
set => SetValue(ItemProperty, value);
|
||||
}
|
||||
|
||||
public NavItem ActiveItem
|
||||
{
|
||||
get => GetValue(ActiveItemProperty);
|
||||
set => SetValue(ActiveItemProperty, value);
|
||||
}
|
||||
|
||||
public ICommand? Command
|
||||
{
|
||||
get => GetValue(CommandProperty);
|
||||
set => SetValue(CommandProperty, value);
|
||||
}
|
||||
|
||||
public object? CommandParameter
|
||||
{
|
||||
get => GetValue(CommandParameterProperty);
|
||||
set => SetValue(CommandParameterProperty, value);
|
||||
}
|
||||
|
||||
public NavButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
13
LehrerApp.Desktop/Views/PlaceholderView.axaml
Normal file
13
LehrerApp.Desktop/Views/PlaceholderView.axaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<!-- PlaceholderView.axaml -->
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||||
x:Class="LehrerApp.Desktop.Views.PlaceholderView"
|
||||
x:DataType="vm:PlaceholderViewModel">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="8">
|
||||
<TextBlock Text="{Binding Title}" FontSize="24" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="Wird noch implementiert…" Opacity="0.5"
|
||||
HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
148
LehrerApp.Desktop/Views/Students/StudentDetailView.axaml
Normal file
148
LehrerApp.Desktop/Views/Students/StudentDetailView.axaml
Normal file
@@ -0,0 +1,148 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Students"
|
||||
x:Class="LehrerApp.Desktop.Views.Students.StudentDetailView"
|
||||
x:DataType="vm:StudentDetailViewModel">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
|
||||
<!-- ── Header ──────────────────────────────────────────────────────── -->
|
||||
<Border Grid.Row="0" Padding="20,16"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
|
||||
<!-- Anzeigemodus -->
|
||||
<StackPanel Grid.Column="0"
|
||||
IsVisible="{Binding !IsEditing}">
|
||||
<TextBlock Text="{Binding StudentTitle}"
|
||||
FontSize="22" FontWeight="SemiBold"/>
|
||||
<TextBlock Text="{Binding Student.DateOfBirth,
|
||||
StringFormat='Geb. {0:dd.MM.yyyy}',
|
||||
FallbackValue=''}"
|
||||
FontSize="12" Opacity="0.5"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Bearbeitungsmodus -->
|
||||
<StackPanel Grid.Column="0" Spacing="6"
|
||||
IsVisible="{Binding IsEditing}">
|
||||
<Grid ColumnDefinitions="*,8,*">
|
||||
<TextBox Grid.Column="0"
|
||||
Text="{Binding EditFirstName}"
|
||||
Watermark="Vorname"/>
|
||||
<TextBox Grid.Column="2"
|
||||
Text="{Binding EditLastName}"
|
||||
Watermark="Nachname"/>
|
||||
</Grid>
|
||||
<TextBox Text="{Binding EditNotes}"
|
||||
Watermark="Interne Notiz (optional)"
|
||||
AcceptsReturn="True" MaxHeight="80"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Aktions-Buttons -->
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8"
|
||||
VerticalAlignment="Top">
|
||||
<Button Content="Bearbeiten"
|
||||
Command="{Binding StartEditCommand}"
|
||||
IsVisible="{Binding !IsEditing}"/>
|
||||
<Button Content="Speichern"
|
||||
Command="{Binding SaveEditCommand}"
|
||||
IsVisible="{Binding IsEditing}"/>
|
||||
<Button Content="Abbrechen"
|
||||
Command="{Binding CancelEditCommand}"
|
||||
IsVisible="{Binding IsEditing}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Tab-Leiste ──────────────────────────────────────────────────── -->
|
||||
<Border Grid.Row="1"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,0,1" Padding="16,0">
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<Button Content="Übersicht"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:StudentTab.Overview}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
<Button Content="Noten"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:StudentTab.Grades}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
<Button Content="Dokumentation"
|
||||
Command="{Binding SwitchTabCommand}"
|
||||
CommandParameter="{x:Static vm:StudentTab.Documentation}"
|
||||
Background="Transparent" Padding="12,8"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ── Tab-Inhalt ──────────────────────────────────────────────────── -->
|
||||
<ScrollViewer Grid.Row="2" Padding="20">
|
||||
|
||||
<!-- Übersicht: Lerngruppen-Verlauf -->
|
||||
<StackPanel IsVisible="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:StudentTab.Overview}}"
|
||||
Spacing="16">
|
||||
|
||||
<TextBlock Text="Lerngruppen" FontSize="15" FontWeight="SemiBold"/>
|
||||
<ItemsControl ItemsSource="{Binding Enrollments}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:EnrollmentEntry">
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="6" Padding="12,8" Margin="0,0,0,6">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding SchoolYear}"
|
||||
FontWeight="SemiBold" Width="70"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding GroupName}"
|
||||
Margin="8,0"/>
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding Subject}"
|
||||
Opacity="0.5" FontSize="12"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Text="{Binding Student.Notes}"
|
||||
IsVisible="{Binding Student.Notes,
|
||||
Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||
Opacity="0.7" FontSize="13"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Dokumentation -->
|
||||
<ItemsControl IsVisible="{Binding ActiveTab,
|
||||
Converter={x:Static ObjectConverters.Equal},
|
||||
ConverterParameter={x:Static vm:StudentTab.Documentation}}"
|
||||
ItemsSource="{Binding Documentation}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="vm:DocEntry">
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="6" Padding="12,10" Margin="0,0,0,8">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{Binding Date}"
|
||||
Opacity="0.5" FontSize="12" Width="80"/>
|
||||
<StackPanel Grid.Column="1" Margin="8,0">
|
||||
<TextBlock Text="{Binding Title}"
|
||||
FontWeight="SemiBold" FontSize="13"/>
|
||||
<TextBlock Text="{Binding TypeLabel}"
|
||||
FontSize="11" Opacity="0.5"/>
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="🔒" FontSize="14"
|
||||
IsVisible="{Binding IsConfidential}"
|
||||
ToolTip.Tip="Vertraulich"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
63
LehrerApp.Desktop/Views/Students/StudentListView.axaml
Normal file
63
LehrerApp.Desktop/Views/Students/StudentListView.axaml
Normal file
@@ -0,0 +1,63 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Students"
|
||||
x:Class="LehrerApp.Desktop.Views.Students.StudentListView"
|
||||
x:DataType="vm:StudentListViewModel">
|
||||
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
|
||||
<!-- ── Toolbar ─────────────────────────────────────────────────────── -->
|
||||
<Border Grid.Row="0" Padding="20,16"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="*,Auto,Auto">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="Schüler" FontSize="22" FontWeight="SemiBold"/>
|
||||
<TextBlock FontSize="12" Opacity="0.5">
|
||||
<Run Text="{Binding Students.Count}"/>
|
||||
<Run Text="Schüler gesamt"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox Grid.Column="1"
|
||||
Content="Inaktive anzeigen"
|
||||
IsChecked="{Binding ShowInactive}"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,12,0"/>
|
||||
|
||||
<Button Grid.Column="2"
|
||||
Content="+ Neuer Schüler"
|
||||
Command="{Binding AddStudentCommand}"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Liste + Suche ───────────────────────────────────────────────── -->
|
||||
<DockPanel Grid.Row="1">
|
||||
<TextBox DockPanel.Dock="Top"
|
||||
Text="{Binding SearchText}"
|
||||
Watermark="Name suchen…"
|
||||
Margin="16,10,16,4"/>
|
||||
|
||||
<DataGrid ItemsSource="{Binding Students}"
|
||||
SelectedItem="{Binding SelectedStudent}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeColumns="True"
|
||||
Margin="16,4">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Name"
|
||||
Binding="{Binding FullName}"
|
||||
Width="*"/>
|
||||
<DataGridTextColumn Header="Geburtsdatum"
|
||||
Binding="{Binding DateOfBirth}"
|
||||
Width="130"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
13
LehrerApp.Desktop/Views/Students/StudentViews.cs
Normal file
13
LehrerApp.Desktop/Views/Students/StudentViews.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Students;
|
||||
|
||||
public partial class StudentListView : UserControl
|
||||
{
|
||||
public StudentListView() => InitializeComponent();
|
||||
}
|
||||
|
||||
public partial class StudentDetailView : UserControl
|
||||
{
|
||||
public StudentDetailView() => InitializeComponent();
|
||||
}
|
||||
24
LehrerApp.Desktop/Views/SyncStatusBar.axaml
Normal file
24
LehrerApp.Desktop/Views/SyncStatusBar.axaml
Normal file
@@ -0,0 +1,24 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||||
x:Class="LehrerApp.Desktop.Views.SyncStatusBar"
|
||||
x:DataType="vm:SyncStatusViewModel">
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="{Binding StatusText}" FontSize="12"
|
||||
Opacity="0.7" TextTrimming="CharacterEllipsis"/>
|
||||
<TextBlock Text="{Binding LastSyncText}" FontSize="10"
|
||||
Opacity="0.4"/>
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1"
|
||||
Command="{Binding SyncNowCommand}"
|
||||
IsVisible="{Binding IsServerConfigured}"
|
||||
ToolTip.Tip="Jetzt synchronisieren"
|
||||
Padding="6,4">
|
||||
<TextBlock Text="↻" FontSize="14"
|
||||
IsVisible="{Binding !IsSyncing}"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
20
LehrerApp.Desktop/Views/SyncStatusBar.axaml.cs
Normal file
20
LehrerApp.Desktop/Views/SyncStatusBar.axaml.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Avalonia.Controls;
|
||||
using LehrerApp.Desktop.ViewModels;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace LehrerApp.Desktop.Views;
|
||||
|
||||
public partial class SyncStatusBar : UserControl
|
||||
{
|
||||
public SyncStatusBar()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// DataContext aus DI holen sobald die View geladen ist
|
||||
Loaded += (_, _) =>
|
||||
{
|
||||
if (DataContext is null)
|
||||
DataContext = App.Services.GetRequiredService<SyncStatusViewModel>();
|
||||
};
|
||||
}
|
||||
}
|
||||
17
LehrerApp.Desktop/Views/ViewCodeBehind.cs
Normal file
17
LehrerApp.Desktop/Views/ViewCodeBehind.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace LehrerApp.Desktop.Views;
|
||||
|
||||
// Code-behind Stubs für Views ohne eigene .axaml.cs
|
||||
// NavButton → eigene NavButton.axaml.cs
|
||||
// SyncStatusBar → eigene SyncStatusBar.axaml.cs
|
||||
|
||||
public partial class DashboardView : UserControl
|
||||
{
|
||||
public DashboardView() => InitializeComponent();
|
||||
}
|
||||
|
||||
public partial class PlaceholderView : UserControl
|
||||
{
|
||||
public PlaceholderView() => InitializeComponent();
|
||||
}
|
||||
Reference in New Issue
Block a user