last changes
This commit is contained in:
parent
8ca1fb91dd
commit
b617d39c8f
1
.idea/.idea.ChronoFlow/.idea/avalonia.xml
generated
1
.idea/.idea.ChronoFlow/.idea/avalonia.xml
generated
@ -6,6 +6,7 @@
|
|||||||
<entry key="ChronoFlow.View/Admin/AdminMainView.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
|
<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/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/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/App.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
|
||||||
<entry key="ChronoFlow.View/LoginView.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" />
|
<entry key="ChronoFlow.View/LoginWindow.axaml" value="ChronoFlow.View/ChronoFlow.View.csproj" />
|
||||||
|
|||||||
@ -22,5 +22,6 @@ namespace ChronoFlow.Model
|
|||||||
Abteilung = "";
|
Abteilung = "";
|
||||||
OriginalUsername = "";
|
OriginalUsername = "";
|
||||||
}
|
}
|
||||||
|
public DateTime LetzterLogin { get; set; } = DateTime.MinValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,5 +37,8 @@ namespace ChronoFlow.Model
|
|||||||
return "Green";
|
return "Green";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public DateTime LetzteBearbeitung { get; set; }
|
||||||
|
public bool IstNeu { get; set; } // wird im ViewModel gesetzt
|
||||||
|
public bool WurdeSeitLoginBearbeitet { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,6 +92,7 @@ namespace ChronoFlow.Persistence
|
|||||||
AddColumnIfMissing(connection, "Benutzer", "Mitarbeitennummer", "TEXT");
|
AddColumnIfMissing(connection, "Benutzer", "Mitarbeitennummer", "TEXT");
|
||||||
AddColumnIfMissing(connection, "Benutzer", "Abteilung", "TEXT");
|
AddColumnIfMissing(connection, "Benutzer", "Abteilung", "TEXT");
|
||||||
AddColumnIfMissing(connection, "Benutzer", "MussPasswortAendern", "INTEGER DEFAULT 1");
|
AddColumnIfMissing(connection, "Benutzer", "MussPasswortAendern", "INTEGER DEFAULT 1");
|
||||||
|
AddColumnIfMissing(connection, "Zeiteintraege", "LetzteBearbeitung", "TEXT");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddColumnIfMissing(SqliteConnection connection, string tableName, string columnName, string columnType)
|
private void AddColumnIfMissing(SqliteConnection connection, string tableName, string columnName, string columnType)
|
||||||
@ -247,9 +248,10 @@ namespace ChronoFlow.Persistence
|
|||||||
var cmd = connection.CreateCommand();
|
var cmd = connection.CreateCommand();
|
||||||
cmd.CommandText = @"
|
cmd.CommandText = @"
|
||||||
INSERT INTO Zeiteintraege
|
INSERT INTO Zeiteintraege
|
||||||
(Mitarbeiter, Startzeit, Endzeit, Projekt, Kommentar, Erledigt, MitarbeiterKommentar)
|
(Mitarbeiter, Startzeit, Endzeit, Projekt, Kommentar, Erledigt, MitarbeiterKommentar, LetzteBearbeitung)
|
||||||
VALUES ($Mitarbeiter, $Startzeit, $Endzeit, $Projekt, $Kommentar, $Erledigt, $MitarbeiterKommentar);
|
VALUES
|
||||||
";
|
($Mitarbeiter, $Startzeit, $Endzeit, $Projekt, $Kommentar, $Erledigt, $MitarbeiterKommentar, $LetzteBearbeitung);";
|
||||||
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("$Mitarbeiter", eintrag.Mitarbeiter);
|
cmd.Parameters.AddWithValue("$Mitarbeiter", eintrag.Mitarbeiter);
|
||||||
cmd.Parameters.AddWithValue("$Startzeit", eintrag.Startzeit.ToString("o"));
|
cmd.Parameters.AddWithValue("$Startzeit", eintrag.Startzeit.ToString("o"));
|
||||||
@ -258,6 +260,7 @@ namespace ChronoFlow.Persistence
|
|||||||
cmd.Parameters.AddWithValue("$Kommentar", eintrag.Kommentar ?? "");
|
cmd.Parameters.AddWithValue("$Kommentar", eintrag.Kommentar ?? "");
|
||||||
cmd.Parameters.AddWithValue("$Erledigt", eintrag.Erledigt ? 1 : 0);
|
cmd.Parameters.AddWithValue("$Erledigt", eintrag.Erledigt ? 1 : 0);
|
||||||
cmd.Parameters.AddWithValue("$MitarbeiterKommentar", eintrag.MitarbeiterKommentar ?? "");
|
cmd.Parameters.AddWithValue("$MitarbeiterKommentar", eintrag.MitarbeiterKommentar ?? "");
|
||||||
|
cmd.Parameters.AddWithValue("$LetzteBearbeitung", DateTime.Now.ToString("o"));
|
||||||
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
@ -306,9 +309,9 @@ namespace ChronoFlow.Persistence
|
|||||||
Startzeit = $Startzeit,
|
Startzeit = $Startzeit,
|
||||||
Endzeit = $Endzeit,
|
Endzeit = $Endzeit,
|
||||||
Mitarbeiter = $Mitarbeiter,
|
Mitarbeiter = $Mitarbeiter,
|
||||||
Erledigt = $Erledigt
|
Erledigt = $Erledigt,
|
||||||
WHERE Id = $Id;
|
LetzteBearbeitung = $LetzteBearbeitung
|
||||||
";
|
WHERE Id = $Id;";
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("$Projekt", projekt.Projekt);
|
cmd.Parameters.AddWithValue("$Projekt", projekt.Projekt);
|
||||||
cmd.Parameters.AddWithValue("$Kommentar", projekt.Kommentar ?? "");
|
cmd.Parameters.AddWithValue("$Kommentar", projekt.Kommentar ?? "");
|
||||||
@ -317,6 +320,7 @@ namespace ChronoFlow.Persistence
|
|||||||
cmd.Parameters.AddWithValue("$Mitarbeiter", projekt.Mitarbeiter);
|
cmd.Parameters.AddWithValue("$Mitarbeiter", projekt.Mitarbeiter);
|
||||||
cmd.Parameters.AddWithValue("$Erledigt", projekt.Erledigt ? 1 : 0);
|
cmd.Parameters.AddWithValue("$Erledigt", projekt.Erledigt ? 1 : 0);
|
||||||
cmd.Parameters.AddWithValue("$Id", projekt.Id);
|
cmd.Parameters.AddWithValue("$Id", projekt.Id);
|
||||||
|
cmd.Parameters.AddWithValue("$LetzteBearbeitung", DateTime.Now.ToString("o"));
|
||||||
|
|
||||||
int rowsAffected = cmd.ExecuteNonQuery();
|
int rowsAffected = cmd.ExecuteNonQuery();
|
||||||
Console.WriteLine($"✏ Projekt aktualisiert (Id={projekt.Id}, Rows affected: {rowsAffected})");
|
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})");
|
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>();
|
var eintraege = new List<Zeiteintrag>();
|
||||||
|
|
||||||
using var connection = new SqliteConnection($"Data Source={_dbPath}");
|
using var connection = new SqliteConnection($"Data Source={_dbPath}");
|
||||||
await connection.OpenAsync();
|
await connection.OpenAsync();
|
||||||
|
|
||||||
var cmd = connection.CreateCommand();
|
var cmd = connection.CreateCommand();
|
||||||
cmd.CommandText = @"
|
cmd.CommandText = @"
|
||||||
SELECT * FROM Zeiteintraege
|
SELECT Id, Mitarbeiter, Startzeit, Endzeit, Projekt, Kommentar, Erledigt, MitarbeiterKommentar, LetzteBearbeitung
|
||||||
WHERE Mitarbeiter = $Mitarbeiter;
|
FROM Zeiteintraege
|
||||||
|
WHERE Mitarbeiter = $Name;
|
||||||
";
|
";
|
||||||
cmd.Parameters.AddWithValue("$Mitarbeiter", mitarbeiterName);
|
cmd.Parameters.AddWithValue("$Name", name);
|
||||||
|
|
||||||
using var reader = await cmd.ExecuteReaderAsync();
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
|
||||||
while (await reader.ReadAsync())
|
while (await reader.ReadAsync())
|
||||||
{
|
{
|
||||||
eintraege.Add(new Zeiteintrag
|
eintraege.Add(new Zeiteintrag
|
||||||
{
|
{
|
||||||
Id = reader.GetInt32(0),
|
Id = reader.GetInt32(0),
|
||||||
Mitarbeiter = reader.GetString(1),
|
Mitarbeiter = reader.GetString(1),
|
||||||
Startzeit = DateTime.Parse(reader.GetString(2)),
|
Startzeit = reader.GetDateTime(2),
|
||||||
Endzeit = DateTime.Parse(reader.GetString(3)),
|
Endzeit = reader.GetDateTime(3),
|
||||||
Projekt = reader.GetString(4),
|
Projekt = reader.GetString(4),
|
||||||
Kommentar = reader.GetString(5),
|
Kommentar = reader.GetString(5),
|
||||||
Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
|
Erledigt = reader.GetBoolean(6),
|
||||||
MitarbeiterKommentar = reader.GetString(7)
|
MitarbeiterKommentar = reader.GetString(7),
|
||||||
|
LetzteBearbeitung = reader.IsDBNull(8) ? DateTime.MinValue : reader.GetDateTime(8)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return eintraege;
|
return eintraege;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,17 +513,20 @@ namespace ChronoFlow.Persistence
|
|||||||
cmd.CommandText = @"
|
cmd.CommandText = @"
|
||||||
UPDATE Zeiteintraege
|
UPDATE Zeiteintraege
|
||||||
SET Erledigt = $Erledigt,
|
SET Erledigt = $Erledigt,
|
||||||
MitarbeiterKommentar = $Kommentar
|
MitarbeiterKommentar = $Kommentar,
|
||||||
|
LetzteBearbeitung = $Bearbeitet
|
||||||
WHERE Id = $Id;
|
WHERE Id = $Id;
|
||||||
";
|
";
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("$Erledigt", erledigt ? 1 : 0);
|
cmd.Parameters.AddWithValue("$Erledigt", erledigt ? 1 : 0);
|
||||||
cmd.Parameters.AddWithValue("$Kommentar", mitarbeiterKommentar ?? "");
|
cmd.Parameters.AddWithValue("$Kommentar", mitarbeiterKommentar ?? "");
|
||||||
|
cmd.Parameters.AddWithValue("$Bearbeitet", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
cmd.Parameters.AddWithValue("$Id", id);
|
cmd.Parameters.AddWithValue("$Id", id);
|
||||||
|
|
||||||
int rowsAffected = await cmd.ExecuteNonQueryAsync();
|
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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,37 +3,21 @@
|
|||||||
xmlns:model="clr-namespace:ChronoFlow.Model;assembly=ChronoFlow.Model"
|
xmlns:model="clr-namespace:ChronoFlow.Model;assembly=ChronoFlow.Model"
|
||||||
x:Class="ChronoFlow.View.Admin.AdminMainView">
|
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"/>
|
|
||||||
|
|
||||||
<!-- 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>
|
</StackPanel>
|
||||||
</SplitView.Pane>
|
|
||||||
|
|
||||||
<!-- Hauptinhalt -->
|
<!-- Hauptinhalt -->
|
||||||
<SplitView.Content>
|
|
||||||
<StackPanel Margin="20" Spacing="15">
|
<StackPanel Margin="20" Spacing="15">
|
||||||
|
|
||||||
<!-- Überschrift -->
|
|
||||||
<TextBlock Text="Admin-Dashboard" FontSize="24" FontWeight="Bold" HorizontalAlignment="Center"/>
|
<TextBlock Text="Admin-Dashboard" FontSize="24" FontWeight="Bold" HorizontalAlignment="Center"/>
|
||||||
|
|
||||||
<!-- 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"/>
|
<TextBlock Text="Zuletzt hinzugefügte Projekte" FontSize="18" FontWeight="SemiBold" Margin="0,20,0,10"/>
|
||||||
|
|
||||||
<ItemsControl x:Name="LetzteProjekteListe">
|
<ItemsControl x:Name="LetzteProjekteListe">
|
||||||
@ -49,11 +33,7 @@
|
|||||||
</Border>
|
</Border>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
|
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</SplitView.Content>
|
</DockPanel>
|
||||||
|
|
||||||
</SplitView>
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -67,12 +67,6 @@ namespace ChronoFlow.View.Admin
|
|||||||
{
|
{
|
||||||
_viewManager.Show("ProjektErstellen");
|
_viewManager.Show("ProjektErstellen");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dashboard_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
_viewManager.Show("AdminMain");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AlleProjekte_Click(object sender, RoutedEventArgs e)
|
private void AlleProjekte_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_viewManager.Show("AlleProjekte");
|
_viewManager.Show("AlleProjekte");
|
||||||
@ -83,15 +77,9 @@ namespace ChronoFlow.View.Admin
|
|||||||
_viewManager.Show("MitarbeiterListe");
|
_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()
|
public void AktualisiereLetzteProjekte()
|
||||||
{
|
{
|
||||||
@ -102,5 +90,7 @@ namespace ChronoFlow.View.Admin
|
|||||||
{
|
{
|
||||||
_viewManager.Show("AbgeschlosseneProjekte");
|
_viewManager.Show("AbgeschlosseneProjekte");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
x:Class="ChronoFlow.View.Admin.MitarbeiterBearbeitenDialog"
|
x:Class="ChronoFlow.View.Admin.MitarbeiterBearbeitenDialog"
|
||||||
Width="450" Height="600"
|
Width="450" Height="600"
|
||||||
Title="Mitarbeiter bearbeiten">
|
Title="Mitarbeiter bearbeiten">
|
||||||
|
<ScrollViewer>
|
||||||
<StackPanel Margin="20" Spacing="10">
|
<StackPanel Margin="20" Spacing="15">
|
||||||
<TextBlock Text="Username:" />
|
<TextBlock Text="Username:" />
|
||||||
<TextBox x:Name="UsernameBox" />
|
<TextBox x:Name="UsernameBox" />
|
||||||
|
|
||||||
@ -28,4 +28,5 @@
|
|||||||
IsVisible="False"
|
IsVisible="False"
|
||||||
Margin="0,10,0,0" />
|
Margin="0,10,0,0" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</Window>
|
</Window>
|
||||||
@ -4,7 +4,8 @@
|
|||||||
Width="500" Height="600"
|
Width="500" Height="600"
|
||||||
Title="Projekt bearbeiten">
|
Title="Projekt bearbeiten">
|
||||||
|
|
||||||
<StackPanel Margin="20" Spacing="12">
|
<ScrollViewer>
|
||||||
|
<StackPanel Margin="20" Spacing="15">
|
||||||
<TextBlock Text="Projektname:" />
|
<TextBlock Text="Projektname:" />
|
||||||
<TextBox x:Name="ProjektnameBox" />
|
<TextBox x:Name="ProjektnameBox" />
|
||||||
|
|
||||||
@ -25,4 +26,5 @@
|
|||||||
<Button Content="❌ Abbrechen" Width="130" Click="AbbrechenButton_Click" />
|
<Button Content="❌ Abbrechen" Width="130" Click="AbbrechenButton_Click" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</Window>
|
</Window>
|
||||||
@ -2,7 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
x:Class="ChronoFlow.View.Admin.ProjektErstellenView">
|
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" />
|
<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">
|
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center" Margin="0,10,0,0">
|
||||||
<Button Content="✅ Speichern" Click="SpeichernButton_Click" Width="115" />
|
<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>
|
</StackPanel>
|
||||||
|
|
||||||
<TextBlock x:Name="FeedbackText" Foreground="Red" IsVisible="False" />
|
<TextBlock x:Name="FeedbackText" Foreground="Red" IsVisible="False" />
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,8 +1,15 @@
|
|||||||
<Application xmlns="https://github.com/avaloniaui"
|
<Application xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:themes="clr-namespace:Avalonia.Themes.Fluent;assembly=Avalonia.Themes.Fluent"
|
xmlns:themes="clr-namespace:Avalonia.Themes.Fluent;assembly=Avalonia.Themes.Fluent"
|
||||||
x:Class="ChronoFlow.App"
|
xmlns:conv="clr-namespace:ChronoFlow.View.Converter"
|
||||||
RequestedThemeVariant="Default">
|
x:Class="ChronoFlow.App">
|
||||||
|
|
||||||
|
<Application.Resources>
|
||||||
|
<conv:BoolToBrushConverter x:Key="BoolToBrushConverter"
|
||||||
|
TrueBrush="Blue"
|
||||||
|
FalseBrush="Gray"/>
|
||||||
|
</Application.Resources>
|
||||||
|
|
||||||
<Application.Styles>
|
<Application.Styles>
|
||||||
<themes:FluentTheme />
|
<themes:FluentTheme />
|
||||||
</Application.Styles>
|
</Application.Styles>
|
||||||
|
|||||||
@ -13,6 +13,9 @@
|
|||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||||
<PackageReference Include="MessageBox.Avalonia" Version="0.10.4" />
|
<PackageReference Include="MessageBox.Avalonia" Version="0.10.4" />
|
||||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.6" />
|
<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>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
24
ChronoFlow.View/Converter/BoolToBrushConverter.cs
Normal file
24
ChronoFlow.View/Converter/BoolToBrushConverter.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -106,6 +106,7 @@ namespace ChronoFlow.View
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Console.WriteLine("🚀 Öffne MainWindow...");
|
Console.WriteLine("🚀 Öffne MainWindow...");
|
||||||
|
user.LetzterLogin = DateTime.Now;
|
||||||
var main = new MainWindow(user);
|
var main = new MainWindow(user);
|
||||||
main.Show();
|
main.Show();
|
||||||
Console.WriteLine("✅ MainWindow wurde geöffnet.");
|
Console.WriteLine("✅ MainWindow wurde geöffnet.");
|
||||||
@ -120,5 +121,6 @@ namespace ChronoFlow.View
|
|||||||
ErrorText.IsVisible = true;
|
ErrorText.IsVisible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,18 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="600"
|
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="600"
|
||||||
x:Class="ChronoFlow.View.MainWindow"
|
x:Class="ChronoFlow.View.MainWindow"
|
||||||
Title="ChronoFlow">
|
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>
|
<Grid>
|
||||||
<ContentControl x:Name="ContentArea" />
|
<ContentControl x:Name="ContentArea" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
</Window>
|
</Window>
|
||||||
@ -2,6 +2,7 @@ using System;
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using ChronoFlow.Model;
|
using ChronoFlow.Model;
|
||||||
|
using ChronoFlow.Persistence;
|
||||||
using ChronoFlow.View.Admin;
|
using ChronoFlow.View.Admin;
|
||||||
using ChronoFlow.View.Mitarbeiter;
|
using ChronoFlow.View.Mitarbeiter;
|
||||||
|
|
||||||
@ -27,7 +28,8 @@ namespace ChronoFlow.View
|
|||||||
_viewManager.Register("AlleProjekte", () => new AlleProjekteView(_viewManager));
|
_viewManager.Register("AlleProjekte", () => new AlleProjekteView(_viewManager));
|
||||||
_viewManager.Register("MitarbeiterListe", () => new MitarbeiterListeView(_viewManager));
|
_viewManager.Register("MitarbeiterListe", () => new MitarbeiterListeView(_viewManager));
|
||||||
_viewManager.Register("AbgeschlosseneProjekte", () => new AbgeschlosseneProjekteView(_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")
|
if (_loggedInUser.Role == "Admin")
|
||||||
{
|
{
|
||||||
@ -60,5 +62,12 @@ namespace ChronoFlow.View
|
|||||||
{
|
{
|
||||||
_viewManager.Show("AdminMain");
|
_viewManager.Show("AdminMain");
|
||||||
}
|
}
|
||||||
|
private void Logout_Click(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var loginWindow = new LoginWindow();
|
||||||
|
loginWindow.Show();
|
||||||
|
|
||||||
|
this.Close(); // Aktuelles Fenster schließen
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,29 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:vm="clr-namespace:ChronoFlow.ViewModels.Mitarbeiter"
|
xmlns:vm="clr-namespace:ChronoFlow.ViewModels.Mitarbeiter"
|
||||||
|
xmlns:converter="clr-namespace:ChronoFlow.View.Converter"
|
||||||
x:Class="ChronoFlow.View.Mitarbeiter.EmployeeTasksView">
|
x:Class="ChronoFlow.View.Mitarbeiter.EmployeeTasksView">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<converter:BoolToBrushConverter x:Key="BoolToBrushConverter"/>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<ScrollViewer>
|
||||||
<StackPanel Margin="20" Spacing="10">
|
<StackPanel Margin="20" Spacing="10">
|
||||||
<TextBlock Text="Meine Aufgaben" FontSize="24" FontWeight="Bold"/>
|
<TextBlock Text="Meine Aufgaben" FontSize="24" FontWeight="Bold"/>
|
||||||
|
|
||||||
|
<!-- 🟢 Der Hinweis kommt vor dem ItemsControl -->
|
||||||
|
<TextBlock Text="🎉 Du hast aktuell keine Aufgaben!"
|
||||||
|
FontSize="16"
|
||||||
|
FontStyle="Italic"
|
||||||
|
FontWeight="Medium"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
IsVisible="{Binding HatKeineEintraege}"/>
|
||||||
|
|
||||||
|
<!-- 📝 Die eigentliche Aufgabenliste -->
|
||||||
<ItemsControl ItemsSource="{Binding Eintraege}">
|
<ItemsControl ItemsSource="{Binding Eintraege}">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Border BorderThickness="1" BorderBrush="Gray" CornerRadius="4" Padding="10" Margin="5">
|
<Border BorderBrush="{Binding WurdeSeitLoginBearbeitet, Converter={StaticResource BoolToBrushConverter}}"
|
||||||
|
BorderThickness="1" CornerRadius="4" Padding="10" Margin="5">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
<TextBlock Text="{Binding Projekt}" FontWeight="Bold"/>
|
<TextBlock Text="{Binding Projekt}" FontWeight="Bold"/>
|
||||||
<CheckBox Content="Erledigt" IsChecked="{Binding Erledigt}"/>
|
<CheckBox Content="Erledigt" IsChecked="{Binding Erledigt}"/>
|
||||||
@ -25,4 +40,6 @@
|
|||||||
<Button Content="Änderungen speichern" Command="{Binding SpeichereEintraegeCommand}"/>
|
<Button Content="Änderungen speichern" Command="{Binding SpeichereEintraegeCommand}"/>
|
||||||
<TextBlock Text="{Binding StatusText}" Foreground="Green" FontStyle="Italic"/>
|
<TextBlock Text="{Binding StatusText}" Foreground="Green" FontStyle="Italic"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,20 +1,16 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using ChronoFlow.ViewModels.Mitarbeiter;
|
using ChronoFlow.ViewModels.Mitarbeiter;
|
||||||
using ChronoFlow.Persistence;
|
using ChronoFlow.Persistence;
|
||||||
|
using ChronoFlow.Model;
|
||||||
|
|
||||||
namespace ChronoFlow.View.Mitarbeiter
|
namespace ChronoFlow.View.Mitarbeiter
|
||||||
{
|
{
|
||||||
public partial class EmployeeTasksView : UserControl
|
public partial class EmployeeTasksView : UserControl
|
||||||
{
|
{
|
||||||
public EmployeeTasksView(string benutzername)
|
public EmployeeTasksView(User user, IZeiterfassungsRepository repository)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
DataContext = new EmployeeTasksViewModel(user, repository);
|
||||||
// Benutzername dynamisch übergeben
|
|
||||||
DataContext = new EmployeeTasksViewModel(
|
|
||||||
new SqliteZeiterfassungsService(),
|
|
||||||
benutzername
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
@ -9,46 +11,75 @@ namespace ChronoFlow.ViewModels.Mitarbeiter
|
|||||||
{
|
{
|
||||||
public partial class EmployeeTasksViewModel : ObservableObject
|
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]
|
[ObservableProperty]
|
||||||
private ObservableCollection<Zeiteintrag> eintraege = new();
|
private ObservableCollection<Zeiteintrag> eintraege = new();
|
||||||
|
|
||||||
// Ausgabe für Erfolg/Nachricht
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string? statusText;
|
private string? statusText;
|
||||||
|
|
||||||
private readonly IZeiterfassungsRepository repository;
|
public bool HatKeineEintraege => Eintraege.Count == 0;
|
||||||
private readonly string aktuellerBenutzername;
|
|
||||||
|
|
||||||
// Konstruktor erhält Repository (z. B. SqliteZeiterfassungsService) + aktuellen Benutzernamen
|
partial void OnEintraegeChanged(ObservableCollection<Zeiteintrag>? oldValue, ObservableCollection<Zeiteintrag> newValue)
|
||||||
public EmployeeTasksViewModel(IZeiterfassungsRepository repository, string aktuellerBenutzername)
|
|
||||||
{
|
{
|
||||||
this.repository = repository;
|
OnPropertyChanged(nameof(HatKeineEintraege));
|
||||||
this.aktuellerBenutzername = aktuellerBenutzername;
|
}
|
||||||
|
|
||||||
// Direkt beim Start laden
|
public EmployeeTasksViewModel(User benutzer, IZeiterfassungsRepository repository)
|
||||||
_ = LadeEintraegeAsync();
|
{
|
||||||
|
_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]
|
[RelayCommand]
|
||||||
public async Task LadeEintraegeAsync()
|
public async Task LadeEintraegeAsync()
|
||||||
{
|
{
|
||||||
var eintraegeAusDb = await repository.GetEintraegeFuerMitarbeiterAsync(aktuellerBenutzername);
|
var eintraegeAusDb = await _repository.GetEintraegeFuerMitarbeiterAsync(aktuellerBenutzername);
|
||||||
Eintraege = new ObservableCollection<Zeiteintrag>(eintraegeAusDb);
|
|
||||||
StatusText = $"🔄 {Eintraege.Count} Einträge geladen.";
|
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}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Speichert Änderungen (Status + Kommentar) für alle sichtbaren Einträge
|
|
||||||
|
if (offene.Any(e => e.WurdeSeitLoginBearbeitet))
|
||||||
|
StatusText = "📢 Es wurden Aufgaben seit Ihrem letzten Login geändert.";
|
||||||
|
|
||||||
|
Eintraege = new ObservableCollection<Zeiteintrag>(offene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
public async Task SpeichereEintraegeAsync()
|
public async Task SpeichereEintraegeAsync()
|
||||||
{
|
{
|
||||||
foreach (var eintrag in Eintraege)
|
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.";
|
StatusText = "✅ Änderungen gespeichert.";
|
||||||
|
await LadeEintraegeAsync(); // automatisch neu laden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
x:Class="ChronoFlow.View.MitarbeiterHinzufuegenView">
|
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"/>
|
<TextBlock Text="➕ Mitarbeiter hinzufügen" FontWeight="Bold" FontSize="20" HorizontalAlignment="Center"/>
|
||||||
|
|
||||||
<TextBox x:Name="UsernameBox" Watermark="Benutzername"/>
|
<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"/>
|
<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"/>
|
<TextBlock x:Name="FeedbackText" Foreground="Green" IsVisible="False" TextAlignment="Center"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
Loading…
Reference in New Issue
Block a user