@using SteUp.Shared.Components.Layout @using SteUp.Shared.Components.Layout.Overlay @using SteUp.Shared.Components.Layout.Spinner @using SteUp.Shared.Components.SingleElements.Card.ModalForm @using SteUp.Shared.Components.SingleElements.MessageBox @using SteUp.Shared.Core.Dto @using SteUp.Shared.Core.Entities @using SteUp.Shared.Core.Interface.IntegryApi @using SteUp.Shared.Core.Interface.LocalDb @using SteUp.Shared.Core.Interface.System @using SteUp.Shared.Core.Interface.System.Network @using SteUp.Shared.Core.Messages.Scanner @inject INetworkService NetworkService @inject IDialogService Dialog @inject IIntegryApiService IntegryApiService @inject IAttachedService AttachedService @inject IIspezioniService IspezioniService @inject IIntegrySteupService IntegrySteupService @inject OnScannerService OnScannerService
@foreach (var fasi in SteupDataService.Reparti) { @fasi.Descrizione } @foreach (var type in SteupDataService.TipiAttività.Where(x => x.CodJfas.EqualsIgnoreCase(Scheda.CodJfas!))) { @type.ActivityTypeId } @if (FileLoading) {
} else if (!AttachedList.IsNullOrEmpty()) {
@foreach (var item in AttachedList!.Select((p, index) => new { p, index })) { @if (!item.p.ThumbPath.IsNullOrEmpty()) { } @item.p.Name }
} @if (!IsView) {
Aggiungi foto
}
@if (!Scheda.Articoli.IsNullOrEmpty()) {
@foreach (var articolo in Scheda.Articoli) { @articolo.Descrizione Barcode: @articolo.Barcode }
}
@if (!IsView) {
Consulta articoli
}
Suggerisci note descrittive
@code { [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; [Parameter] public required string CodMdep { get; set; } [Parameter] public required DateOnly Data { get; set; } [Parameter] public bool IsNew { get; set; } [Parameter] public Scheda Scheda { get; set; } = new(); private bool IsView => !NetworkService.ConnectionAvailable; private string? ManualBarcode { get; set; } //Overlay private bool VisibleOverlay { get; set; } private bool SuccessAnimation { get; set; } private bool OnLoading { get; set; } private string? TextLoading { get; set; } private bool FileLoading { get; set; } private ConfirmUpdateActivity _confirmUpdateMessage = null!; private MudForm _form = null!; private string? LabelSave { get; set; } private bool IsDirty { get; set; } private Scheda _originalScheda = null!; private List? AttachedList { get; set; } protected override void OnInitialized() { Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter; OnScannerService.OnNewScanSuccessful += HandleNewScanSuccessful; OnScannerService.OnErrorScan += OnErrorScan; _originalScheda = Scheda.Clone(); Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter; LoadAttached(); } private void LoadAttached() { FileLoading = true; StateHasChanged(); Task.Run(async () => { var fileList = await AttachedService.GetInspectionFiles( new Ispezione { CodMdep = CodMdep, Data = Data, Rilevatore = UserSession.User.Username } ); await InvokeAsync(() => { AttachedList = fileList; FileLoading = false; StateHasChanged(); }); }); } private async Task Save() { VisibleOverlay = true; StateHasChanged(); if (IsNew) await NewSave(); else await Update(); await AttachedService.CleanTempStorageAsync(); SuccessAnimation = true; StateHasChanged(); await Task.Delay(1250); DisposeMessage(); MudDialog.Close(Scheda); } private async Task NewSave() { if (!AttachedList.IsNullOrEmpty()) { foreach (var attached in AttachedList!) { var fileNameAdded = await AttachedService.SaveInspectionFile( new Ispezione { CodMdep = CodMdep, Data = Data, Rilevatore = UserSession.User.Username }, attached.FileBytes!, attached.Name! ); Scheda.ImageNames ??= []; if (fileNameAdded != null) Scheda.ImageNames.Add(fileNameAdded); } } await IspezioniService.AddSchedaAsync(CodMdep, Data, UserSession.User.Username, Scheda); } private async Task Update() { if (!AttachedList.IsNullOrEmpty()) { foreach (var attached in AttachedList!.Where(x => !x.SavedOnAppData)) { var ispezione = new Ispezione { CodMdep = CodMdep, Data = Data, Rilevatore = UserSession.User.Username }; if (!attached.ToRemove) { var fileNameAdded = await AttachedService.SaveInspectionFile( ispezione, attached.FileBytes!, attached.Name! ); Scheda.ImageNames ??= []; if (fileNameAdded != null) Scheda.ImageNames.Add(fileNameAdded); } else _ = AttachedService.RemoveInspectionFile(ispezione, attached.Name!); } } await IspezioniService.UpdateSchedaAsync(Scheda); } private async Task Cancel() { if (await CheckSavePreAction()) { await AttachedService.CleanTempStorageAsync(); DisposeMessage(); MudDialog.Cancel(); } } #region Form private void OnAfterChangeReparto() { Scheda.ActivityTypeId = null; OnAfterChangeValue(); } private void OnAfterChangeValue() { RecalcDirty(); StateHasChanged(); } private void RecalcDirty(bool forceTrue = false) { IsDirty = forceTrue || !ValueComparer.AreEqual(Scheda, _originalScheda); if (IsDirty) LabelSave = !IsNew ? "Aggiorna" : "Salva"; else LabelSave = null; } private static class ValueComparer { public static bool AreEqual(Scheda? a, Scheda? b) { if (a is null || b is null) return a == b; return a.CodJfas == b.CodJfas && a.DescrizioneReparto == b.DescrizioneReparto && a.ActivityTypeId == b.ActivityTypeId && a.Note == b.Note && a.Responsabile == b.Responsabile && a.Scadenza == b.Scadenza; } } private async Task CheckSavePreAction() { if (!IsDirty) return true; var resul = await _confirmUpdateMessage.ShowAsync(); if (resul is not true) return true; VisibleOverlay = true; StateHasChanged(); await Submit(); VisibleOverlay = false; StateHasChanged(); return false; } private async Task Submit() { await _form.Validate(); if (_form.IsValid) await Save(); } #endregion #region File private async Task OpenAddAttached() { var result = await ModalHelper.OpenAddAttached(Dialog); if (result is not { Canceled: false, Data: List attachedList }) return; OnLoading = true; await InvokeAsync(StateHasChanged); await Task.Yield(); // prepara placeholder in UI subito (così vedi le card con spinner) AttachedList ??= []; foreach (var a in attachedList) AttachedList.Add(new AttachedDto { Name = a.Name, MimeType = a.MimeType, FileBytes = a.FileBytes }); await InvokeAsync(StateHasChanged); RecalcDirty(true); // Processa in background e aggiorna UI man mano (o a blocchi) _ = Task.Run(async () => { for (var i = 0; i < attachedList.Count; i++) { var a = attachedList[i]; if (a.FileBytes is null || a.Name is null) continue; var (origUrl, thumbUrl) = await AttachedService.SaveAndCreateThumbAsync(a.FileBytes, a.Name); await InvokeAsync(() => { var target = AttachedList![AttachedList.Count - attachedList.Count + i]; target.TempPath = origUrl; target.ThumbPath = thumbUrl; StateHasChanged(); }); } await InvokeAsync(() => { OnLoading = false; StateHasChanged(); }); }); } private void OpenSelectArt() { if (Scheda.CodJfas.IsNullOrEmpty()) { Snackbar.Clear(); Snackbar.Add("Selezionare prima il reparto", Severity.Error); return; } OnLoading = true; TextLoading = "Download articoli in griglia"; StateHasChanged(); _ = Task.Run(async () => { List? articoli; try { articoli = await IntegrySteupService.RetrieveGrigliaPlu( new RetrieveGrigliaPluRequestDto { CodMdep = CodMdep, ActivityTypeId = Scheda.ActivityTypeId, CodJfas = Scheda.CodJfas } ); } catch (Exception e) { await InvokeAsync(() => { OnLoading = false; TextLoading = null; StateHasChanged(); OnError(e.Message); }); return; } var modal = await ModalHelper.OpenSelectArt(Dialog, articoli); await InvokeAsync(() => { OnLoading = false; TextLoading = null; StateHasChanged(); }); if (modal is { Canceled: false, Data: List articoliSelezionati }) { Scheda.Articoli.AddRange(articoliSelezionati.ConvertAll(x => new SchedaArticolo { Barcode = x.Barcode, Descrizione = x.Descrizione }) ); await InvokeAsync(StateHasChanged); } }); } private void OnRemoveAttached(int index) { if (AttachedList is null || index < 0 || index >= AttachedList.Count) return; if (AttachedList[index].SavedOnAppData) AttachedList[index].ToRemove = true; AttachedList.RemoveAt(index); RecalcDirty(true); StateHasChanged(); } #endregion private void SuggestActivityDescription() { if (Scheda.ActivityTypeId == null) { Snackbar.Add("Indicare prima il motivo", Severity.Error); return; } VisibleOverlay = true; StateHasChanged(); _ = Task.Run(async () => { var activityDescriptions = await IntegryApiService.SuggestActivityDescription(Scheda.ActivityTypeId); var modal = await ModalHelper.OpenSuggestActivityDescription(Dialog, activityDescriptions); if (modal is { Canceled: false, Data: not null }) Scheda.Note = modal.Data!.ToString(); VisibleOverlay = false; await InvokeAsync(StateHasChanged); }); } #region Scanner private void OnManualBarcodeSet() { if (ManualBarcode == null) return; HandleNewScanSuccessful(ManualBarcode); ManualBarcode = null; } private async void HandleNewScanSuccessful(string? value) { try { if (value is null) return; if (Scheda.Articoli.Any(x => x.Barcode.Equals(value))) return; await InvokeAsync(() => { OnLoading = true; StateHasChanged(); }); var art = await IntegrySteupService.RetrieveArtFromBarcode(value); await InvokeAsync(() => { OnLoading = false; StateHasChanged(); if (art != null) { RecalcDirty(true); Scheda.Articoli.Add(new SchedaArticolo { Barcode = art.Barcode, Descrizione = art.Descrizione }); StateHasChanged(); } else { OnError("Nessun articolo trovato"); } }); } catch (Exception e) { await InvokeAsync(() => { OnLoading = false; StateHasChanged(); }); OnError(e.Message); } } private void OnErrorScan(string? value) => OnError(value); #endregion private void OnError(string? errorMessage) { if (errorMessage == null) return; _ = ModalHelper.ShowError(Dialog, errorMessage); } private void RemoveArt(string barcode) { var index = Scheda.Articoli.FindIndex(x => x.Barcode.Equals(barcode)); if (index < 0) return; RecalcDirty(true); Scheda.Articoli.RemoveAt(index); StateHasChanged(); } private void DisposeMessage() { OnScannerService.OnNewScanSuccessful -= HandleNewScanSuccessful; OnScannerService.OnErrorScan -= OnErrorScan; } }