last changes

This commit is contained in:
ViperioN1339 2025-06-21 11:32:41 +02:00
parent 8ca1fb91dd
commit b617d39c8f
19 changed files with 236 additions and 144 deletions

View File

@ -6,6 +6,7 @@
<entry key="ChronoFlow.View/Admin/AdminMainView.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
<entry key="ChronoFlow.View/Admin/ConfirmDialog.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
<entry key="ChronoFlow.View/Admin/MitarbeiterListeView.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
<entry key="ChronoFlow.View/Admin/ProjektErstellenView.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
<entry key="ChronoFlow.View/App.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
<entry key="ChronoFlow.View/LoginView.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
<entry key="ChronoFlow.View/LoginWindow.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />

View File

@ -22,5 +22,6 @@ namespace ChronoFlow.Model
Abteilung = "";
OriginalUsername = "";
}
public DateTime LetzterLogin { get; set; } = DateTime.MinValue;
}
}

View File

@ -37,5 +37,8 @@ namespace ChronoFlow.Model
return "Green";
}
}
public DateTime LetzteBearbeitung { get; set; }
public bool IstNeu { get; set; } // wird im ViewModel gesetzt
public bool WurdeSeitLoginBearbeitet { get; set; }
}
}

View File

@ -92,6 +92,7 @@ namespace ChronoFlow.Persistence
AddColumnIfMissing(connection, "Benutzer", "Mitarbeitennummer", "TEXT");
AddColumnIfMissing(connection, "Benutzer", "Abteilung", "TEXT");
AddColumnIfMissing(connection, "Benutzer", "MussPasswortAendern", "INTEGER DEFAULT 1");
AddColumnIfMissing(connection, "Zeiteintraege", "LetzteBearbeitung", "TEXT");
}
private void AddColumnIfMissing(SqliteConnection connection, string tableName, string columnName, string columnType)
@ -247,9 +248,10 @@ namespace ChronoFlow.Persistence
var cmd = connection.CreateCommand();
cmd.CommandText = @"
INSERT INTO Zeiteintraege
(Mitarbeiter, Startzeit, Endzeit, Projekt, Kommentar, Erledigt, MitarbeiterKommentar)
VALUES ($Mitarbeiter, $Startzeit, $Endzeit, $Projekt, $Kommentar, $Erledigt, $MitarbeiterKommentar);
";
(Mitarbeiter, Startzeit, Endzeit, Projekt, Kommentar, Erledigt, MitarbeiterKommentar, LetzteBearbeitung)
VALUES
($Mitarbeiter, $Startzeit, $Endzeit, $Projekt, $Kommentar, $Erledigt, $MitarbeiterKommentar, $LetzteBearbeitung);";
cmd.Parameters.AddWithValue("$Mitarbeiter", eintrag.Mitarbeiter);
cmd.Parameters.AddWithValue("$Startzeit", eintrag.Startzeit.ToString("o"));
@ -258,6 +260,7 @@ namespace ChronoFlow.Persistence
cmd.Parameters.AddWithValue("$Kommentar", eintrag.Kommentar ?? "");
cmd.Parameters.AddWithValue("$Erledigt", eintrag.Erledigt ? 1 : 0);
cmd.Parameters.AddWithValue("$MitarbeiterKommentar", eintrag.MitarbeiterKommentar ?? "");
cmd.Parameters.AddWithValue("$LetzteBearbeitung", DateTime.Now.ToString("o"));
cmd.ExecuteNonQuery();
@ -302,13 +305,13 @@ namespace ChronoFlow.Persistence
cmd.CommandText = @"
UPDATE Zeiteintraege
SET Projekt = $Projekt,
Kommentar = $Kommentar,
Startzeit = $Startzeit,
Endzeit = $Endzeit,
Mitarbeiter = $Mitarbeiter,
Erledigt = $Erledigt
WHERE Id = $Id;
";
Kommentar = $Kommentar,
Startzeit = $Startzeit,
Endzeit = $Endzeit,
Mitarbeiter = $Mitarbeiter,
Erledigt = $Erledigt,
LetzteBearbeitung = $LetzteBearbeitung
WHERE Id = $Id;";
cmd.Parameters.AddWithValue("$Projekt", projekt.Projekt);
cmd.Parameters.AddWithValue("$Kommentar", projekt.Kommentar ?? "");
@ -317,6 +320,7 @@ namespace ChronoFlow.Persistence
cmd.Parameters.AddWithValue("$Mitarbeiter", projekt.Mitarbeiter);
cmd.Parameters.AddWithValue("$Erledigt", projekt.Erledigt ? 1 : 0);
cmd.Parameters.AddWithValue("$Id", projekt.Id);
cmd.Parameters.AddWithValue("$LetzteBearbeitung", DateTime.Now.ToString("o"));
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"✏ Projekt aktualisiert (Id={projekt.Id}, Rows affected: {rowsAffected})");
@ -464,34 +468,39 @@ namespace ChronoFlow.Persistence
Console.WriteLine($"🔒 Passwort für Benutzer '{username}' zurückgesetzt (Rows affected: {rowsAffected})");
}
public async Task<List<Zeiteintrag>> GetEintraegeFuerMitarbeiterAsync(string mitarbeiterName)
public async Task<List<Zeiteintrag>> GetEintraegeFuerMitarbeiterAsync(string name)
{
var eintraege = new List<Zeiteintrag>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
await connection.OpenAsync();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
SELECT * FROM Zeiteintraege
WHERE Mitarbeiter = $Mitarbeiter;
";
cmd.Parameters.AddWithValue("$Mitarbeiter", mitarbeiterName);
SELECT Id, Mitarbeiter, Startzeit, Endzeit, Projekt, Kommentar, Erledigt, MitarbeiterKommentar, LetzteBearbeitung
FROM Zeiteintraege
WHERE Mitarbeiter = $Name;
";
cmd.Parameters.AddWithValue("$Name", name);
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
eintraege.Add(new Zeiteintrag
{
Id = reader.GetInt32(0),
Mitarbeiter = reader.GetString(1),
Startzeit = DateTime.Parse(reader.GetString(2)),
Endzeit = DateTime.Parse(reader.GetString(3)),
Startzeit = reader.GetDateTime(2),
Endzeit = reader.GetDateTime(3),
Projekt = reader.GetString(4),
Kommentar = reader.GetString(5),
Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
MitarbeiterKommentar = reader.GetString(7)
Erledigt = reader.GetBoolean(6),
MitarbeiterKommentar = reader.GetString(7),
LetzteBearbeitung = reader.IsDBNull(8) ? DateTime.MinValue : reader.GetDateTime(8)
});
}
return eintraege;
}
@ -502,19 +511,22 @@ namespace ChronoFlow.Persistence
var cmd = connection.CreateCommand();
cmd.CommandText = @"
UPDATE Zeiteintraege
SET Erledigt = $Erledigt,
MitarbeiterKommentar = $Kommentar
WHERE Id = $Id;
";
UPDATE Zeiteintraege
SET Erledigt = $Erledigt,
MitarbeiterKommentar = $Kommentar,
LetzteBearbeitung = $Bearbeitet
WHERE Id = $Id;
";
cmd.Parameters.AddWithValue("$Erledigt", erledigt ? 1 : 0);
cmd.Parameters.AddWithValue("$Kommentar", mitarbeiterKommentar ?? "");
cmd.Parameters.AddWithValue("$Bearbeitet", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
cmd.Parameters.AddWithValue("$Id", id);
int rowsAffected = await cmd.ExecuteNonQueryAsync();
Console.WriteLine($"✏ Zeiteintrag (Id={id}) aktualisiert: erledigt={erledigt}, kommentar gesetzt.");
Console.WriteLine($"✏ Zeiteintrag (Id={id}) aktualisiert: erledigt={erledigt}, LetzteBearbeitung gesetzt.");
}
}
}

