QR-Scanner: Kamera-Fallbacks und Foto-Upload; weitere Aenderungen
This commit is contained in:
1 parent
7a0406eaa2
commit
e2aef67099
13 files changed
+965
-58
No files matched your search
@@ -4,6 +4,8 @@
|
||||
@inject ILocationCodeService LocationCodeService
|
||||
@inject ITireStackService TireStackService
|
||||
@inject UserSessionService UserSession
|
||||
@inject IStorageRowPdfService RowPdfService
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<PageTitle>Lagerplätze - Reifen Späth Lagerverwaltung</PageTitle>
|
||||
|
||||
@@ -52,7 +54,7 @@ else
|
||||
</button>
|
||||
<button class="stat-chip available @(statusFilter == StatusAvailable ? "active" : "")"
|
||||
@onclick="FilterByStatusAvailable" title="Nur freie Plätze anzeigen">
|
||||
<span class="chip-value">@allLocations.Count(l => !l.IsOccupied)</span> Frei
|
||||
<span class="chip-value">@allLocations.Count(l => !l.IsOccupied && l.IsAvailable)</span> Frei
|
||||
</button>
|
||||
<button class="stat-chip occupied @(statusFilter == StatusOccupied ? "active" : "")"
|
||||
@onclick="FilterByStatusOccupied" title="Nur belegte Plätze anzeigen">
|
||||
@@ -132,11 +134,24 @@ else
|
||||
var occupiedCount = rowGroup.Count(l => l.IsOccupied);
|
||||
var totalCount = rowGroup.Count();
|
||||
<div class="row-section @(isCollapsed ? "collapsed" : "")">
|
||||
<button type="button" class="row-header" @onclick="() => ToggleRow(rowKey)">
|
||||
<span class="row-chevron">@(isCollapsed ? "▶" : "▼")</span>
|
||||
<h3 class="row-title">Reihe @rowGroup.Key</h3>
|
||||
<span class="row-summary">@occupiedCount / @totalCount belegt</span>
|
||||
</button>
|
||||
<div class="row-header-wrap">
|
||||
<button type="button" class="row-header" @onclick="() => ToggleRow(rowKey)">
|
||||
<span class="row-chevron">@(isCollapsed ? "▶" : "▼")</span>
|
||||
<h3 class="row-title">Reihe @rowGroup.Key</h3>
|
||||
<span class="row-summary">@occupiedCount / @totalCount belegt</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline btn-sm row-print-btn"
|
||||
title="Reihe als PDF drucken"
|
||||
disabled="@(printingRowKey != null)"
|
||||
@onclick="() => PrintRow(areaGroup.Key, rowGroup.Key)"
|
||||
@onclick:stopPropagation>
|
||||
@(printingRowKey == rowKey ? "⏳" : "🖨") PDF
|
||||
</button>
|
||||
</div>
|
||||
@if (printErrorRowKey == rowKey && printError != null)
|
||||
{
|
||||
<div class="row-print-error" role="alert">@printError</div>
|
||||
}
|
||||
@if (!isCollapsed)
|
||||
{
|
||||
@foreach (var posGroup in rowGroup.GroupBy(l => l.Position).OrderBy(g => (int)g.Key))
|
||||
@@ -155,11 +170,21 @@ else
|
||||
@if (location.IsOccupied && storedTireStack != null)
|
||||
{
|
||||
<div class="card-content">
|
||||
<span class="customer-name">
|
||||
<span class="customer-name" title="@(storedTireStack.Customer?.FullName ?? storedTireStack.CatalogItem?.Name ?? "Lager")">
|
||||
@(storedTireStack.Customer?.FullName ?? storedTireStack.CatalogItem?.Name ?? "Lager")
|
||||
</span>
|
||||
@if (storedTireStack.Vehicle != null)
|
||||
{
|
||||
<span class="vehicle-line" title="@storedTireStack.Vehicle.ShortName">
|
||||
<span class="vehicle-model">🚗 @storedTireStack.Vehicle.ShortName</span>
|
||||
</span>
|
||||
}
|
||||
<span class="tire-info">
|
||||
@(storedTireStack.Season == TireSeason.Sommer ? "☀️" : storedTireStack.Season == TireSeason.Winter ? "❄️" : "🔄")
|
||||
<span class="season-icon">@(storedTireStack.Season == TireSeason.Sommer ? "☀️" : storedTireStack.Season == TireSeason.Winter ? "❄️" : "🔄")</span>
|
||||
@if (!string.IsNullOrEmpty(storedTireStack.TireSize))
|
||||
{
|
||||
<span class="tire-size-compact">@storedTireStack.TireSize</span>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@@ -231,7 +256,7 @@ else
|
||||
<span class="customer">@storedTireStack.Customer.FullName</span>
|
||||
@if (storedTireStack.Vehicle != null)
|
||||
{
|
||||
<span class="vehicle-info">@storedTireStack.Vehicle.ShortName</span>
|
||||
<span class="vehicle-info">🚗 @storedTireStack.Vehicle.ShortName</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -761,6 +786,40 @@ else
|
||||
}
|
||||
}
|
||||
|
||||
private string? printingRowKey;
|
||||
private string? printErrorRowKey;
|
||||
private string? printError;
|
||||
|
||||
private async Task PrintRow(AreaType area, int row)
|
||||
{
|
||||
var rowKey = $"{area}-{row}";
|
||||
if (printingRowKey != null) return;
|
||||
|
||||
printingRowKey = rowKey;
|
||||
printError = null;
|
||||
printErrorRowKey = null;
|
||||
|
||||
try
|
||||
{
|
||||
var rowLocations = allLocations
|
||||
.Where(l => l.Area == area && l.Row == row)
|
||||
.ToList();
|
||||
|
||||
var pdf = RowPdfService.GenerateRowPdf(area, row, rowLocations);
|
||||
var fileName = $"Lagerplan_{area.GetDisplayName()}_Reihe{row}_{DateTime.Now:yyyyMMdd-HHmm}.pdf";
|
||||
await JS.InvokeVoidAsync("appInterop.downloadFile", fileName, Convert.ToBase64String(pdf), "application/pdf");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
printErrorRowKey = rowKey;
|
||||
printError = $"PDF konnte nicht erstellt werden: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
printingRowKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Batch creation
|
||||
private AreaType batchArea = AreaType.Lager;
|
||||
private int batchRow = 1;
|
||||
|
||||
Reference in new issue
Block a user