Togli il + dalla barra e porta le azioni nella testata
Il "+" stava incastrato a destra nella barra di navigazione, che per il resto contiene destinazioni. Cambiava significato da una schermata all'altra senza mai dichiararlo, e su Ispezioni apriva un menu per far scegliere fra una cosa sola. Il documento di stile esclude esplicitamente il FAB di serie, e la barra torna a contenere solo le due destinazioni. Su Ispezioni l'azione e' un bottone con il suo nome nella testata, e porta dritta alla scelta del punto vendita senza passaggi intermedi. Lo stato vuoto offre lo stesso comando invece di spiegare dove trovarlo. Su Ispezione le azioni sono tre e con pesi diversi: restano in un bottom sheet, aperto dalla testata. Eliminare un'ispezione ora chiede conferma — prima un tocco cancellava ispezione e schede senza appello. Le azioni vivono nella pagina che le esegue, quindi i messaggi che le rimbalzavano dalla barra (NewSchedaService, CompleteInspectionService) non hanno piu' mittente e se ne vanno. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,9 +17,7 @@ using SteUp.Shared.Core.Interface.IntegryApi;
|
|||||||
using SteUp.Shared.Core.Interface.LocalDb;
|
using SteUp.Shared.Core.Interface.LocalDb;
|
||||||
using SteUp.Shared.Core.Interface.System;
|
using SteUp.Shared.Core.Interface.System;
|
||||||
using SteUp.Shared.Core.Interface.System.Network;
|
using SteUp.Shared.Core.Interface.System.Network;
|
||||||
using SteUp.Shared.Core.Messages.Ispezione;
|
|
||||||
using SteUp.Shared.Core.Messages.Scanner;
|
using SteUp.Shared.Core.Messages.Scanner;
|
||||||
using SteUp.Shared.Core.Messages.Scheda;
|
|
||||||
using SteUp.Shared.Core.Messages.System;
|
using SteUp.Shared.Core.Messages.System;
|
||||||
using SteUp.Shared.Core.Services;
|
using SteUp.Shared.Core.Services;
|
||||||
|
|
||||||
@@ -63,9 +61,7 @@ public static class CoreModule
|
|||||||
public void RegisterMessageServices()
|
public void RegisterMessageServices()
|
||||||
{
|
{
|
||||||
builder.Services.AddSingleton<IMessenger, WeakReferenceMessenger>();
|
builder.Services.AddSingleton<IMessenger, WeakReferenceMessenger>();
|
||||||
builder.Services.AddSingleton<NewSchedaService>();
|
|
||||||
builder.Services.AddSingleton<OnScannerService>();
|
builder.Services.AddSingleton<OnScannerService>();
|
||||||
builder.Services.AddSingleton<CompleteInspectionService>();
|
|
||||||
builder.Services.AddSingleton<BackButtonService>();
|
builder.Services.AddSingleton<BackButtonService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,3 @@
|
|||||||
@using CommunityToolkit.Mvvm.Messaging
|
|
||||||
@using SteUp.Shared.Components.Layout.Sheet
|
|
||||||
@using SteUp.Shared.Components.SingleElements.MessageBox
|
|
||||||
@using SteUp.Shared.Core.Enum
|
|
||||||
@using SteUp.Shared.Core.Interface.LocalDb
|
|
||||||
@using SteUp.Shared.Core.Messages.Ispezione
|
|
||||||
@using SteUp.Shared.Core.Messages.Scheda
|
|
||||||
@inject INetworkService NetworkService
|
|
||||||
@inject IDialogService Dialog
|
|
||||||
@inject IMessenger Messenger
|
|
||||||
@inject IIspezioniService IspezioniService
|
|
||||||
@inject IJSRuntime Js
|
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
|
||||||
@*
|
@*
|
||||||
@@ -17,6 +5,10 @@
|
|||||||
sotto, le destinazioni restano a portata di pollice. Icona outline a
|
sotto, le destinazioni restano a portata di pollice. Icona outline a
|
||||||
riposo, piena da selezionata, etichetta sempre visibile in entrambe.
|
riposo, piena da selezionata, etichetta sempre visibile in entrambe.
|
||||||
Da 720px diventa una colonna laterale (vedi components.css).
|
Da 720px diventa una colonna laterale (vedi components.css).
|
||||||
|
|
||||||
|
Qui stanno SOLO le destinazioni. Le azioni di una schermata appartengono
|
||||||
|
alla schermata, e si trovano nella sua testata: un "+" incastrato nella
|
||||||
|
barra non dice cosa crea, e cambia significato da una pagina all'altra.
|
||||||
*@
|
*@
|
||||||
|
|
||||||
<nav class="navbar @(IsVisible ? "" : "navbar--hidden")" aria-label="Navigazione principale">
|
<nav class="navbar @(IsVisible ? "" : "navbar--hidden")" aria-label="Navigazione principale">
|
||||||
@@ -33,189 +25,32 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="navbar__label">Profilo</span>
|
<span class="navbar__label">Profilo</span>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
@if (ActionsVisible)
|
|
||||||
{
|
|
||||||
<button type="button" class="navbar__fab" @onclick="OpenActions"
|
|
||||||
aria-label="Azioni" title="Azioni">
|
|
||||||
<i class="ri-add-line" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<ActionSheet @bind-Open="_sheetOpen" Title="@SheetTitle" Subtitle="@SheetSubtitle">
|
|
||||||
<div class="stack stack-xs">
|
|
||||||
@if (OnInspectionPage)
|
|
||||||
{
|
|
||||||
@if (!_isCompleted)
|
|
||||||
{
|
|
||||||
<button type="button" class="action-tile" disabled="@(!NetworkService.IsNetworkAvailable())"
|
|
||||||
@onclick="NewScheda">
|
|
||||||
<span class="action-tile__icon action-tile__icon--primary">
|
|
||||||
<i class="ri-add-line" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
<span class="action-tile__label">Nuova scheda</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (ShowCompleteInspection)
|
|
||||||
{
|
|
||||||
<button type="button" class="action-tile" disabled="@(!NetworkService.IsNetworkAvailable())"
|
|
||||||
@onclick="CompleteInspection">
|
|
||||||
<span class="action-tile__icon action-tile__icon--success">
|
|
||||||
<i class="ri-check-double-line" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
<span class="action-tile__label">Concludi ispezione</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
<button type="button" class="action-tile" disabled="@(!NetworkService.IsNetworkAvailable())"
|
|
||||||
@onclick="DeleteInspection">
|
|
||||||
<span class="action-tile__icon action-tile__icon--danger">
|
|
||||||
<i class="ri-delete-bin-line" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
<span class="action-tile__label">Elimina ispezione</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<button type="button" class="action-tile" disabled="@(!NetworkService.IsNetworkAvailable())"
|
|
||||||
@onclick="NewInspection">
|
|
||||||
<span class="action-tile__icon action-tile__icon--primary">
|
|
||||||
<i class="ri-add-line" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
<span class="action-tile__label">Nuova ispezione</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!NetworkService.IsNetworkAvailable())
|
|
||||||
{
|
|
||||||
<div class="feedback feedback--warning" role="status">
|
|
||||||
<i class="feedback__icon ri-wifi-off-line" aria-hidden="true"></i>
|
|
||||||
<span>Senza connessione queste azioni non sono disponibili. Il lavoro gia' fatto resta sul dispositivo.</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</ActionSheet>
|
|
||||||
|
|
||||||
<ConfirmMessageBox @ref="_messageBox" NoText="Annulla" YesText="Concludi" YesColor="Color.Primary"
|
|
||||||
Message="Una volta conclusa, l'ispezione non sara' piu' modificabile e non potrai aggiungere altre schede. Procedere?"/>
|
|
||||||
|
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
private bool IsVisible { get; set; } = true;
|
private bool IsVisible { get; set; } = true;
|
||||||
private bool ActionsVisible { get; set; } = true;
|
|
||||||
private bool OnInspectionPage { get; set; }
|
|
||||||
private bool ShowCompleteInspection { get; set; }
|
|
||||||
private bool _isCompleted;
|
|
||||||
private bool _sheetOpen;
|
|
||||||
|
|
||||||
private ConfirmMessageBox _messageBox = null!;
|
|
||||||
|
|
||||||
private static readonly string[] NavigableRoutes = ["ispezioni", "ispezione", "user"];
|
private static readonly string[] NavigableRoutes = ["ispezioni", "ispezione", "user"];
|
||||||
|
|
||||||
private string SheetTitle => OnInspectionPage ? "Azioni ispezione" : "Nuova ispezione";
|
|
||||||
|
|
||||||
private string? SheetSubtitle => OnInspectionPage
|
|
||||||
? SteupDataService.InspectionPageState.Ispezione.CodMdep
|
|
||||||
: null;
|
|
||||||
|
|
||||||
private string CurrentRoute =>
|
private string CurrentRoute =>
|
||||||
NavigationManager.Uri.Remove(0, NavigationManager.BaseUri.Length).Split('?')[0];
|
NavigationManager.Uri.Remove(0, NavigationManager.BaseUri.Length).Split('?')[0];
|
||||||
|
|
||||||
private bool IsOn(string route) => CurrentRoute.EqualsIgnoreCase(route);
|
private bool IsOn(string route) => CurrentRoute.EqualsIgnoreCase(route);
|
||||||
|
|
||||||
protected override Task OnInitializedAsync()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
NavigationManager.LocationChanged += OnLocationChanged;
|
NavigationManager.LocationChanged += OnLocationChanged;
|
||||||
Refresh();
|
Refresh();
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLocationChanged(object? sender, LocationChangedEventArgs args)
|
private void OnLocationChanged(object? sender, LocationChangedEventArgs args) => Refresh();
|
||||||
{
|
|
||||||
// Cambiando schermata un menu aperto non ha piu' senso.
|
|
||||||
_sheetOpen = false;
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Refresh()
|
private void Refresh()
|
||||||
{
|
{
|
||||||
var route = CurrentRoute;
|
IsVisible = NavigableRoutes.Contains(CurrentRoute, StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
IsVisible = NavigableRoutes.Contains(route, StringComparer.OrdinalIgnoreCase);
|
|
||||||
OnInspectionPage = route.EqualsIgnoreCase("ispezione");
|
|
||||||
ActionsVisible = IsVisible && !route.EqualsIgnoreCase("user");
|
|
||||||
|
|
||||||
if (OnInspectionPage)
|
|
||||||
{
|
|
||||||
var ispezione = SteupDataService.InspectionPageState.Ispezione;
|
|
||||||
_isCompleted = ispezione.Stato == StatusEnum.Completata;
|
|
||||||
// "Concludi" non ha senso su un'ispezione mai inviata o gia' conclusa.
|
|
||||||
ShowCompleteInspection = !ispezione.ActivityId.IsNullOrEmpty() && !_isCompleted;
|
|
||||||
|
|
||||||
// Su un'ispezione conclusa resta solo la consultazione.
|
|
||||||
if (_isCompleted) ActionsVisible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenActions()
|
|
||||||
{
|
|
||||||
Refresh();
|
|
||||||
_sheetOpen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task NewInspection()
|
|
||||||
{
|
|
||||||
_sheetOpen = false;
|
|
||||||
|
|
||||||
if (await SteupDataService.CanOpenNewInspection())
|
|
||||||
{
|
|
||||||
_ = Dialog.OpenSelectShop();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await Dialog.ShowWarning(
|
|
||||||
"Per aprire una nuova ispezione devi prima concludere tutte le ispezioni aperte da piu' di 20 giorni.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task CompleteInspection()
|
|
||||||
{
|
|
||||||
_sheetOpen = false;
|
|
||||||
|
|
||||||
var result = await _messageBox.ShowAsync();
|
|
||||||
if (result is true) Messenger.Send(new CompleteInspectionMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task NewScheda()
|
|
||||||
{
|
|
||||||
_sheetOpen = false;
|
|
||||||
|
|
||||||
var ispezione = SteupDataService.InspectionPageState.Ispezione;
|
|
||||||
var modal = await Dialog.OpenFormScheda(ispezione.CodMdep, ispezione.Data, true);
|
|
||||||
|
|
||||||
if (modal is { Canceled: false }) Messenger.Send(new NewSchedaMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DeleteInspection()
|
|
||||||
{
|
|
||||||
_sheetOpen = false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var ispezione = SteupDataService.InspectionPageState.Ispezione;
|
|
||||||
await IspezioniService.DeleteIspezioneAsync(ispezione.CodMdep, ispezione.Data, ispezione.Rilevatore);
|
|
||||||
|
|
||||||
await Js.InvokeVoidAsync("goBack");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
await Dialog.ShowError(e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() => NavigationManager.LocationChanged -= OnLocationChanged;
|
public void Dispose() => NavigationManager.LocationChanged -= OnLocationChanged;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
@using Microsoft.Extensions.Logging
|
@using Microsoft.Extensions.Logging
|
||||||
@using SteUp.Shared.Components.Layout
|
@using SteUp.Shared.Components.Layout
|
||||||
@using SteUp.Shared.Components.Layout.Overlay
|
@using SteUp.Shared.Components.Layout.Overlay
|
||||||
|
@using SteUp.Shared.Components.Layout.Sheet
|
||||||
@using SteUp.Shared.Components.SingleElements
|
@using SteUp.Shared.Components.SingleElements
|
||||||
@using SteUp.Shared.Components.SingleElements.Card
|
@using SteUp.Shared.Components.SingleElements.Card
|
||||||
@using SteUp.Shared.Components.SingleElements.MessageBox
|
@using SteUp.Shared.Components.SingleElements.MessageBox
|
||||||
@@ -12,18 +13,66 @@
|
|||||||
@using SteUp.Shared.Core.Interface.IntegryApi
|
@using SteUp.Shared.Core.Interface.IntegryApi
|
||||||
@using SteUp.Shared.Core.Interface.LocalDb
|
@using SteUp.Shared.Core.Interface.LocalDb
|
||||||
@using SteUp.Shared.Core.Interface.System
|
@using SteUp.Shared.Core.Interface.System
|
||||||
@using SteUp.Shared.Core.Messages.Ispezione
|
|
||||||
@using SteUp.Shared.Core.Messages.Scheda
|
|
||||||
@inject NewSchedaService NewScheda
|
|
||||||
@inject CompleteInspectionService CompleteInspection
|
|
||||||
@inject IIspezioniService IspezioniService
|
@inject IIspezioniService IspezioniService
|
||||||
@inject IDialogService Dialog
|
@inject IDialogService Dialog
|
||||||
@inject IIntegrySteupService IntegrySteupService
|
@inject IIntegrySteupService IntegrySteupService
|
||||||
@inject IFileManager FileManager
|
@inject IFileManager FileManager
|
||||||
@inject ILogger<IspezionePage> Logger
|
@inject ILogger<IspezionePage> Logger
|
||||||
@implements IDisposable
|
|
||||||
|
|
||||||
<HeaderLayout Title="@Titolo" Subtitle="@Sottotitolo" Back="true"/>
|
<HeaderLayout Title="@Titolo" Subtitle="@Sottotitolo" Back="true">
|
||||||
|
<Actions>
|
||||||
|
@* Su un'ispezione conclusa resta solo la consultazione: niente azioni. *@
|
||||||
|
@if (!IsCompleted)
|
||||||
|
{
|
||||||
|
@* Qui le azioni sono piu' d'una e non hanno lo stesso peso: lo
|
||||||
|
sheet le mostra con nome, icona e tono, invece di nasconderle
|
||||||
|
tutte dietro lo stesso glifo. *@
|
||||||
|
<button type="button" class="appbar__icon-action" @onclick="@(() => _actionsOpen = true)"
|
||||||
|
aria-label="Azioni sull'ispezione" title="Azioni">
|
||||||
|
<i class="ri-more-2-fill" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</Actions>
|
||||||
|
</HeaderLayout>
|
||||||
|
|
||||||
|
<ActionSheet @bind-Open="_actionsOpen" Title="Azioni ispezione" Subtitle="@Ispezione.CodMdep">
|
||||||
|
<div class="stack stack-xs">
|
||||||
|
<button type="button" class="action-tile" disabled="@(!NetworkService.IsNetworkAvailable())"
|
||||||
|
@onclick="NewScheda">
|
||||||
|
<span class="action-tile__icon action-tile__icon--primary">
|
||||||
|
<i class="ri-add-line" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<span class="action-tile__label">Nuova scheda</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@if (!Ispezione.ActivityId.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
<button type="button" class="action-tile" disabled="@(!NetworkService.IsNetworkAvailable())"
|
||||||
|
@onclick="ConfirmCompleteInspection">
|
||||||
|
<span class="action-tile__icon action-tile__icon--success">
|
||||||
|
<i class="ri-check-double-line" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<span class="action-tile__label">Concludi ispezione</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
<button type="button" class="action-tile" disabled="@(!NetworkService.IsNetworkAvailable())"
|
||||||
|
@onclick="ConfirmDeleteInspection">
|
||||||
|
<span class="action-tile__icon action-tile__icon--danger">
|
||||||
|
<i class="ri-delete-bin-line" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
<span class="action-tile__label">Elimina ispezione</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@if (!NetworkService.IsNetworkAvailable())
|
||||||
|
{
|
||||||
|
<div class="feedback feedback--warning" role="status">
|
||||||
|
<i class="feedback__icon ri-wifi-off-line" aria-hidden="true"></i>
|
||||||
|
<span>Senza connessione queste azioni non sono disponibili. Il lavoro gia' fatto resta sul dispositivo.</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</ActionSheet>
|
||||||
|
|
||||||
<div class="app-scroll">
|
<div class="app-scroll">
|
||||||
<div class="page-width page-body stack stack-lg">
|
<div class="page-width page-body stack stack-lg">
|
||||||
@@ -92,8 +141,16 @@
|
|||||||
@if (!IsCompleted)
|
@if (!IsCompleted)
|
||||||
{
|
{
|
||||||
<p class="empty-state__text">
|
<p class="empty-state__text">
|
||||||
Tocca <b>+</b> nella barra in basso per creare la prima scheda di questa ispezione.
|
Aggiungi la prima scheda di questa ispezione.
|
||||||
</p>
|
</p>
|
||||||
|
<div class="empty-state__action">
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Rounded.Add"
|
||||||
|
Disabled="@(!NetworkService.IsNetworkAvailable())"
|
||||||
|
OnClick="NewScheda">
|
||||||
|
Nuova scheda
|
||||||
|
</MudButton>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -149,7 +206,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SpinnerOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="_success" Message="@_progressMessage"/>
|
<SpinnerOverlay VisibleOverlay="VisibleOverlay" SuccessAnimation="_success" Message="@_progressMessage"/>
|
||||||
<ConfirmMessageBox @ref="_exportRepartoBox" NoText="Annulla" YesText="Invia" YesColor="Color.Primary"
|
<ConfirmMessageBox @ref="_completeBox" Title="Concludere l'ispezione?" NoText="Annulla"
|
||||||
|
YesText="Concludi" YesColor="Color.Primary"
|
||||||
|
Message="Una volta conclusa, l'ispezione non sarà più modificabile e non potrai aggiungere altre schede."/>
|
||||||
|
<ConfirmMessageBox @ref="_deleteBox" Title="Eliminare l'ispezione?" NoText="Annulla"
|
||||||
|
YesText="Elimina" YesColor="Color.Error"
|
||||||
|
Message="L'ispezione e tutte le sue schede verranno eliminate dal dispositivo. L'operazione non è reversibile."/>
|
||||||
|
<ConfirmMessageBox @ref="_exportRepartoBox" Title="Inviare le schede del reparto?" NoText="Annulla"
|
||||||
|
YesText="Invia" YesColor="Color.Primary"
|
||||||
Message="Le schede complete di questo reparto verranno inviate al server. Procedere?"/>
|
Message="Le schede complete di questo reparto verranno inviate al server. Procedere?"/>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@@ -162,6 +226,10 @@
|
|||||||
private string? _progressMessage;
|
private string? _progressMessage;
|
||||||
|
|
||||||
private ConfirmMessageBox _exportRepartoBox = null!;
|
private ConfirmMessageBox _exportRepartoBox = null!;
|
||||||
|
private ConfirmMessageBox _completeBox = null!;
|
||||||
|
private ConfirmMessageBox _deleteBox = null!;
|
||||||
|
|
||||||
|
private bool _actionsOpen;
|
||||||
|
|
||||||
private Ispezione Ispezione => SteupDataService.InspectionPageState.Ispezione;
|
private Ispezione Ispezione => SteupDataService.InspectionPageState.Ispezione;
|
||||||
private bool IsCompleted => Ispezione.Stato == StatusEnum.Completata;
|
private bool IsCompleted => Ispezione.Stato == StatusEnum.Completata;
|
||||||
@@ -185,13 +253,7 @@
|
|||||||
|
|
||||||
private string Sottotitolo => Ispezione.CodMdep;
|
private string Sottotitolo => Ispezione.CodMdep;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized() => LoadSchede();
|
||||||
{
|
|
||||||
NewScheda.OnNewScheda += LoadSchede;
|
|
||||||
CompleteInspection.OnComplete += HandleCompleteInspection;
|
|
||||||
|
|
||||||
LoadSchede();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadSchede()
|
private void LoadSchede()
|
||||||
{
|
{
|
||||||
@@ -208,6 +270,44 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task NewScheda()
|
||||||
|
{
|
||||||
|
_actionsOpen = false;
|
||||||
|
|
||||||
|
var modal = await Dialog.OpenFormScheda(Ispezione.CodMdep, Ispezione.Data, true);
|
||||||
|
if (modal is { Canceled: false }) LoadSchede();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ConfirmCompleteInspection()
|
||||||
|
{
|
||||||
|
_actionsOpen = false;
|
||||||
|
|
||||||
|
var confirmed = await _completeBox.ShowAsync();
|
||||||
|
if (confirmed is true) HandleCompleteInspection();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ConfirmDeleteInspection()
|
||||||
|
{
|
||||||
|
_actionsOpen = false;
|
||||||
|
|
||||||
|
// Prima non c'era conferma: un tocco cancellava l'ispezione e tutte le
|
||||||
|
// sue schede senza appello.
|
||||||
|
var confirmed = await _deleteBox.ShowAsync();
|
||||||
|
if (confirmed is not true) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var ispezione = Ispezione;
|
||||||
|
await IspezioniService.DeleteIspezioneAsync(ispezione.CodMdep, ispezione.Data, ispezione.Rilevatore);
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo("/ispezioni");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
OnError(e, e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void HandleCompleteInspection()
|
private async void HandleCompleteInspection()
|
||||||
{
|
{
|
||||||
// Guardia anti doppio-invio: il completamento è irreversibile.
|
// Guardia anti doppio-invio: il completamento è irreversibile.
|
||||||
@@ -496,10 +596,4 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
|
||||||
{
|
|
||||||
NewScheda.OnNewScheda -= LoadSchede;
|
|
||||||
CompleteInspection.OnComplete -= HandleCompleteInspection;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,21 @@
|
|||||||
@using SteUp.Shared.Core.Entities
|
@using SteUp.Shared.Core.Entities
|
||||||
@using SteUp.Shared.Core.Interface.LocalDb
|
@using SteUp.Shared.Core.Interface.LocalDb
|
||||||
@inject IIspezioniService IspezioniService
|
@inject IIspezioniService IspezioniService
|
||||||
|
@inject IDialogService Dialog
|
||||||
|
|
||||||
<HeaderLayout Title="Ispezioni" Subtitle="@Subtitle"/>
|
<HeaderLayout Title="Ispezioni" Subtitle="@Subtitle">
|
||||||
|
<Actions>
|
||||||
|
@* L'unica azione della schermata: porta dritta alla scelta del punto
|
||||||
|
vendita. Un passaggio intermedio per scegliere fra una cosa sola non
|
||||||
|
e' una scelta, e' un tocco in piu'. *@
|
||||||
|
<button type="button" class="appbar__action" @onclick="NewInspection"
|
||||||
|
disabled="@(!NetworkService.IsNetworkAvailable())"
|
||||||
|
title="@(NetworkService.IsNetworkAvailable() ? null : "Serve la connessione per aprire una nuova ispezione")">
|
||||||
|
<i class="ri-add-line" aria-hidden="true"></i>
|
||||||
|
<span>Nuova</span>
|
||||||
|
</button>
|
||||||
|
</Actions>
|
||||||
|
</HeaderLayout>
|
||||||
|
|
||||||
<div class="app-scroll">
|
<div class="app-scroll">
|
||||||
<div class="page-width page-body">
|
<div class="page-width page-body">
|
||||||
@@ -32,8 +45,16 @@
|
|||||||
<i class="empty-state__icon ri-clipboard-line" aria-hidden="true"></i>
|
<i class="empty-state__icon ri-clipboard-line" aria-hidden="true"></i>
|
||||||
<p class="empty-state__title">Nessuna ispezione</p>
|
<p class="empty-state__title">Nessuna ispezione</p>
|
||||||
<p class="empty-state__text">
|
<p class="empty-state__text">
|
||||||
Tocca <b>+</b> nella barra in basso per aprire la prima ispezione su un punto vendita.
|
Apri la prima ispezione scegliendo il punto vendita da controllare.
|
||||||
</p>
|
</p>
|
||||||
|
<div class="empty-state__action">
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
||||||
|
StartIcon="@Icons.Material.Rounded.Add"
|
||||||
|
Disabled="@(!NetworkService.IsNetworkAvailable())"
|
||||||
|
OnClick="NewInspection">
|
||||||
|
Nuova ispezione
|
||||||
|
</MudButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -65,6 +86,22 @@
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task NewInspection()
|
||||||
|
{
|
||||||
|
if (await SteupDataService.CanOpenNewInspection())
|
||||||
|
{
|
||||||
|
var modal = await Dialog.OpenSelectShop();
|
||||||
|
// La scelta del punto vendita naviga da sola sull'ispezione; se
|
||||||
|
// l'utente torna indietro, la lista dev'essere quella aggiornata.
|
||||||
|
if (modal is { Canceled: true }) return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Dialog.ShowWarning(
|
||||||
|
"Per aprire una nuova ispezione devi prima concludere tutte le ispezioni aperte da piu' di 20 giorni.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnClickIspezione(Ispezione ispezione)
|
private void OnClickIspezione(Ispezione ispezione)
|
||||||
{
|
{
|
||||||
SteupDataService.InspectionPageState.Ispezione = ispezione;
|
SteupDataService.InspectionPageState.Ispezione = ispezione;
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
|
||||||
|
|
||||||
namespace SteUp.Shared.Core.Messages.Ispezione;
|
|
||||||
|
|
||||||
public class CompleteInspectionMessage(object? value = null) : ValueChangedMessage<object?>(value);
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
|
|
||||||
namespace SteUp.Shared.Core.Messages.Ispezione;
|
|
||||||
|
|
||||||
public class CompleteInspectionService
|
|
||||||
{
|
|
||||||
public event Action? OnComplete;
|
|
||||||
|
|
||||||
public CompleteInspectionService(IMessenger messenger)
|
|
||||||
{
|
|
||||||
messenger.Register<CompleteInspectionMessage>(this, (_, _) => { OnComplete?.Invoke(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
|
||||||
|
|
||||||
namespace SteUp.Shared.Core.Messages.Scheda;
|
|
||||||
|
|
||||||
public class NewSchedaMessage(object? value = null) : ValueChangedMessage<object?>(value);
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
|
|
||||||
namespace SteUp.Shared.Core.Messages.Scheda;
|
|
||||||
|
|
||||||
public class NewSchedaService
|
|
||||||
{
|
|
||||||
public event Action? OnNewScheda;
|
|
||||||
|
|
||||||
public NewSchedaService(IMessenger messenger)
|
|
||||||
{
|
|
||||||
messenger.Register<NewSchedaMessage>(this, (_, _) => { OnNewScheda?.Invoke(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -565,39 +565,18 @@
|
|||||||
.navbar__label {
|
.navbar__label {
|
||||||
font-size: var(--label-md-size);
|
font-size: var(--label-md-size);
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Icona piena e pastiglia di selezione sulla voce attiva. */
|
/* Icona piena e pastiglia di selezione sulla voce attiva. */
|
||||||
.navbar__item.active { color: var(--primary-dark); }
|
.navbar__item.active { color: var(--primary-dark); }
|
||||||
|
.navbar__item.active .navbar__label { font-weight: 600; }
|
||||||
.navbar__item.active .navbar__icon { background-color: var(--info-surface); }
|
.navbar__item.active .navbar__icon { background-color: var(--info-surface); }
|
||||||
|
|
||||||
.navbar__item:active .navbar__icon { transform: scale(0.94); }
|
.navbar__item:active .navbar__icon { transform: scale(0.94); }
|
||||||
|
|
||||||
/* Azione primaria della schermata, dentro la barra e a portata di pollice. */
|
|
||||||
.navbar__fab {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 56px;
|
|
||||||
height: 44px;
|
|
||||||
margin: 12px var(--space-sm) 12px 0;
|
|
||||||
border: none;
|
|
||||||
border-radius: var(--radius-control);
|
|
||||||
background-color: var(--primary);
|
|
||||||
color: var(--on-primary);
|
|
||||||
font-size: 26px;
|
|
||||||
transition: transform var(--duration-fast) var(--ease-out),
|
|
||||||
background-color var(--duration-fast) var(--ease-out);
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar__fab:active { transform: scale(0.94); background-color: var(--primary-pressed); }
|
|
||||||
.navbar__fab:disabled { background-color: var(--divider); color: var(--ink-muted); }
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.navbar__item:active .navbar__icon,
|
.navbar__item:active .navbar__icon { transform: none; }
|
||||||
.navbar__fab:active { transform: none; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Da 720px la navigazione diventa una colonna laterale (rail). */
|
/* Da 720px la navigazione diventa una colonna laterale (rail). */
|
||||||
@@ -617,13 +596,6 @@
|
|||||||
|
|
||||||
.navbar__item { flex: 0 0 auto; padding-block: var(--space-xs); }
|
.navbar__item { flex: 0 0 auto; padding-block: var(--space-xs); }
|
||||||
|
|
||||||
.navbar__fab {
|
|
||||||
order: -1;
|
|
||||||
width: 56px;
|
|
||||||
height: 48px;
|
|
||||||
margin: var(--space-xs) auto var(--space-sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-shell { padding-left: calc(96px + var(--space-lg)); }
|
.app-shell { padding-left: calc(96px + var(--space-lg)); }
|
||||||
.page-body { padding-bottom: calc(var(--space-lg) + env(safe-area-inset-bottom, 0px)); }
|
.page-body { padding-bottom: calc(var(--space-lg) + env(safe-area-inset-bottom, 0px)); }
|
||||||
}
|
}
|
||||||
@@ -1123,3 +1095,93 @@
|
|||||||
.skeleton--line { height: 15px; width: 100%; }
|
.skeleton--line { height: 15px; width: 100%; }
|
||||||
.skeleton--line-short { height: 15px; width: 40%; }
|
.skeleton--line-short { height: 15px; width: 40%; }
|
||||||
.skeleton--badge { height: 24px; width: 110px; border-radius: var(--radius-pill); }
|
.skeleton--badge { height: 24px; width: 110px; border-radius: var(--radius-pill); }
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
Azioni della testata
|
||||||
|
L'azione primaria di una schermata sta qui, con il suo nome: dice cosa fa
|
||||||
|
prima di essere toccata, e resta la stessa cosa in ogni pagina. Il vecchio
|
||||||
|
"+" dentro la barra di navigazione cambiava significato da una schermata
|
||||||
|
all'altra e non lo dichiarava mai.
|
||||||
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.appbar__action {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-6);
|
||||||
|
min-height: 40px;
|
||||||
|
padding: 0 var(--space-14) 0 var(--space-sm);
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--radius-pill);
|
||||||
|
background-color: var(--primary);
|
||||||
|
color: var(--on-primary);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: var(--label-lg-size);
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: transform var(--duration-fast) var(--ease-out),
|
||||||
|
background-color var(--duration-fast) var(--ease-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
.appbar__action i { font-size: 20px; }
|
||||||
|
|
||||||
|
.appbar__action:active { transform: scale(0.96); background-color: var(--primary-pressed); }
|
||||||
|
.appbar__action:disabled { background-color: var(--divider); color: var(--ink-muted); }
|
||||||
|
|
||||||
|
/* Variante a sola icona, per le schermate dove le azioni sono piu' d'una e
|
||||||
|
vivono in un bottom sheet. */
|
||||||
|
.appbar__icon-action {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: var(--touch-min);
|
||||||
|
height: var(--touch-min);
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--radius-pill);
|
||||||
|
background: none;
|
||||||
|
color: var(--ink);
|
||||||
|
font-size: 22px;
|
||||||
|
transition: background-color var(--duration-fast) var(--ease-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
.appbar__icon-action:active { background-color: var(--surface-muted); }
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.appbar__action:active { transform: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
Riga di scelta di un punto vendita
|
||||||
|
E' una card, ma si comporta da riga: testo a sinistra, chevron a destra.
|
||||||
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
.shop-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-sm);
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
font-family: inherit;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-card__text {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-card__chevron {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
font-size: 22px;
|
||||||
|
color: var(--ink-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* L'indirizzo serve a distinguere due negozi con lo stesso nome, non a essere
|
||||||
|
letto per intero: due righe bastano e tengono l'elenco scorrevole. */
|
||||||
|
.shop-card .list-card__meta {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user