Salvataggio come bozza: il lavoro in corso non si perde piu'
Uscendo da una scheda a meta' (tasto indietro del dispositivo o "Annulla")
il lavoro veniva scartato. Il tasto indietro non era nemmeno gestito: non
arriva alla WebView e non c'e' stack di navigazione, quindi mandava l'app
in background con i dati solo in memoria.
Nuovo stato Bozza ("Da completare"): salvata in locale, mai inviabile
finche' non viene conclusa.
- Scheda.Bozza + migration additiva (default false: le schede esistenti
non cambiano stato).
- SchedaSyncHelper: terzo SyncState, CountBozze(). CountDaInviare()
esclude le bozze, quindi il badge "da inviare" resta corretto.
- ModalFormScheda: SaveDraft() salva solo in locale senza validazione;
Save() azzera il flag; Submit() avvisa quando il form e' invalido
(prima il tocco su "Salva" sembrava non fare nulla se i campi mancanti
erano fuori schermo); Update() prende preserveActivityId cosi' una
bozza di scheda gia' inviata mantiene il link al server e al
completamento lo aggiorna invece di duplicarlo.
- ConfirmUpdateActivity: il pulsante bozza sta su NoText, non CancelText
(CancelText ritorna null, NoText ritorna false).
- BackButtonService + MainActivity.OnBackPressed: il tasto indietro passa
dallo stesso percorso di "Annulla". Ignorato mentre e' aperto un dialog
figlio, per non mostrare il prompt sotto un altro dialog.
- IspezionePage: "Concludi ispezione" si blocca se ci sono bozze,
"Esporta reparto" le salta, chip "N da completare" per reparto.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,12 @@ public class Scheda : EntityBase<Scheda>
|
||||
|
||||
public List<SchedaArticolo> Articoli { get; set; } = [];
|
||||
public List<string>? ImageNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Scheda salvata in locale ma non ancora completata (es. uscita dal form con lavoro in corso).
|
||||
/// Non viene mai inviata al server finché il rilevatore non la conclude.
|
||||
/// </summary>
|
||||
public bool Bozza { get; set; }
|
||||
|
||||
public string? DescrizioneReparto { get; set; }
|
||||
public string? ActivityTypeId { get; set; }
|
||||
|
||||
@@ -14,19 +14,27 @@ public enum SyncState
|
||||
DaInviare = 0,
|
||||
|
||||
/// Inviata al server (ha un ActivityId).
|
||||
Inviato = 1
|
||||
Inviato = 1,
|
||||
|
||||
/// Salvata in locale ma non completata: da riprendere, non inviabile.
|
||||
Bozza = 2
|
||||
}
|
||||
|
||||
public static class SchedaSyncHelper
|
||||
{
|
||||
public static SyncState GetSyncState(this Scheda scheda) =>
|
||||
string.IsNullOrEmpty(scheda.ActivityId) ? SyncState.DaInviare : SyncState.Inviato;
|
||||
scheda.Bozza
|
||||
? SyncState.Bozza
|
||||
: string.IsNullOrEmpty(scheda.ActivityId)
|
||||
? SyncState.DaInviare
|
||||
: SyncState.Inviato;
|
||||
|
||||
public static string ToLabel(this SyncState state) =>
|
||||
state switch
|
||||
{
|
||||
SyncState.DaInviare => "Da inviare",
|
||||
SyncState.Inviato => "Inviato",
|
||||
SyncState.Bozza => "Da completare",
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
@@ -39,6 +47,7 @@ public static class SchedaSyncHelper
|
||||
{
|
||||
SyncState.DaInviare => Color.Primary,
|
||||
SyncState.Inviato => Color.Success,
|
||||
SyncState.Bozza => Color.Warning,
|
||||
_ => Color.Default
|
||||
};
|
||||
|
||||
@@ -47,10 +56,16 @@ public static class SchedaSyncHelper
|
||||
{
|
||||
SyncState.DaInviare => Icons.Material.Rounded.PhonelinkOff,
|
||||
SyncState.Inviato => Icons.Material.Rounded.CloudDone,
|
||||
SyncState.Bozza => Icons.Material.Rounded.EditNote,
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
/// Numero di schede non ancora inviate in una lista.
|
||||
/// Numero di schede non ancora inviate in una lista. Le bozze non contano:
|
||||
/// non sono inviabili finché non vengono completate.
|
||||
public static int CountDaInviare(this IEnumerable<Scheda> schede) =>
|
||||
schede.Count(s => s.GetSyncState() == SyncState.DaInviare);
|
||||
|
||||
/// Numero di schede lasciate a metà, da riprendere.
|
||||
public static int CountBozze(this IEnumerable<Scheda> schede) =>
|
||||
schede.Count(s => s.GetSyncState() == SyncState.Bozza);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace SteUp.Shared.Core.Messages.System;
|
||||
|
||||
/// <summary>
|
||||
/// Ponte fra il tasto indietro del dispositivo (host nativo) e la UI Blazor.
|
||||
/// Il form scheda si registra mentre è aperto così il back non manda l'app in
|
||||
/// background buttando via il lavoro non salvato: passa invece dallo stesso
|
||||
/// percorso del pulsante "Annulla", che propone il salvataggio come bozza.
|
||||
/// </summary>
|
||||
public class BackButtonService
|
||||
{
|
||||
private Func<Task>? _handler;
|
||||
|
||||
/// Registra il gestore corrente. Ritorna l'azione di deregistrazione.
|
||||
public IDisposable Register(Func<Task> handler)
|
||||
{
|
||||
_handler = handler;
|
||||
return new Registration(this, handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invocato dall'host nativo. Ritorna true se la UI Blazor ha preso in carico
|
||||
/// il tasto indietro: in quel caso l'host non deve fare altro.
|
||||
/// </summary>
|
||||
public bool TryHandleBackPressed()
|
||||
{
|
||||
var handler = _handler;
|
||||
if (handler is null) return false;
|
||||
|
||||
// Fire-and-forget: il gestore rientra nel dispatcher Blazor da solo.
|
||||
_ = handler();
|
||||
return true;
|
||||
}
|
||||
|
||||
private sealed class Registration(BackButtonService owner, Func<Task> handler) : IDisposable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
// Non azzerare se nel frattempo si è registrato qualcun altro.
|
||||
if (ReferenceEquals(owner._handler, handler)) owner._handler = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user