diff --git a/Components/Pages/Home.razor b/Components/Pages/Home.razor
index 6b633c7..9c179e4 100644
--- a/Components/Pages/Home.razor
+++ b/Components/Pages/Home.razor
@@ -55,7 +55,9 @@
-
+
diff --git a/Components/Pages/WorkspaceDetail.razor b/Components/Pages/WorkspaceDetail.razor
new file mode 100644
index 0000000..62ddc89
--- /dev/null
+++ b/Components/Pages/WorkspaceDetail.razor
@@ -0,0 +1,114 @@
+@page "/workspace/{*WorkspaceId}"
+@using ZahlenAnalyse.Web.Models
+@using ZahlenAnalyse.Web.Services
+@inject WorkspaceService DbService
+@inject ISnackbar Snackbar
+@inject NavigationManager NavManager
+
+
+ @if (_workspace == null)
+ {
+
+ }
+ else
+ {
+ @_workspace.Name
+
+
+
+
+ Daten importieren
+ Lade eine Excel-Datei hoch, um Fakten in diesen Workspace zu importieren.
+
+
+
+
+ Excel hochladen
+
+
+
+
+
+
+
+
+ Dimensionen
+
+ @foreach (var dim in _workspace.Dimensions)
+ {
+ @dim.Name
+ }
+
+
+
+
+
+
+ Letzte Importe / Einträge
+
+
+ Datum
+ Betrag
+ Details
+
+
+ @context.Date.ToShortDateString()
+ @context.Amount.ToString("N2") €
+ @string.Join(" | ", context.Dimensions.Values)
+
+
+
+
+
+ }
+
+
+@code {
+ [Parameter] public string WorkspaceId { get; set; } = string.Empty;
+ private Workspace? _workspace;
+ private List _recentFakten = new();
+
+ protected override async Task OnInitializedAsync()
+ {
+ _workspace = await DbService.GetWorkspaceAsync(WorkspaceId);
+ if (_workspace != null)
+ {
+ _recentFakten = await DbService.GetFaktenForWorkspaceAsync(WorkspaceId);
+ _recentFakten = _recentFakten.Take(5).ToList();
+ }
+ }
+
+ private async Task UploadFile(Microsoft.AspNetCore.Components.Forms.IBrowserFile e)
+ {
+ var file = e;
+ if (file == null) return;
+
+ try
+ {
+ // 1. Datenstrom vom Browser öffnen
+ using var browserStream = file.OpenReadStream(maxAllowedSize: 1024 * 1024 * 10); // 10MB
+
+ // 2. Den Stream komplett in den "Eimer" (Arbeitsspeicher) laden
+ using var memoryStream = new MemoryStream();
+ await browserStream.CopyToAsync(memoryStream);
+
+ // 3. WICHTIG: Den Lese-Zeiger im Eimer wieder nach ganz oben setzen!
+ memoryStream.Position = 0;
+
+ // 4. Den fertigen MemoryStream an den Service übergeben
+ await DbService.ImportFromExcelAsync(WorkspaceId, memoryStream);
+
+ Snackbar.Add("Import erfolgreich!", Severity.Success);
+
+ // Die Tabelle mit den neuen Daten aktualisieren
+ _recentFakten = (await DbService.GetFaktenForWorkspaceAsync(WorkspaceId)).Take(5).ToList();
+ }
+ catch (Exception ex)
+ {
+ Snackbar.Add($"Fehler beim Import: {ex.Message}", Severity.Error);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Services/WorkspaceService.cs b/Services/WorkspaceService.cs
index 65b2541..fd3c996 100644
--- a/Services/WorkspaceService.cs
+++ b/Services/WorkspaceService.cs
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Components.Authorization;
using Raven.Client.Documents;
using ZahlenAnalyse.Web.Models;
+using ExcelDataReader;
+using System.Data;
namespace ZahlenAnalyse.Web.Services;
@@ -118,4 +120,43 @@ public class WorkspaceService
.OrderByDescending(f => f.Date)
.ToListAsync();
}
+
+ public async Task ImportFromExcelAsync(string workspaceId, Stream fileStream)
+{
+ // Encoding für deutsche Excel-Dateien
+ System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
+
+ using var reader = ExcelReaderFactory.CreateReader(fileStream);
+ var result = reader.AsDataSet(new ExcelDataSetConfiguration() {
+ ConfigureDataTable = (_) => new ExcelDataTableConfiguration() { UseHeaderRow = true }
+ });
+
+ var dataTable = result.Tables[0];
+
+ using var session = _store.OpenAsyncSession();
+
+ foreach (DataRow row in dataTable.Rows)
+ {
+ var fakt = new AnalysisFakt
+ {
+ WorkspaceId = workspaceId,
+ Date = Convert.ToDateTime(row["Datum"]),
+ Amount = Convert.ToDecimal(row["Betrag"]),
+ // Hier mappen wir dynamisch die Dimensionen
+ Dimensions = new Dictionary()
+ };
+
+ // Wir gehen davon aus, dass deine Excel-Spaltennamen
+ // den Dimensions-Namen entsprechen
+ foreach (var col in dataTable.Columns.Cast().Skip(2)) // Datum/Betrag überspringen
+ {
+ fakt.Dimensions[col.ColumnName] = row[col.ColumnName].ToString() ?? "";
+ }
+
+ await EnrichWithAuditDataAsync(fakt);
+ await session.StoreAsync(fakt);
+ }
+
+ await session.SaveChangesAsync();
+}
}
\ No newline at end of file
diff --git a/ZahlenAnalyse.Web.csproj b/ZahlenAnalyse.Web.csproj
index d776c60..c2a883c 100644
--- a/ZahlenAnalyse.Web.csproj
+++ b/ZahlenAnalyse.Web.csproj
@@ -9,6 +9,8 @@
+
+