Files
EpicNext-Cms/docs/CATALOG_REFACTOR_PLAN.md
Simo 193b6686a9
CI / check (push) Successful in 1m16s
CI / deploy (push) Successful in 28s
refactor(catalog): unify commands and embed guarded catalog workspace
2026-09-06 19:40:52 +02:00

12 KiB

Refactor del catalogo HK — analisi e programma

Data: 6 settembre 2026. Base verificata: main, commit 9b0ea2fb. Documento di proposta, non implementazione approvata. Il sito /admin/catalog reindirizza al login senza sessione staff: nessuna prova delle mutazioni sul database di produzione. Le criticità indicate sono percorsi verificati nel codice; gli effetti concorrenti richiedono riproduzione controllata.

Obiettivo e perimetro

Un catalogo HK con un solo ambiente di lavoro, regole coerenti e operazioni recuperabili. Conservare stile HK, icone reali, salvataggio diretto, catalogo normale e Builder Club. Nessun ritorno dei Preferiti.

Inclusi: albero, categorie, offerte, prezzi, bundle, disponibilità, proprietà condivise dei furni, traduzioni, ricerca, anteprima, operazioni massive, manutenzione, collegamenti a Catalog Studio e sincronizzazione Git/hotel.

Catalog Studio conserva la responsabilità di importare, convertire e riparare .nitro, icone e furnidata. Il refactor collega questi strumenti alla selezione del catalogo; non comporta riscrivere il convertitore, cambiare protocollo dell'emulatore o sostituire il sistema Git/Gitea già esistente.

Inventario verificato

Sono già presenti virtualizzazione dell'albero, trascinamento, multiselezione, griglia/tabella, editor dei prezzi, anteprima negozio, import massivo, traduzioni, manutenzione e coda di export Git. Vanno riutilizzati.

File Righe attuali Responsabilità da separare
src/app/admin/catalog/[id]/catalog-items-table/catalog-items-table.tsx 2342 Rendering, selezione, editor offerta/furno, prezzi massivi, drag and drop, dialoghi
src/components/admin/catalog-manager/sortable-tree.tsx 1135 Lettura albero, mutazioni, ricerca, trascinamento, comandi
src/components/admin/catalog-manager/inline-editor.tsx 775 Fetch, stato modifiche, schede, salvataggio, anteprima
src/app/admin/catalog/[id]/catalog-page-form.tsx 738 Campi, layout, media, salvataggio
src/app/admin/catalog/[id]/catalog-translate-tab.tsx 617 Selezione, proposta traduzioni, applicazione
src/app/admin/catalog/builder-club/bc-manager.tsx 608 Gestione parallela BC
src/app/admin/catalog/page.tsx 526 Query, conteggi, varianti normale/BC, composizione UI

Le dimensioni aiutano a trovare i punti di intervento: l'obiettivo non è un limite arbitrario di righe, ma responsabilità verificabili e riutilizzabili.

Problemi e interventi

Priorità Evidenza Intervento
P0 sortable-tree.tsx invia il riordino dei fratelli con Promise.allSettled, una action per riga; catalog.ts aggiorna RCON per ciascuna Un comando batch con lista completa, validazione, transazione e un solo evento di aggiornamento
P0 catalog-items.ts riordina le offerte con update sequenziali fuori transazione Stesso contratto atomico per l'ordine delle offerte
P0 updateCatalogPage accetta parentId direttamente; il controllo cicli è separato in movePage Validazione comune per creazione, form, spostamento e API; controllare destinazioni inesistenti e concorrenza
P0 deletePage normale sposta figli, elimina offerte e pagina separatamente Transazione, analisi dell'impatto e snapshot ripristinabile
P0 updateCatalogItem modifica pagina, offerta e items_base con scritture separate Transazione e verifica che il furno appartenga all'offerta; scope distinto per proprietà condivise
P1 cascadeDelete non mantiene un insieme di nodi visitati; il calcolo profondità BC è ricorsivo senza guardia ai cicli Lettura tollerante di dati incoerenti, diagnostica e arresto sicuro delle traversate
P1 handleEditTab modifica lo stato prima della conferma; chiusura X bypassa la protezione Un unico controllo delle modifiche per cambio pagina, offerta, scheda, uscita e navigazione
P1 loadPage/loadItemsData non annullano o identificano la richiesta precedente AbortController e identità della selezione; solo la risposta corrente può aggiornare l'editor
P1 Il salvataggio ignora il booleano restituito da RCON; Git opera in coda Distinguere DB salvato, invio hotel riuscito/fallito e stato Git; retry senza risalvare i dati
P1 loadCatalogItemsData usa Number(value)
P2 Tutte le offerte e metadati sono caricati insieme; filtro con CAST(page_id AS CHAR) Misurare query/payload, separare elenco e dettagli, paginazione e adapter compatibile INT/VARCHAR
P2 Editor normale/BC e form condividono solo parte delle regole; testi anche letterali Contratti comuni, differenze BC esplicite, traduzioni e permessi coerenti

