diff --git a/.idea/.idea.ChronoFlow/.idea/avalonia.xml b/.idea/.idea.ChronoFlow/.idea/avalonia.xml
index e36ab00..9932faa 100644
--- a/.idea/.idea.ChronoFlow/.idea/avalonia.xml
+++ b/.idea/.idea.ChronoFlow/.idea/avalonia.xml
@@ -10,6 +10,9 @@
+
+
+
diff --git a/ChronoFlow.Model/Zeiteintrag.cs b/ChronoFlow.Model/Zeiteintrag.cs
index f0cdbc6..aaf11bb 100644
--- a/ChronoFlow.Model/Zeiteintrag.cs
+++ b/ChronoFlow.Model/Zeiteintrag.cs
@@ -23,5 +23,19 @@ namespace ChronoFlow.Model
Erledigt = false;
MitarbeiterKommentar = "";
}
+ public string PrioritaetsFarbe
+ {
+ get
+ {
+ var tageBisEnde = (Endzeit - DateTime.Now).TotalDays;
+
+ if (tageBisEnde <= 3)
+ return "Red";
+ else if (tageBisEnde <= 7)
+ return "DarkOrange";
+ else
+ return "Green";
+ }
+ }
}
}
\ No newline at end of file
diff --git a/ChronoFlow.Persistence/ITimeEntryRepository.cs b/ChronoFlow.Persistence/ITimeEntryRepository.cs
new file mode 100644
index 0000000..e02c5d4
--- /dev/null
+++ b/ChronoFlow.Persistence/ITimeEntryRepository.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using ChronoFlow.Model;
+
+namespace ChronoFlow.Persistence
+{
+ public interface ITimeEntryRepository
+ {
+ Task> GetEntriesForUserAsync(string username);
+ Task UpdateEntryStatusAndCommentAsync(int id, bool isCompleted, string? comment);
+
+ // (Optional) Weitere Methoden für Admin-Funktionen:
+ Task> GetAllEntriesAsync(); // Admin
+ Task AddEntryAsync(Zeiteintrag entry); // Admin
+ Task DeleteEntryAsync(int id); // Admin
+ }
+}
\ No newline at end of file
diff --git a/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs b/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs
index 8ba464e..3fa80eb 100644
--- a/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs
+++ b/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs
@@ -7,7 +7,12 @@ using ChronoFlow.Security;
namespace ChronoFlow.Persistence
{
- public class SqliteZeiterfassungsService
+ public interface IZeiterfassungsRepository
+ {
+ Task> GetEintraegeFuerMitarbeiterAsync(string mitarbeiterName);
+ Task UpdateStatusUndKommentarAsync(int id, bool erledigt, string mitarbeiterKommentar);
+ }
+ public class SqliteZeiterfassungsService : IZeiterfassungsRepository
{
private readonly string _dbPath = "chrono_data.sb";
@@ -458,5 +463,58 @@ namespace ChronoFlow.Persistence
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"🔒 Passwort für Benutzer '{username}' zurückgesetzt (Rows affected: {rowsAffected})");
}
+
+ public async Task> GetEintraegeFuerMitarbeiterAsync(string mitarbeiterName)
+ {
+ var eintraege = new List();
+ 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);
+
+ 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)),
+ Projekt = reader.GetString(4),
+ Kommentar = reader.GetString(5),
+ Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
+ MitarbeiterKommentar = reader.GetString(7)
+ });
+ }
+ return eintraege;
+ }
+
+ public async Task UpdateStatusUndKommentarAsync(int id, bool erledigt, string mitarbeiterKommentar)
+ {
+ using var connection = new SqliteConnection($"Data Source={_dbPath}");
+ await connection.OpenAsync();
+
+ var cmd = connection.CreateCommand();
+ cmd.CommandText = @"
+ UPDATE Zeiteintraege
+ SET Erledigt = $Erledigt,
+ MitarbeiterKommentar = $Kommentar
+ WHERE Id = $Id;
+ ";
+
+ cmd.Parameters.AddWithValue("$Erledigt", erledigt ? 1 : 0);
+ cmd.Parameters.AddWithValue("$Kommentar", mitarbeiterKommentar ?? "");
+ cmd.Parameters.AddWithValue("$Id", id);
+
+ int rowsAffected = await cmd.ExecuteNonQueryAsync();
+ Console.WriteLine($"✏ Zeiteintrag (Id={id}) aktualisiert: erledigt={erledigt}, kommentar gesetzt.");
+ }
+
}
-}
+}
\ No newline at end of file
diff --git a/ChronoFlow.View/Admin/ProjektErstellenView.axaml.cs b/ChronoFlow.View/Admin/ProjektErstellenView.axaml.cs
index 1e5a296..bcc5281 100644
--- a/ChronoFlow.View/Admin/ProjektErstellenView.axaml.cs
+++ b/ChronoFlow.View/Admin/ProjektErstellenView.axaml.cs
@@ -88,7 +88,7 @@ namespace ChronoFlow.View.Admin
MitarbeiterDropdown.SelectedItem = null;
// 🔄 Dashboard aktualisieren, wenn zurück
- if (_viewManager.TryGetView("AdminMain", out var adminView))
+ if (_viewManager.TryGetView("AdminMain", out var adminView) && adminView != null)
{
adminView.AktualisiereLetzteProjekte();
}
diff --git a/ChronoFlow.View/ChronoFlow.View.csproj b/ChronoFlow.View/ChronoFlow.View.csproj
index d109a1d..e987b80 100644
--- a/ChronoFlow.View/ChronoFlow.View.csproj
+++ b/ChronoFlow.View/ChronoFlow.View.csproj
@@ -10,6 +10,7 @@
+
@@ -26,6 +27,9 @@
MitarbeiterHinzufuegenView.axaml
Code
+
+ EmployeeTasksViewModel.axaml.axaml
+
diff --git a/ChronoFlow.View/MainWindow.axaml.cs b/ChronoFlow.View/MainWindow.axaml.cs
index 89aed83..0fd0e6c 100644
--- a/ChronoFlow.View/MainWindow.axaml.cs
+++ b/ChronoFlow.View/MainWindow.axaml.cs
@@ -3,6 +3,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using ChronoFlow.Model;
using ChronoFlow.View.Admin;
+using ChronoFlow.View.Mitarbeiter;
namespace ChronoFlow.View
{
@@ -26,7 +27,7 @@ namespace ChronoFlow.View
_viewManager.Register("AlleProjekte", () => new AlleProjekteView(_viewManager));
_viewManager.Register("MitarbeiterListe", () => new MitarbeiterListeView(_viewManager));
_viewManager.Register("AbgeschlosseneProjekte", () => new AbgeschlosseneProjekteView(_viewManager));
- // ⏳ später: _viewManager.Register("MitarbeiterMain", () => new MitarbeiterMainView(_viewManager));
+ _viewManager.Register("Zeiterfassung", () => new EmployeeTasksView(_loggedInUser.Username));
if (_loggedInUser.Role == "Admin")
{
diff --git a/ChronoFlow.View/Mitarbeiter/EmployeeTasksView.axaml b/ChronoFlow.View/Mitarbeiter/EmployeeTasksView.axaml
new file mode 100644
index 0000000..fe6713b
--- /dev/null
+++ b/ChronoFlow.View/Mitarbeiter/EmployeeTasksView.axaml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ChronoFlow.View/Mitarbeiter/EmployeeTasksView.axaml.cs b/ChronoFlow.View/Mitarbeiter/EmployeeTasksView.axaml.cs
new file mode 100644
index 0000000..e57da44
--- /dev/null
+++ b/ChronoFlow.View/Mitarbeiter/EmployeeTasksView.axaml.cs
@@ -0,0 +1,20 @@
+using Avalonia.Controls;
+using ChronoFlow.ViewModels.Mitarbeiter;
+using ChronoFlow.Persistence;
+
+namespace ChronoFlow.View.Mitarbeiter
+{
+ public partial class EmployeeTasksView : UserControl
+ {
+ public EmployeeTasksView(string benutzername)
+ {
+ InitializeComponent();
+
+ // Benutzername dynamisch übergeben
+ DataContext = new EmployeeTasksViewModel(
+ new SqliteZeiterfassungsService(),
+ benutzername
+ );
+ }
+ }
+}
\ No newline at end of file
diff --git a/ChronoFlow.View/Mitarbeiter/EmployeeTasksViewModel.axaml b/ChronoFlow.View/Mitarbeiter/EmployeeTasksViewModel.axaml
new file mode 100644
index 0000000..956f5fc
--- /dev/null
+++ b/ChronoFlow.View/Mitarbeiter/EmployeeTasksViewModel.axaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ChronoFlow.View/Mitarbeiter/EmployeeTasksViewModel.axaml.cs b/ChronoFlow.View/Mitarbeiter/EmployeeTasksViewModel.axaml.cs
new file mode 100644
index 0000000..9269d42
--- /dev/null
+++ b/ChronoFlow.View/Mitarbeiter/EmployeeTasksViewModel.axaml.cs
@@ -0,0 +1,54 @@
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using ChronoFlow.Model;
+using ChronoFlow.Persistence;
+
+namespace ChronoFlow.ViewModels.Mitarbeiter
+{
+ public partial class EmployeeTasksViewModel : ObservableObject
+ {
+ // Liste aller Zeiteinträge für den aktuell eingeloggten Mitarbeiter
+ [ObservableProperty]
+ private ObservableCollection eintraege = new();
+
+ // Ausgabe für Erfolg/Nachricht
+ [ObservableProperty]
+ private string? statusText;
+
+ private readonly IZeiterfassungsRepository repository;
+ private readonly string aktuellerBenutzername;
+
+ // Konstruktor erhält Repository (z. B. SqliteZeiterfassungsService) + aktuellen Benutzernamen
+ public EmployeeTasksViewModel(IZeiterfassungsRepository repository, string aktuellerBenutzername)
+ {
+ this.repository = repository;
+ this.aktuellerBenutzername = aktuellerBenutzername;
+
+ // Direkt beim Start laden
+ _ = LadeEintraegeAsync();
+ }
+
+ // 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(eintraegeAusDb);
+ StatusText = $"🔄 {Eintraege.Count} Einträge geladen.";
+ }
+
+ // 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);
+ }
+
+ StatusText = "✅ Änderungen gespeichert.";
+ }
+ }
+}
\ No newline at end of file
diff --git a/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml b/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml
index 24d8773..93dfc23 100644
--- a/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml
+++ b/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml
@@ -5,14 +5,16 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml.cs b/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml.cs
index e69de29..898d515 100644
--- a/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml.cs
+++ b/ChronoFlow.View/Mitarbeiter/MitarbeiterMainView.axaml.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.ObjectModel;
+using Avalonia.Controls;
+using ChronoFlow.Model;
+using ChronoFlow.Persistence;
+
+namespace ChronoFlow.View.Mitarbeiter
+{
+ public partial class MitarbeiterMainView : UserControl
+ {
+ private readonly ViewManager _viewManager;
+ private readonly User _currentUser;
+ private readonly ObservableCollection _letzteProjekte = new();
+ private readonly ObservableCollection _notifications = new();
+
+ public MitarbeiterMainView(ViewManager viewManager, User user)
+ {
+ InitializeComponent();
+ _viewManager = viewManager;
+ _currentUser = user;
+
+ LetzteProjekteListe.ItemsSource = _letzteProjekte;
+ NotificationList.ItemsSource = _notifications;
+
+ LadeLetzteProjekte();
+ LadeBenachrichtigungen();
+ }
+
+ private void LadeLetzteProjekte()
+ {
+ var dbService = new SqliteZeiterfassungsService();
+ var projekte = dbService.LadeLetzteProjekte(3);
+ _letzteProjekte.Clear();
+
+ foreach (var p in projekte)
+ {
+ if (p.Mitarbeiter == _currentUser.Username)
+ _letzteProjekte.Add(p);
+ }
+ }
+
+ private void LadeBenachrichtigungen()
+ {
+ // 🛈 Platzhalter → hier später echte DB-Infos laden!
+ _notifications.Clear();
+ _notifications.Add("Projekt Alpha wurde aktualisiert.");
+ _notifications.Add("Deadline für Projekt Beta wurde verschoben.");
+ }
+ }
+}
\ No newline at end of file