Commit Graph

73 Commits

Author SHA1 Message Date
MarcoE ac501dc261 Metti l'anello di focus solo sui comandi
La regola valeva per qualunque elemento, e la WebView sposta il fuoco anche su
contenitori non interattivi: dopo la chiusura di un dialog restava un anello
azzurro intorno al titolo della testata, che indicava un bersaglio inesistente.
Ora lo prendono link, bottoni, campi e gli elementi dichiaratamente tappabili.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:46:28 +02:00
MarcoE 2d7e3c591e Dai una gerarchia ai pesi tipografici
Quasi tutto il testo dell'app stava fra 600 e 800: etichette, valori, indirizzi,
conteggi, voci di elenco. Un grassetto ovunque non segnala niente, e la pagina
Profilo era il caso peggiore — ogni riga gridava come un titolo.

La scala ora ha quattro gradini, documentati nei token:
  400  corpo, metadati, valori descrittivi
  500  etichette di campo, voci di lista, testo dei controlli
  600  stati brevi (badge, voce attiva), nomi in una riga di elenco
  700  titoli, uno solo per blocco

Sopra il 700 non si sale: l'800 dei titoli di card e dell'avatar e' sceso a 700.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:46:28 +02:00
MarcoE 7099f02b60 Ridai il titolo ai dialog di conferma
MudDialogProvider aveva NoHeader="true" come valore predefinito di tutti i
dialog. MudMessageBox rende il proprio titolo nella testata, quindi quel
valore lo sopprimeva ovunque: davanti a "Elimina" si leggeva solo il testo
delle conseguenze, senza la domanda.

Le schermate a tutto schermo (form scheda, scelta punto vendita, scelta
articoli) chiedono gia' NoHeader per conto loro nelle DialogOptions, quindi
toglierlo dal provider non le tocca.

I titoli ora dicono cosa sta per succedere invece del generico "Attenzione!":
"Eliminare la scheda?", "Uscire dall'account?", "Inviare le schede del
reparto?".