Riferimenti principali: src/actions/catalog.ts, src/actions/catalog-items.ts, src/actions/catalog-bc.ts, src/lib/services/catalog-tree.ts, src/lib/services/catalog-items-loader.ts, src/app/api/admin/catalog/tree/route.ts, src/components/admin/catalog-manager/catalog-manager-dialog.tsx, src/components/admin/catalog-manager/inline-editor.tsx.

Alternative

  1. Pulizia dei file mantenendo tutti gli editor: rischio iniziale basso, ma conserva duplicazioni e differenze operative. Utile solo come passaggio iniziale.
  2. Refactor progressivo con un editor principale — consigliato: servizi comuni prima, poi promozione del Visual Manager a pagina. Permette piccoli rilasci e confronti tra vecchio e nuovo percorso.
  3. Riscrittura completa: libertà maggiore, ma più rischio di perdere casi speciali, compatibilità DB e funzioni già presenti. Non giustificata dall'inventario attuale.

Architettura proposta

Modulo src/features/catalog con confini chiari:

  • domain/: tipi Page, Offer, FurnitureReference, CatalogKind; validazione gerarchie, prezzi, bundle e disponibilità; nessuna dipendenza React/DB.
  • server/queries/: letture albero, elenco offerte, dettaglio e ricerca; output serializzabile esplicito.
  • server/commands/: create/update/move/reorder/delete; autorizzazione, validazione, transazioni, controllo revisione e audit.
  • server/repositories/: accesso Drizzle e compatibilità delle colonne; adapter normale/BC senza fingere che tutti i campi coincidano.
  • client/: stato selezione, modifiche locali, operazioni in corso, caricamento e gestione conflitti.
  • components/: albero, elenco offerte, editor categoria, editor offerta, dettagli furno, diagnostica, stato sincronizzazione.

Le route e le action attuali rimangono inizialmente adapter sottili. Un unico risultato di operazione include ID operazione, revisione, elementi modificati, eventuali errori di campo e stato sincronizzazione. Non introdurre nuove librerie prima di verificare i limiti degli strumenti già installati.

Flusso di scrittura: permesso → validazione → verifica revisione → transazione DB con audit → risposta di salvataggio → aggiornamento hotel/export Git. La durabilità del passaggio DB→coda va garantita con un evento persistito nella transazione o meccanismo equivalente verificato. Un fallimento Git/RCON non deve far ripetere una creazione già committata. Riutilizzare il worker e la coda esistenti, aggiungendo idempotenza dove manca.

UX proposta

Pagina /admin/catalog con barra: Normale/BC, ricerca, nuova categoria, aggiungi furni, stato operazioni. Sotto: categorie a sinistra, offerte al centro, dettagli a destra. Il pannello dettagli si richiude; su schermi piccoli diventa una vista dedicata. Un solo scorrimento per ciascuna area, azioni di salvataggio sempre raggiungibili.

La URL conserva catalogo, categoria, offerta, vista e ricerca; i campi non salvati restano nello stato locale. Indietro/avanti e ricaricamento devono riaprire il contesto corretto. I vecchi URL dei dettagli continuano a funzionare.

Tre oggetti riconoscibili:

  • Categoria: percorso, titolo, icona, layout, visibilità e requisiti.
  • Offerta: prezzo, valuta, quantità, componenti bundle, disponibilità e ordine.
  • Furno condiviso: classname, sprite, dimensioni e interazioni; mostrare quante offerte lo referenziano prima di una modifica globale.

