Datenerfassung;

This commit is contained in:
2026-05-29 13:05:15 +02:00
parent 818377c0a8
commit fe11b715a6
3 changed files with 201 additions and 1 deletions
+190
View File
@@ -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
<MudContainer MaxWidth="MaxWidth.Medium" Class="mt-8 mb-8">
<MudText Typo="Typo.h4" Class="mb-6">Daten erfassen</MudText>
@if (_isLoading)
{
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
}
else
{
<MudPaper Class="pa-6 mb-6" Elevation="1">
<MudSelect T="Workspace"
Label="Workspace auswählen"
Variant="Variant.Outlined"
Value="_selectedWorkspace"
ValueChanged="OnWorkspaceSelected"
ToStringFunc="@(w => w?.Name)">
@foreach (var ws in _workspaces)
{
<MudSelectItem Value="ws">@ws.Name</MudSelectItem>
}
</MudSelect>
</MudPaper>
@if (_selectedWorkspace != null)
{
<MudPaper Class="pa-6 mb-6" Elevation="1">
<MudText Typo="Typo.h6" Class="mb-4">Basisdaten</MudText>
<MudGrid>
<MudItem xs="12" sm="6">
<MudDatePicker Label="Datum"
@bind-Date="_selectedDate"
Variant="Variant.Outlined" />
</MudItem>
<MudItem xs="12" sm="6">
<MudNumericField @bind-Value="_fakt.Amount"
Label="Betrag"
Format="N2"
Adornment="Adornment.End"
AdornmentText="€"
Variant="Variant.Outlined"
HideSpinButtons="true" />
</MudItem>
</MudGrid>
</MudPaper>
<MudPaper Class="pa-6 mb-6" Elevation="1">
<MudText Typo="Typo.h6" Class="mb-4">Kategorisierung</MudText>
<MudGrid>
@foreach (var dim in _selectedWorkspace.Dimensions)
{
<MudItem xs="12">
<MudAutocomplete T="string"
Label="@dim.Name"
Value="_fakt.Dimensions[dim.Name]"
ValueChanged="@(val => _fakt.Dimensions[dim.Name] = val)"
SearchFunc="@((text, token) => SearchPath(text, dim))"
ResetValueOnEmptyText="true"
CoerceText="true"
CoerceValue="true"
Variant="Variant.Outlined"
Placeholder="Tippen zum Suchen..."
AdornmentIcon="@Icons.Material.Filled.Search" />
</MudItem>
}
</MudGrid>
</MudPaper>
<MudStack Row="true" Justify="Justify.FlexEnd">
<MudButton Variant="Variant.Text" Href="/">Abbrechen</MudButton>
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
StartIcon="@Icons.Material.Filled.Save"
OnClick="SaveData">
Datensatz speichern
</MudButton>
</MudStack>
}
}
</MudContainer>
@code {
[Parameter] public string? WorkspaceId { get; set; }
private List<Workspace> _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<IEnumerable<string>> SearchPath(string value, DimensionDefinition dim)
{
var allPaths = new List<string>();
// 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<string> 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);
}
}
}
+1 -1
View File
@@ -74,7 +74,7 @@
</MudStack>
</MudCardContent>
<MudCardActions>
<MudButton Variant="Variant.Text" Color="Color.Primary">
<MudButton Href="@($"/erfassen/{ws.Id}")" Variant="Variant.Text" Color="Color.Primary">
Daten erfassen
</MudButton>
<MudButton Variant="Variant.Text" Color="Color.Secondary">