Le scelte in fondo al dialog si dispongono a destra e, sotto i 380 punti,
diventano una colonna a piena larghezza: con etichette lunghe come "Salva come
bozza" i bersagli non si comprimono.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:45:47 +02:00
MarcoE ca0aaf69b5 Allinea lo splash alla superficie dell'app
Lo splash era rosa (#FDECEA) mentre l'app apre su #E9EDF2: a ogni avvio si
vedeva un lampo di colore prima della prima schermata. Ora e' la stessa
superficie, e il passaggio non si nota.

Il tema dello splash deriva da quello generato da MAUI e chiede le icone di
sistema scure, coerenti con lo sfondo chiaro. Su Android 12+ lo splash e'
disegnato dal sistema, che dell'attributo puo' non tenere conto: sul terminale
di prova le icone restano chiare per la frazione di secondo dello splash.

Marchio da 128 a 112: su 360 punti di larghezza riempiva troppo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:45:34 +02:00
MarcoE 52b2994d3b Intercetta il tasto indietro dove passa davvero
Il salvataggio come bozza non e' mai scattato dal tasto indietro: la UI Blazor
non riceveva l'evento, e uscire da un form con modifiche in corso buttava via
il lavoro esattamente come prima che la bozza esistesse.

Il back non arrivava a OnBackPressed per due motivi diversi:
- da AndroidX Activity 1.6 il gesto passa dall'OnBackPressedDispatcher e il
  metodo dell'Activity non viene piu' invocato;
- con la navigazione a tre tasti il back arriva come evento di tastiera e la
  WebView lo intercetta per conto suo, tornando indietro nella propria
  cronologia, prima che Activity o dispatcher lo vedano.

Ora la chiave si ferma in DispatchKeyEvent, che passa prima della gerarchia di
view, e resta un callback sul dispatcher per la navigazione a gesti, dove
evento di tastiera non ce n'e'. Entrambi restano accesi solo finche' la UI ha
davvero qualcosa da dire: altrimenti il back si comporta come sempre.

I gestori diventano una pila, cosi' sopra il form puo' aprirsi un bottom sheet
e il back chiude prima quello senza portarsi via la registrazione sottostante.
ActionSheet si registra da solo mentre e' aperto.

Verificato sull'EDA52: back sul form con modifiche apre "Lavoro non salvato" e
salva la bozza; back sullo sheet chiude solo lo sheet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 12:45:23 +02:00
MarcoE 811d8a86d8 Correzioni alla UI dopo la verifica sul terminale
Prime correzioni fatte guardando l'app su un Honeywell EDA52 (720x1440
@320dpi, cioe' 360 punti logici di larghezza) invece che a occhio.

- Barra di stato: era tinta di corallo da colorPrimaryDark, cioe' l'accento
  usato come decorazione della cornice di sistema. Ora si fonde con lo
  sfondo dell'app, con icone scure (WindowInsetsController).
- Gradino compatto sotto i 380px: la scala di STILE_UI e' tarata su telefoni
  piu' larghi, e a misura piena i titoli si troncavano e in una schermata
  entrava pochissimo lavoro. Le proporzioni restano, cambia la taglia.
  Sui telefoni normali non cambia nulla.
- Icone delle azioni costruttive: usavano il fondo del tono danger, quindi
  "Nuova scheda" e "Aggiungi una foto" erano identiche a "Elimina
  ispezione". Ora usano il tono info. Un --primary-surface non risolveva:
  il primario di SteUP e' gia' un rosso, quindi un suo fondo tenue resta
  indistinguibile da quello danger.
- Testata: il titolo puo' andare su due righe prima di troncare. Il nome del
  punto vendita e' l'ancora del compito, "D11-PRIMO PREZ..." non aiuta.
- Schermata ispezione: il nome del punto vendita non e' piu' ripetuto nel
  pannello di riepilogo, dove era gia' in testata.
- Padding dei gruppi di form e della barra azioni ridotti su schermo stretto.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:52:31 +02:00
MarcoE 2a0054aa30 Rifacimento della UI secondo STILE_UI.md
Adotta lo stile condiviso delle app Integry: superfici piatte, raggi ampi,
spaziature a scala fissa, gerarchia data dallo spazio prima che dalla
decorazione. La palette storica di SteUP resta intatta; sono stati aggiunti
solo i ruoli che mancavano (workspace, surfaceMuted, divider, inkMuted e le
triplette dei toni semantici).

Fondamenta
- tokens.css: ruoli colore, scale di spazio/raggi/tipografia, curve di
  movimento e scala z-index semantica. Unica fonte di verita': pilotano
  anche le variabili CSS di MudBlazor.
- Inter variabile ospitata in locale (133KB) al posto di Nunito da Google
  Fonts: l'app lavora offline, un font che arriva dalla rete in campo non
  arriva.
- base.css: shell applicativa e comportamenti da app nativa — niente
  selezione testo, niente menu al tocco lungo, niente lampo grigio sul tap,
  niente rimbalzo elastico, niente zoom a doppio tocco, scroll con inerzia.
- mudblazor-overrides.css: MudBlazor appiattito (elevation 0, nessun tint,
  target 44/48, etichette in caso naturale).
- Rimossi Bootstrap (CSS, icone e JS) e i 996 righe di CSS con ambito per
  componente del vecchio sistema: erano tutti inutilizzati.

Struttura
- Navigazione flottante in basso con icona piena sulla voce attiva; da 720px
  diventa colonna laterale. Il MudFabMenu e' sostituito da un bottom sheet:
  stessa funzione, bersagli molto piu' grandi.
- Testata alta col titolo a sinistra, fusa con la pagina.
- Nel form scheda il salvataggio sta in una barra ancorata in fondo, non in
  coda a uno scroll lungo.
- Scelta di punto vendita e articoli a schermo intero con ricerca; la
  selezione multipla usa righe da 56px invece di un menu a tendina.
- Urgenza scelta a pillole invece che da una select.

Stato e riscontro
- StatusBadgeHelper: tono, icona ed etichetta di ogni stato in un punto solo,
  cosi' lo stesso stato si presenta identico ovunque.
- Scheletri al posto degli spinner; l'overlay bloccante dice sempre cosa sta
  facendo; gli stati vuoti suggeriscono la mossa successiva.
- Rimosso il ritardo artificiale di 250ms in InspectionCard, che non
  attendeva nulla.

DESIGN.md riscritto sul nuovo sistema.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:09:26 +02:00
MarcoE 3a9174f6fc Raddrizza le foto applicando l'orientamento EXIF
La fotocamera di sistema non ruota lo scatto: salva i pixel come li legge
il sensore e annota la rotazione in EXIF. SkiaSharp (SKBitmap.Decode)
ignora quel tag, quindi le foto scattate ruotate finivano storte nelle
miniature e venivano inviate cosi' al server.

- ImageOrientation: applica l'orientamento ai pixel e ricodifica senza tag
  residui, mantenendo il formato di partenza. Immagine gia' dritta: nessuna
  ricodifica, per non perdere qualita' inutilmente. In caso di errore
  restituisce i byte originali, meglio una foto storta che nessuna foto.
- UtilityFile.ConvertToDto: normalizza li', unico punto di passaggio di
  fotocamera e galleria, cosi' miniature, salvataggio locale e upload
  lavorano su pixel gia' dritti. Corretto anche DimensionBytes.
- ImageThumb: applica l'orientamento anche in fase di miniatura, per
  raddrizzare le foto gia' presenti sul dispositivo.

Nessun ritratto forzato: costringere una foto orizzontale in verticale
vorrebbe dire ruotare il contenuto o ritagliarlo, e queste foto sono prove
di ispezione.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 10:32:41 +02:00
MarcoE 3b04702665 Decodifica PLU dai barcode CODE128 a 7 cifre
Oltre alle etichette a peso variabile (EAN13/CODE128 a 13 cifre), ora
vengono riconosciuti i CODE128 di 7 cifre che iniziano con '2': si scarta
il prefisso e restano le 6 cifre del PLU, come per DecodeEanPeso.
2026-09-16 18:07:43 +02:00
MarcoE 0174316bb7 Niente errore quando il trigger viene premuto a vuoto
Honeywell emette BarcodeFailureEvent anche solo premendo e rilasciando il
trigger senza inquadrare nulla: e' la normale mancata lettura, non un
guasto. Finiva pero' in OnScanFailed insieme ai guasti veri, quindi ogni
pressione a vuoto fermava il rilevatore con un dialog bloccante contenente
il toString() Java grezzo:

  Scan failure: com.honeywell.aidc.BarcodeFailureEvent[source=...]

Ora l'evento e' ignorato: chi preme il trigger sa gia' di non aver letto
niente, non serve alcun riscontro. OnScanFailed resta riservato ai guasti
reali (ScannerUnavailableException alla Claim, init di AidcManager fallito).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 17:57:41 +02:00
MarcoE d076a4b77a 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>
2026-09-16 13:24:35 +02:00
MarcoE e3942d00cc Fix rilevamento modifiche nella scheda: articoli e allegati
Uscendo dalla scheda il prompt di salvataggio non compariva e il pulsante
"Salva" restava nascosto, perche' IsDirty non vedeva il lavoro fatto:

- gli articoli scelti dalla griglia (OpenSelectArt) non marcavano mai la
  scheda come modificata;
- ValueComparer confronta solo i campi del form, quindi ogni RecalcDirty()
  successivo azzerava il flag alzato con forceTrue da scanner e allegati.
  Non bastava confrontare Articoli: Clone() e' un MemberwiseClone, quindi
  _originalScheda condivide la stessa lista.

Ora il confronto usa uno snapshot dei barcode preso all'apertura piu' un
flag per gli allegati (che vivono in AttachedList fino al salvataggio), e
RecalcDirty() perde forceTrue: non puo' piu' essere azzerato. Le chiamate
su insert/remove degli articoli erano anche fatte prima della modifica
della lista, quindi valutavano lo stato precedente.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:23:34 +02:00
MarcoE 92b60deac0 Fix tastiera che copre il campo di scrittura
Da Android 15 (API 35+) l'edge-to-edge e' forzato e adjustResize non
ridimensiona piu' la finestra: la tastiera si limita a coprire la
BlazorWebView. Con il layout rigido (html overflow:hidden, #app 100vh,
page/main height:100% overflow:hidden) nemmeno il browser riesce a
portare in vista il campo col focus.

- MainActivity: WindowSoftInputMode AdjustResize|StateHidden e listener
  sugli WindowInsets che applica al content view il padding bottom pari
  all'inset IME (meno quello delle system bars, gia' coperto da
  SafeAreaEdges in MainPage), cosi' il 100vh si ricalcola.