View File

@ -3,57 +3,37 @@
xmlns:model="clr-namespace:ChronoFlow.Model;assembly=ChronoFlow.Model"
x:Class="ChronoFlow.View.Admin.AdminMainView">
<SplitView x:Name="AdminPane" DisplayMode="CompactInline" IsPaneOpen="True" CompactPaneLength="37" OpenPaneLength="200">
<DockPanel>
<!-- 🧭 Top-Menüleiste für Admins -->
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Background="Black" Margin="5" Spacing="10">
<Button Content="📋 Alle bestehenden Projekte" Click="AlleProjekte_Click"/>
<Button Content="👥 Mitarbeiterliste" Click="MitarbeiterListe_Click"/>
<Button Content="✅ Abgeschlossene Projekte" Click="AbgeschlosseneProjekte_Click"/>
<Button Content=" Mitarbeiter hinzufügen" Click="MitarbeiterHinzufuegen_Click"/>
<Button Content=" Projekt erstellen" Click="ProjektErstellen_Click"/>
<!-- Linke Sidebar (SplitView-Pane) -->
<SplitView.Pane>
<StackPanel>
<!-- Burger-Button -->
<Button Content="☰" Click="TogglePane_Click"/>
</StackPanel>
<!-- Navigation Buttons -->
<Button Content="🏠 Dashboard" Click="Dashboard_Click"/>
<Button Content="📋 Alle Projekte anzeigen" Click="AlleProjekte_Click"/>
<Button Content="👥 Mitarbeiter-Liste" Click="MitarbeiterListe_Click"/>
<Button Content="✅ Abgeschlossene Projekte" Click="AbgeschlosseneProjekte_Click" />
<Button Content="⚙ Einstellungen" Click="Einstellungen_Click"/>
</StackPanel>
</SplitView.Pane>
<!-- Hauptinhalt -->
<StackPanel Margin="20" Spacing="15">
<TextBlock Text="Admin-Dashboard" FontSize="24" FontWeight="Bold" HorizontalAlignment="Center"/>
<!-- Hauptinhalt -->
<SplitView.Content>
<StackPanel Margin="20" Spacing="15">
<!-- Überschrift -->
<TextBlock Text="Admin-Dashboard" FontSize="24" FontWeight="Bold" HorizontalAlignment="Center"/>
<TextBlock Text="Zuletzt hinzugefügte Projekte" FontSize="18" FontWeight="SemiBold" Margin="0,20,0,10"/>
<!-- Aktions-Buttons (oben) -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<Button Content=" Mitarbeiter hinzufügen" Width="200" Height="50" Click="MitarbeiterHinzufuegen_Click"/>
<Button Content=" Projekt erstellen" Width="200" Height="50" Click="ProjektErstellen_Click"/>
</StackPanel>
<!-- Anzeige der letzten Projekte -->
<TextBlock Text="Zuletzt hinzugefügte Projekte" FontSize="18" FontWeight="SemiBold" Margin="0,20,0,10"/>
<ItemsControl x:Name="LetzteProjekteListe">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type model:Zeiteintrag}">
<Border BorderBrush="Gray" BorderThickness="1" Padding="10" Margin="0,5">
<StackPanel>
<TextBlock Text="{Binding Projekt}" FontWeight="Bold"/>
<TextBlock Text="{Binding Mitarbeiter}"/>
<TextBlock Text="{Binding Startzeit, StringFormat='Start: {0:G}'}"/>
<TextBlock Text="{Binding Endzeit, StringFormat='Ende: {0:G}'}"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</SplitView.Content>
</SplitView>
<ItemsControl x:Name="LetzteProjekteListe">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type model:Zeiteintrag}">
<Border BorderBrush="Gray" BorderThickness="1" Padding="10" Margin="0,5">
<StackPanel>
<TextBlock Text="{Binding Projekt}" FontWeight="Bold"/>
<TextBlock Text="{Binding Mitarbeiter}"/>
<TextBlock Text="{Binding Startzeit, StringFormat='Start: {0:G}'}"/>
<TextBlock Text="{Binding Endzeit, StringFormat='Ende: {0:G}'}"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DockPanel>
</UserControl>

