@inject ITireStackService TireStackService @inject ITireReportService TireReportService @inject UserSessionService UserSession
@if (isOpen) {
@if (isLoading) {
Messungen werden geladen…
} else { @if (!string.IsNullOrEmpty(error)) { } @if (AllowEdit) {
} @if (editing != null) {

@(isNew ? "Neue Messung" : "Messung bearbeiten")

mm
mm
mm
mm
@if (!string.IsNullOrEmpty(editing.ReportUrl)) { Original-Report öffnen ↗ }
} @if (inspections.Count == 0) { @if (editing == null) {

Noch keine Profiltiefen-Messung fĂĽr diesen Satz vorhanden.

} } else { } }
}
@if (AllowEdit) { } @code { [Parameter, EditorRequired] public Guid TireStackId { get; set; } [Parameter] public bool AllowEdit { get; set; } [Parameter] public bool Compact { get; set; } [Parameter] public bool InitiallyOpen { get; set; } [Parameter] public string? ScannerSubtitle { get; set; } [Parameter] public EventCallback OnLatestChanged { get; set; } private static readonly System.Globalization.CultureInfo De = System.Globalization.CultureInfo.GetCultureInfo("de-DE"); private readonly string panelId = $"insp-{Guid.NewGuid():N}"; private Guid loadedFor; private bool isOpen; private bool loaded; private bool isLoading; private bool isBusy; private bool isFetching; private bool showScanner; private string? error; private List inspections = new(); private TireInspection? latest; private TireInspection? editing; private bool isNew; private Guid? confirmDeleteId; protected override async Task OnParametersSetAsync() { if (loadedFor != TireStackId) { loadedFor = TireStackId; inspections = new(); latest = null; loaded = false; editing = null; confirmDeleteId = null; error = null; isOpen = InitiallyOpen; await LoadAsync(); } } private async Task LoadAsync() { isLoading = true; try { inspections = await TireStackService.GetInspectionsAsync(TireStackId); latest = inspections.FirstOrDefault(); loaded = true; } catch (Exception ex) { error = $"Messungen konnten nicht geladen werden: {ex.Message}"; } finally { isLoading = false; } } private void Toggle() => isOpen = !isOpen; private static string RatingClass(TireMeasureRating r) => r switch { TireMeasureRating.Ok => "ok", TireMeasureRating.Warning => "warn", TireMeasureRating.Critical => "crit", _ => "none" }; private static string Fmt(decimal? mm) => mm.HasValue ? mm.Value.ToString("0.0", De) + " mm" : "–"; private void OpenScanner() { error = null; showScanner = true; } private async Task OnQrScanned(string text) { showScanner = false; if (!TireReportService.TryParseReportUrl(text, out var recordSn, out _)) { error = "Der QR-Code enthält keinen gültigen Reifen-Report-Link."; return; } isFetching = true; error = null; StateHasChanged(); try { var report = await TireReportService.FetchAsync(recordSn); report.RecomputeRatings(); editing = report.ToInspection(TireStackId, UserSession.CurrentUser?.Id); isNew = true; } catch (TireReportException ex) { error = ex.Message; } catch (Exception ex) { error = $"Report konnte nicht verarbeitet werden: {ex.Message}"; } finally { isFetching = false; } } private void StartManual() { error = null; confirmDeleteId = null; isNew = true; editing = new TireInspection { TireStackId = TireStackId, Source = "Manuell", MeasuredAt = DateTime.UtcNow, CreatedByUserId = UserSession.CurrentUser?.Id }; } private void StartEdit(TireInspection insp) { error = null; confirmDeleteId = null; isNew = false; editing = new TireInspection { Id = insp.Id, TireStackId = insp.TireStackId, Source = insp.Source, RecordSn = insp.RecordSn, ReportUrl = insp.ReportUrl, MeasuredAt = insp.MeasuredAt, LicensePlate = insp.LicensePlate, Mileage = insp.Mileage, TreadDepthFL = insp.TreadDepthFL, TreadDepthFR = insp.TreadDepthFR, TreadDepthRL = insp.TreadDepthRL, TreadDepthRR = insp.TreadDepthRR, Recommendation = insp.Recommendation, RawJson = insp.RawJson, CreatedAt = insp.CreatedAt, CreatedByUserId = insp.CreatedByUserId }; } private void OnDateChanged(ChangeEventArgs e) { if (editing == null) return; if (DateTime.TryParse(e.Value?.ToString(), out var d)) editing.MeasuredAt = DateTime.SpecifyKind(d, DateTimeKind.Local).ToUniversalTime(); else editing.MeasuredAt = null; } private void CancelEdit() { editing = null; error = null; } private async Task SaveEdit() { if (editing == null) return; isBusy = true; error = null; StateHasChanged(); try { editing.RatingFL = TireInspection.RateDepth(editing.TreadDepthFL); editing.RatingFR = TireInspection.RateDepth(editing.TreadDepthFR); editing.RatingRL = TireInspection.RateDepth(editing.TreadDepthRL); editing.RatingRR = TireInspection.RateDepth(editing.TreadDepthRR); editing.LicensePlate = string.IsNullOrWhiteSpace(editing.LicensePlate) ? null : editing.LicensePlate.Trim(); editing.Recommendation = string.IsNullOrWhiteSpace(editing.Recommendation) ? null : editing.Recommendation.Trim(); if (isNew) await TireStackService.AddInspectionAsync(editing); else await TireStackService.UpdateInspectionAsync(editing); editing = null; await LoadAsync(); await OnLatestChanged.InvokeAsync(latest); } catch (Exception ex) { error = $"Speichern fehlgeschlagen: {ex.Message}"; } finally { isBusy = false; } } private async Task Delete(TireInspection insp) { isBusy = true; error = null; try { await TireStackService.DeleteInspectionAsync(insp.Id); confirmDeleteId = null; await LoadAsync(); await OnLatestChanged.InvokeAsync(latest); } catch (Exception ex) { error = $"Löschen fehlgeschlagen: {ex.Message}"; } finally { isBusy = false; } } }