- main.js: su focusin e visualViewport resize porta il campo attivo al
  centro con scrollIntoView, necessario per i contenitori scrollabili.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 11:33:36 +02:00
MarcoE 963eba1e84 Finish v1.1.1(5) 2026-07-22 14:50:59 +02:00
MarcoE 48e55226f3 Finish v1.1.1(5) 2026-07-22 14:50:59 +02:00
MarcoE 55c0e539b1 -> v1.1.1 (5) 2026-07-22 14:50:54 +02:00
MarcoE 5ec7468b1c Fix scanner barcode per i plu 2026-07-22 14:50:09 +02:00
MarcoE 74b671586f Fix duplicazione scheda quando si modificava 2026-07-22 13:06:49 +02:00
MarcoE b2c8174d6f Finish v1.1.0(4) 2026-07-14 14:25:56 +02:00
MarcoE ce704fa91b Finish v1.1.0(4) 2026-07-14 14:25:55 +02:00
MarcoE 2fad8557ba -> 1.1.0 (4) 2026-07-14 14:25:48 +02:00
MarcoE a81689bd56 Fix vari 2026-07-14 14:22:26 +02:00
MarcoE 4e13db24f6 Fix: nota descrittiva suggerita ora visibile subito nel campo note
Il MudTextField delle note ha DebounceInterval e non rifletteva una modifica
del Value fatta da codice. Aggiunta una @key sul campo che, incrementata
quando si applica il suggerimento, forza Blazor a ricreare il campo con la
nota selezionata gia impostata: la nota compare subito a video.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:57:02 +02:00
MarcoE c454474f49 Migliora IspezionePage e form scheda (design review impeccable)
Ispezione:
- Stato sync visibile: badge per-scheda (Da inviare/Inviato) e contatore
  "N da inviare" per reparto (nuovo SchedaSyncHelper)