View File

@ -67,12 +67,6 @@ namespace ChronoFlow.View.Admin
{
_viewManager.Show("ProjektErstellen");
}
private void Dashboard_Click(object sender, RoutedEventArgs e)
{
_viewManager.Show("AdminMain");
}
private void AlleProjekte_Click(object sender, RoutedEventArgs e)
{
_viewManager.Show("AlleProjekte");
@ -83,15 +77,9 @@ namespace ChronoFlow.View.Admin
_viewManager.Show("MitarbeiterListe");
}
private void Einstellungen_Click(object sender, RoutedEventArgs e)
{
_viewManager.Show("Einstellungen");
}
private void TogglePane_Click(object sender, RoutedEventArgs e)
{
AdminPane.IsPaneOpen = !AdminPane.IsPaneOpen;
}
public void AktualisiereLetzteProjekte()
{
@ -102,5 +90,7 @@ namespace ChronoFlow.View.Admin
{
_viewManager.Show("AbgeschlosseneProjekte");
}
}
}

View File

@ -3,8 +3,8 @@
x:Class="ChronoFlow.View.Admin.MitarbeiterBearbeitenDialog"
Width="450" Height="600"
Title="Mitarbeiter bearbeiten">
<StackPanel Margin="20" Spacing="10">
<ScrollViewer>
<StackPanel Margin="20" Spacing="15">
<TextBlock Text="Username:" />
<TextBox x:Name="UsernameBox" />
@ -28,4 +28,5 @@
IsVisible="False"
Margin="0,10,0,0" />
</StackPanel>
</ScrollViewer>
</Window>

