Datenerfassung;
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
</MudStack>
|
</MudStack>
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
<MudCardActions>
|
<MudCardActions>
|
||||||
<MudButton Variant="Variant.Text" Color="Color.Primary">
|
<MudButton Href="@($"/erfassen/{ws.Id}")" Variant="Variant.Text" Color="Color.Primary">
|
||||||
Daten erfassen
|
Daten erfassen
|
||||||
</MudButton>
|
</MudButton>
|
||||||
<MudButton Variant="Variant.Text" Color="Color.Secondary">
|
<MudButton Variant="Variant.Text" Color="Color.Secondary">
|
||||||
|
|||||||
@@ -97,4 +97,14 @@ public class WorkspaceService
|
|||||||
|
|
||||||
return workspace;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user