- Completamento: progresso reale nell'overlay + spunta di successo;
  NON completa se una scheda fallisce (resta editabile, schede "Da inviare")
- Export reparto/completamento blindati: conferma + guardia anti doppio-tap,
  try/finally che libera sempre l'overlay
- Accento corallo unico per l'azione "invia"; target di tocco >=44px;
  empty state; solo il primo pannello espanso di default
- Tasto "Invia" nascosto sulle schede gia inviate
- Messaggio d'errore comprensibile in campo (dettaglio tecnico nei log)
- Fix OnSchedaModified (index >= 0)

Aspetto card:
- SchedaCard e InspectionCard: superficie Carta + hairline border + ombra
  morbida (nuovo token --card-box-shadow); pagina con tinta Grigio Campo
- SchedaCard compattata

Form scheda (ModalFormScheda):
- Tasto Salva/Aggiorna full-width
- Fix "Suggerisci note descrittive": la nota selezionata ora viene inserita
  nel campo (metodo async sul thread UI + OnAfterChangeValue)

StatusEnum: etichette in sentence-case

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:39:20 +02:00
MarcoE 9f4088eff3 Init claude e impeccable 2026-07-08 15:10:12 +02:00
MarcoE a04ccde2ec Spostato tasto salva 2026-07-06 15:00:38 +02:00
MarcoE a3d27c9ef8 Rimossa richiesta fotocamera - galleria e implementata apertura automatica fotocamera 2026-07-06 09:34:00 +02:00
MarcoE c2ff6bbbe5 Finish v1.0.2(3) 2026-06-17 10:48:45 +02:00
MarcoE 294c2d1dd0 Finish v1.0.2(3) 2026-06-17 10:48:44 +02:00
MarcoE 2a42036c29 -> v1.0.2 (3) 2026-06-17 10:48:37 +02:00
MarcoE 339828004d Aggiunta compatibilità con Honeywell CT40 2026-06-17 10:47:45 +02:00
MarcoE 76ac8f051e Finish v1.0.1(2) 2026-04-23 14:52:11 +02:00
MarcoE a1b4ff664d Finish v1.0.1(2) 2026-04-23 14:52:07 +02:00
MarcoE bc8582d3f5 -> v1.0.1 (2) 2026-04-23 14:51:59 +02:00
MarcoE 38ef7ebd33 Aggiunta compatibilità con Honeywell CT70-X1 2026-04-23 14:49:00 +02:00
MarcoE 98d2dda780 Aggiornamento librerie 2026-04-23 14:45:48 +02:00
MarcoE f09ea026bc Aggiunta cancellazione ispezione 2026-04-23 11:22:13 +02:00
MarcoE c2da0e150d Fix get ispezioni 2026-04-23 10:57:10 +02:00
MarcoE f9e4957ae3 Aggiunta compatibilità con HoneyWell CT40XP 2026-04-23 10:56:32 +02:00
MarcoE 43f17c1410 Fix caricamento apertura 2026-03-19 10:09:05 +01:00
MarcoE 0abe88939b Fix prese tutte le ispezioni legate all'utente 2026-03-05 16:53:05 +01:00
MarcoE e57738a37f Fix chiamata api 2026-03-04 12:59:32 +01:00
MarcoE 21ee5137b0 Creato metodo per la rimozione delle ispezioni più vecchie di 60 giorni 2026-03-04 12:08:57 +01:00
MarcoE 2d938fb210 Fix gestione allegati e creato metodo di esportazione log 2026-03-04 11:51:42 +01:00
MarcoE 3760e38c8d Esportazione immagini anche con ispezione completata 2026-03-03 12:50:17 +01:00
MarcoE e1e0c91db5 Nascosto + in caso l'ispezione è completata 2026-03-02 16:54:14 +01:00
MarcoE 99a5395a1f Vario 2026-03-02 16:12:58 +01:00
MarcoE 8fbeaf8637 Aggiunto messaggio per completamento ispezione 2026-03-02 13:01:19 +01:00
MarcoE 63368748ab Aggiunto blocco per ispezioni non completate più vecchie di 20 giorni 2026-03-02 12:30:34 +01:00
MarcoE ab9578a45f Gestiti salvataggi rest 2026-03-02 10:50:34 +01:00