View File

@ -4,7 +4,8 @@
Width="500" Height="600"
Title="Projekt bearbeiten">
<StackPanel Margin="20" Spacing="12">
<ScrollViewer>
<StackPanel Margin="20" Spacing="15">
<TextBlock Text="Projektname:" />
<TextBox x:Name="ProjektnameBox" />
@ -25,4 +26,5 @@
<Button Content="❌ Abbrechen" Width="130" Click="AbbrechenButton_Click" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</Window>

View File

@ -2,7 +2,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ChronoFlow.View.Admin.ProjektErstellenView">
<StackPanel Margin="20" Spacing="10">
<ScrollViewer>
<StackPanel Margin="20" Spacing="15">
<TextBlock Text="Neues Projekt erstellen" FontSize="20" FontWeight="Bold" HorizontalAlignment="Center" />
@ -29,11 +30,12 @@
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center" Margin="0,10,0,0">
<Button Content="✅ Speichern" Click="SpeichernButton_Click" Width="115" />
<Button Content="⬅ Zurück zum Dashboard" Click="ZurueckButton_Click" Width="150" />
<Button Content="⬅ Zurück zum Dashboard" Click="ZurueckButton_Click" Width="180" />
</StackPanel>
<TextBlock x:Name="FeedbackText" Foreground="Red" IsVisible="False" />
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@ -1,8 +1,15 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:themes="clr-namespace:Avalonia.Themes.Fluent;assembly=Avalonia.Themes.Fluent"
x:Class="ChronoFlow.App"
RequestedThemeVariant="Default">
xmlns:conv="clr-namespace:ChronoFlow.View.Converter"
x:Class="ChronoFlow.App">
<Application.Resources>
<conv:BoolToBrushConverter x:Key="BoolToBrushConverter"
TrueBrush="Blue"
FalseBrush="Gray"/>
</Application.Resources>
<Application.Styles>
<themes:FluentTheme />
</Application.Styles>