Idee operative:

  • Ricerca trasversale per nome, classname, ID pagina/offerta/furno e sprite ID, con percorso nei risultati.
  • Selettore visuale di categoria e layout; proprietà tecniche nelle Avanzate.
  • Prezzi con icone reali delle valute; mostrare il prima/dopo delle operazioni massive, arrotondamenti ed elementi esclusi.
  • Multiselezione con riepilogo di spostamento/eliminazione; dopo un errore mantenere selezionati i falliti.
  • Anteprima del negozio già esistente integrata nel contesto; non presentarla come prova completa del comportamento del client hotel.
  • Diagnostica su richiesta: offerta, SQL, furnidata, Nitro e icona separati. Collegamento a Catalog Studio sul furno esatto; nessuna scansione pesante a ogni apertura.
  • Storico di chi/cosa/quando con differenze e ripristino. Il ripristino controlla revisioni successive: non sovrascrive in silenzio modifiche di altri operatori e non annulla acquisti già avvenuti.
  • Riepilogo visibile: salvato, invio hotel, Git. Gli errori hanno riferimento al monitor CMS.
  • Stati vuoti, errori, caricamento e sola lettura distinti; traduzioni complete e uso da tastiera.

Programma di lavoro e criteri di uscita

Lotto Consegna Criterio per proseguire
1. Baseline Matrice funzioni/route/permessi normale e BC; fixture con bundle, LTD, offerte speciali, zeri/null, alberi incoerenti; misure query e rete Tutti i flussi esistenti hanno una destinazione nel piano, senza omissioni
2. Integrità Validatori, transazioni di riordino/spostamento/eliminazione, gerarchie sicure, revisioni Un fallimento intermedio non lascia dati parziali; due operatori non si sovrascrivono
3. Servizi condivisi Query/command/repository e risultato comune; vecchie route come adapter Vecchie UI superano le stesse prove con il nuovo backend
4. Stato editor Unica gestione delle modifiche, richieste annullabili, risposta coerente con selezione Annullare l'uscita conserva tutto; cambi rapidi mostrano sempre l'ultima selezione
5. Pagina unificata Visual Manager nella pagina, griglia/tabella condivise, URL, layout adattivo Parità normale/BC e vecchi link conservati; niente perdita di scroll o azioni nascoste
6. Operazioni avanzate Ricerca, editor bundle, prezzi massivi con differenze, storico e diagnosi contestuale Gli effetti sono spiegati prima dell'applicazione; retry applica solo ciò che manca
7. Sincronizzazione Stato DB/hotel/Git, operazioni persistenti, retry/idempotenza Guasto dopo commit e riavvio worker non duplicano né perdono l'operazione
8. Prestazioni e rimozione duplicati Paginazione, caricamento progressivo, accessibilità, eliminazione vecchi componenti Confronto misurato e prove finali; nessuna route o funzione rimasta senza equivalente

I lotti 2 e 7 condividono il contratto delle operazioni: progettare subito evento persistente e idempotenza, anche se la UI di stato arriva dopo. Nessuna stima in giorni finché non sono note dimensioni reali del catalogo, varianti DB e casi speciali attivi. Ogni lotto può richiedere più PR piccole; niente sostituzione monolitica.

Verifica e rilascio

Test unitari delle regole; integrazione su MariaDB per rollback, concorrenza e varianti INT/VARCHAR; browser con permessi lettura/modifica, desktop e schermo ridotto. Simulare doppio submit, timeout, risposta fuori ordine, fallimento RCON, Git non raggiungibile, riavvio dopo commit. Conservare test e componenti esistenti finché la parità non è dimostrata.

Registrare baseline e risultati per categorie grandi/piccole: richieste per riordino, tempo DB, payload, tempo fino a editor utilizzabile, risposte fallite. Non promettere percentuali senza dati.

Rilascio progressivo con selezione reversibile del nuovo editor. Il ritorno alla UI precedente deve usare gli stessi servizi corretti. Migrazioni additive e compatibili; il rollback dell'app non deve richiedere la cancellazione di dati. Eliminare le vecchie UI solo dopo parità verificata. Confermare CI, deploy, health e prove staff prima di dichiarare risolto il flusso live.

Primo passo consigliato

Lotti 1 e 2: inventario di compatibilità e correzione delle operazioni a rischio, mantenendo inizialmente l'aspetto corrente. Poi estrarre i servizi e unificare l'editor. È la sequenza che permette di migliorare UX senza portare avanti gli stessi difetti dentro una nuova schermata.