diff --git a/Components/Pages/FaktErfassen.razor b/Components/Pages/FaktErfassen.razor
new file mode 100644
index 0000000..0329e92
--- /dev/null
+++ b/Components/Pages/FaktErfassen.razor
@@ -0,0 +1,190 @@
+@page "/erfassen"
+@page "/erfassen/{*WorkspaceId}"
+@using ZahlenAnalyse.Web.Models
+@using ZahlenAnalyse.Web.Services
+@inject WorkspaceService DbService
+@inject ISnackbar Snackbar
+@inject NavigationManager NavManager
+
+
+ Daten erfassen
+
+ @if (_isLoading)
+ {
+
+ }
+ else
+ {
+
+
+ @foreach (var ws in _workspaces)
+ {
+ @ws.Name
+ }
+
+
+
+ @if (_selectedWorkspace != null)
+ {
+
+ Basisdaten
+
+
+
+
+
+
+
+
+
+
+
+ Kategorisierung
+
+ @foreach (var dim in _selectedWorkspace.Dimensions)
+ {
+
+
+
+ }
+
+
+
+
+ Abbrechen
+
+ Datensatz speichern
+
+
+ }
+ }
+
+
+@code {
+ [Parameter] public string? WorkspaceId { get; set; }
+
+ private List _workspaces = new();
+ private Workspace? _selectedWorkspace;
+ private AnalysisFakt _fakt = new();
+ private bool _isLoading = true;
+ private DateTime? _selectedDate = DateTime.Today;
+
+ protected override async Task OnInitializedAsync()
+ {
+ _workspaces = await DbService.GetWorkspacesForUserAsync();
+
+ if (!string.IsNullOrWhiteSpace(WorkspaceId))
+ {
+ var preselected = _workspaces.FirstOrDefault(w => w.Id == WorkspaceId);
+ if (preselected != null)
+ {
+ OnWorkspaceSelected(preselected);
+ }
+ }
+
+ _isLoading = false;
+ }
+
+ private void OnWorkspaceSelected(Workspace ws)
+ {
+ _selectedWorkspace = ws;
+ _fakt = new AnalysisFakt { WorkspaceId = ws.Id ?? string.Empty };
+ _selectedDate = DateTime.Today;
+
+ // Wir bereiten das Dictionary für jede definierte Dimension vor
+ foreach (var dim in ws.Dimensions)
+ {
+ _fakt.Dimensions[dim.Name] = string.Empty;
+ }
+ }
+
+ // Die geniale Suchfunktion für das Autocomplete
+ private async Task> SearchPath(string value, DimensionDefinition dim)
+ {
+ var allPaths = new List();
+
+ // Baum durchlaufen und Pfade sammeln
+ foreach (var node in dim.Nodes)
+ {
+ BuildPaths(node, "", allPaths);
+ }
+
+ // Wenn der User noch nichts getippt hat, zeigen wir alle Pfade an
+ if (string.IsNullOrWhiteSpace(value))
+ return allPaths;
+
+ // Ansonsten filtern wir (Case-Insensitive)
+ return allPaths.Where(x => x.Contains(value, StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ // Rekursive Methode, um aus dem Baum flache Pfade zu machen (z.B. "Europa/Italien")
+ private void BuildPaths(DimensionNode node, string currentPath, List allPaths)
+ {
+ string path = string.IsNullOrEmpty(currentPath) ? node.Name : $"{currentPath} / {node.Name}";
+
+ // Wir fügen jeden Knoten als wählbare Option hinzu
+ allPaths.Add(path);
+
+ foreach (var child in node.Children)
+ {
+ BuildPaths(child, path, allPaths);
+ }
+ }
+
+ private async Task SaveData()
+ {
+ if (_selectedDate.HasValue)
+ {
+ _fakt.Date = _selectedDate.Value.ToUniversalTime(); // Datenbanken lieben UTC
+ }
+
+ try
+ {
+ await DbService.SaveFaktAsync(_fakt);
+ Snackbar.Add("Datensatz erfolgreich gespeichert!", Severity.Success);
+
+ // --- NEU: Komfort-Reset für die Massenerfassung ---
+ var gemerktesDatum = _selectedDate; // 1. Datum merken
+
+ _fakt = new AnalysisFakt { WorkspaceId = _selectedWorkspace!.Id ?? string.Empty };
+ _selectedDate = gemerktesDatum; // 2. Gemerktes Datum wieder einsetzen
+
+ // 3. Dimensionen wieder leeren, damit das Autocomplete frisch ist
+ foreach (var dim in _selectedWorkspace.Dimensions)
+ {
+ _fakt.Dimensions[dim.Name] = string.Empty;
+ }
+ // --------------------------------------------------
+ }
+ catch (Exception ex)
+ {
+ Snackbar.Add($"Fehler beim Speichern: {ex.Message}", Severity.Error);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Components/Pages/Home.razor b/Components/Pages/Home.razor
index abc398e..2ed2baa 100644
--- a/Components/Pages/Home.razor
+++ b/Components/Pages/Home.razor
@@ -74,7 +74,7 @@
-
+
Daten erfassen
diff --git a/Services/WorkspaceService.cs b/Services/WorkspaceService.cs
index 80d2622..f23d5c6 100644
--- a/Services/WorkspaceService.cs
+++ b/Services/WorkspaceService.cs
@@ -97,4 +97,14 @@ public class WorkspaceService
return workspace;
}
+
+ public async Task SaveFaktAsync(AnalysisFakt fakt)
+ {
+ // Unsere elegante Hilfsmethode von vorhin füllt OwnerId, CreatedBy und CreatedAt!
+ await EnrichWithAuditDataAsync(fakt);
+
+ using var session = _store.OpenAsyncSession();
+ await session.StoreAsync(fakt);
+ await session.SaveChangesAsync();
+ }
}
\ No newline at end of file