View File

@ -13,6 +13,9 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="MessageBox.Avalonia" Version="0.10.4" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.6" />
<PackageReference Include="ReactiveUI" Version="20.3.1" />
<PackageReference Include="System.Reactive" Version="6.0.1" />
<PackageReference Include="WCKY.Avalonia.AnimationLibrary" Version="1.0.0" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,24 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;
using Avalonia.Media;
namespace ChronoFlow.View.Converter
{
public class BoolToBrushConverter : IValueConverter
{
public IBrush TrueBrush { get; set; } = Brushes.Blue;
public IBrush FalseBrush { get; set; } = Brushes.Gray;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool b)
return b ? TrueBrush : FalseBrush;
return FalseBrush;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
throw new NotSupportedException();
}
}

View File

@ -106,6 +106,7 @@ namespace ChronoFlow.View
try
{
Console.WriteLine("🚀 Öffne MainWindow...");
user.LetzterLogin = DateTime.Now;
var main = new MainWindow(user);
main.Show();
Console.WriteLine("✅ MainWindow wurde geöffnet.");
@ -120,5 +121,6 @@ namespace ChronoFlow.View
ErrorText.IsVisible = true;
}
}
}
}

View File

@ -5,9 +5,18 @@
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="600"
x:Class="ChronoFlow.View.MainWindow"
Title="ChronoFlow">
<DockPanel LastChildFill="True">
<Button Content="🔓 Logout"
HorizontalAlignment="Right"
Margin="5"
Padding="8,4"
Click="Logout_Click"
DockPanel.Dock="Top"
Background="Transparent"
BorderBrush="Gray"/>
<Grid>
<ContentControl x:Name="ContentArea" />
</Grid>
</DockPanel>
</Window>

View File

@ -2,6 +2,7 @@ using System;
using Avalonia.Controls;
using Avalonia.Interactivity;
using ChronoFlow.Model;
using ChronoFlow.Persistence;
using ChronoFlow.View.Admin;
using ChronoFlow.View.Mitarbeiter;
@ -27,7 +28,8 @@ namespace ChronoFlow.View
_viewManager.Register("AlleProjekte", () => new AlleProjekteView(_viewManager));
_viewManager.Register("MitarbeiterListe", () => new MitarbeiterListeView(_viewManager));
_viewManager.Register("AbgeschlosseneProjekte", () => new AbgeschlosseneProjekteView(_viewManager));
_viewManager.Register("Zeiterfassung", () => new EmployeeTasksView(_loggedInUser.Username));
_viewManager.Register("Zeiterfassung", () =>
new EmployeeTasksView(_loggedInUser, new SqliteZeiterfassungsService()));
if (_loggedInUser.Role == "Admin")
{
@ -60,5 +62,12 @@ namespace ChronoFlow.View
{
_viewManager.Show("AdminMain");
}
private void Logout_Click(object? sender, RoutedEventArgs e)
{
var loginWindow = new LoginWindow();
loginWindow.Show();
this.Close(); // Aktuelles Fenster schließen
}
}
}

View File

@ -1,28 +1,45 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ChronoFlow.ViewModels.Mitarbeiter"
xmlns:converter="clr-namespace:ChronoFlow.View.Converter"
x:Class="ChronoFlow.View.Mitarbeiter.EmployeeTasksView">
<StackPanel Margin="20" Spacing="10">
<TextBlock Text="Meine Aufgaben" FontSize="24" FontWeight="Bold"/>
<UserControl.Resources>
<converter:BoolToBrushConverter x:Key="BoolToBrushConverter"/>
</UserControl.Resources>
<ScrollViewer>
<StackPanel Margin="20" Spacing="10">
<TextBlock Text="Meine Aufgaben" FontSize="24" FontWeight="Bold"/>
<ItemsControl ItemsSource="{Binding Eintraege}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Gray" CornerRadius="4" Padding="10" Margin="5">
<StackPanel Spacing="5">
<TextBlock Text="{Binding Projekt}" FontWeight="Bold"/>
<CheckBox Content="Erledigt" IsChecked="{Binding Erledigt}"/>
<TextBox Text="{Binding MitarbeiterKommentar}" Watermark="Kommentar hinzufügen..."/>
<TextBlock Text="{Binding Endzeit, StringFormat='Deadline: {0:dd.MM.yyyy}'}"
Foreground="{Binding PrioritaetsFarbe}"
FontWeight="Bold" FontSize="14"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- 🟢 Der Hinweis kommt vor dem ItemsControl -->
<TextBlock Text="🎉 Du hast aktuell keine Aufgaben!"
FontSize="16"
FontStyle="Italic"
FontWeight="Medium"
HorizontalAlignment="Center"
IsVisible="{Binding HatKeineEintraege}"/>
<Button Content="Änderungen speichern" Command="{Binding SpeichereEintraegeCommand}"/>
<TextBlock Text="{Binding StatusText}" Foreground="Green" FontStyle="Italic"/>
</StackPanel>
<!-- 📝 Die eigentliche Aufgabenliste -->
<ItemsControl ItemsSource="{Binding Eintraege}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{Binding WurdeSeitLoginBearbeitet, Converter={StaticResource BoolToBrushConverter}}"
BorderThickness="1" CornerRadius="4" Padding="10" Margin="5">
<StackPanel Spacing="5">
<TextBlock Text="{Binding Projekt}" FontWeight="Bold"/>
<CheckBox Content="Erledigt" IsChecked="{Binding Erledigt}"/>
<TextBox Text="{Binding MitarbeiterKommentar}" Watermark="Kommentar hinzufügen..."/>
<TextBlock Text="{Binding Endzeit, StringFormat='Deadline: {0:dd.MM.yyyy}'}"
Foreground="{Binding PrioritaetsFarbe}"
FontWeight="Bold" FontSize="14"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Content="Änderungen speichern" Command="{Binding SpeichereEintraegeCommand}"/>
<TextBlock Text="{Binding StatusText}" Foreground="Green" FontStyle="Italic"/>
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@ -1,20 +1,16 @@
using Avalonia.Controls;
using ChronoFlow.ViewModels.Mitarbeiter;
using ChronoFlow.Persistence;
using ChronoFlow.Model;
namespace ChronoFlow.View.Mitarbeiter
{
public partial class EmployeeTasksView : UserControl
{
public EmployeeTasksView(string benutzername)
public EmployeeTasksView(User user, IZeiterfassungsRepository repository)
{
InitializeComponent();
// Benutzername dynamisch übergeben
DataContext = new EmployeeTasksViewModel(
new SqliteZeiterfassungsService(),
benutzername
);
DataContext = new EmployeeTasksViewModel(user, repository);
}
}
}

View File

@ -1,4 +1,6 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@ -9,46 +11,75 @@ namespace ChronoFlow.ViewModels.Mitarbeiter
{
public partial class EmployeeTasksViewModel : ObservableObject
{
// Liste aller Zeiteinträge für den aktuell eingeloggten Mitarbeiter
private readonly User _benutzer;
private readonly IZeiterfassungsRepository _repository;
private readonly string aktuellerBenutzername;
[ObservableProperty]
private ObservableCollection<Zeiteintrag> eintraege = new();
// Ausgabe für Erfolg/Nachricht
[ObservableProperty]
private string? statusText;
private readonly IZeiterfassungsRepository repository;
private readonly string aktuellerBenutzername;
public bool HatKeineEintraege => Eintraege.Count == 0;
// Konstruktor erhält Repository (z.B. SqliteZeiterfassungsService) + aktuellen Benutzernamen
public EmployeeTasksViewModel(IZeiterfassungsRepository repository, string aktuellerBenutzername)
partial void OnEintraegeChanged(ObservableCollection<Zeiteintrag>? oldValue, ObservableCollection<Zeiteintrag> newValue)
{
this.repository = repository;
this.aktuellerBenutzername = aktuellerBenutzername;
// Direkt beim Start laden
_ = LadeEintraegeAsync();
OnPropertyChanged(nameof(HatKeineEintraege));
}
public EmployeeTasksViewModel(User benutzer, IZeiterfassungsRepository repository)
{
_benutzer = benutzer;
_repository = repository;
aktuellerBenutzername = benutzer.Username;
Console.WriteLine($"[DEBUG] ViewModel erstellt für Benutzer: {aktuellerBenutzername}");
_ = LadeEintraegeAsync(); // Lade Daten automatisch beim Öffnen
}
// Lädt alle Einträge für den Benutzer aus der Datenbank
[RelayCommand]
public async Task LadeEintraegeAsync()
{
var eintraegeAusDb = await repository.GetEintraegeFuerMitarbeiterAsync(aktuellerBenutzername);
Eintraege = new ObservableCollection<Zeiteintrag>(eintraegeAusDb);
StatusText = $"🔄 {Eintraege.Count} Einträge geladen.";
var eintraegeAusDb = await _repository.GetEintraegeFuerMitarbeiterAsync(aktuellerBenutzername);
var offene = eintraegeAusDb
.Where(e => !e.Erledigt)
.OrderBy(e => e.Endzeit)
.ToList();
// 🔔 Setze Markierung für geänderte Aufgaben
foreach (var eintrag in offene)
{
eintrag.WurdeSeitLoginBearbeitet = eintrag.LetzteBearbeitung > _benutzer.LetzterLogin;
// 🔍 Debug-Ausgabe zur Prüfung
Console.WriteLine($"[DEBUG] Eintrag {eintrag.Id}: Endzeit={eintrag.Endzeit}, LetzteBearbeitung={eintrag.LetzteBearbeitung}, LetzterLogin={_benutzer.LetzterLogin}, Markiert={eintrag.WurdeSeitLoginBearbeitet}");
}
if (offene.Any(e => e.WurdeSeitLoginBearbeitet))
StatusText = "📢 Es wurden Aufgaben seit Ihrem letzten Login geändert.";
Eintraege = new ObservableCollection<Zeiteintrag>(offene);
}
// Speichert Änderungen (Status + Kommentar) für alle sichtbaren Einträge
[RelayCommand]
public async Task SpeichereEintraegeAsync()
{
foreach (var eintrag in Eintraege)
{
await repository.UpdateStatusUndKommentarAsync(eintrag.Id, eintrag.Erledigt, eintrag.MitarbeiterKommentar);
await _repository.UpdateStatusUndKommentarAsync(
eintrag.Id,
eintrag.Erledigt,
eintrag.MitarbeiterKommentar
);
}
StatusText = "✅ Änderungen gespeichert.";
await LadeEintraegeAsync(); // automatisch neu laden
}
}
}
}

View File

@ -2,7 +2,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ChronoFlow.View.MitarbeiterHinzufuegenView">
<StackPanel Margin="20" Spacing="10">
<ScrollViewer>
<StackPanel Margin="20" Spacing="15">
<TextBlock Text=" Mitarbeiter hinzufügen" FontWeight="Bold" FontSize="20" HorizontalAlignment="Center"/>
<TextBox x:Name="UsernameBox" Watermark="Benutzername"/>
@ -20,4 +21,5 @@
<Button Content="⬅ Zurück zum Dashboard" Click="ZurueckZumDashboard_Click" HorizontalAlignment="Center" Margin="0,10,0,0"/>
<TextBlock x:Name="FeedbackText" Foreground="Green" IsVisible="False" TextAlignment="Center"/>
</StackPanel>
</ScrollViewer>
</UserControl>