--- phase: 01-core-generation-pipeline plan: 04 subsystem: ui tags: [react, typescript, tanstack-query, react-router, tailwindcss, lucide-react] # Dependency graph requires: - phase: 01-core-generation-pipeline (plan 01) provides: App.tsx skeleton, BrowserRouter basename, api/client.ts con API_BASE - phase: 01-core-generation-pipeline (plan 03) provides: tutti gli endpoint API (settings, generate/bulk, job polling, export CSV, calendar) provides: - Web UI React completa con 5 pagine e sidebar di navigazione - Dashboard con stato API key e quick actions - GenerateCalendar con form + async polling via ProgressIndicator - OutputReview con griglia PostCard + SlideViewer + edit inline + CSV export - GenerateSingle con form completo e anteprima - Settings con form API key, LLM model, nicchie, frequenza - TanStack Query hooks per tutti gli endpoint API (11 hooks) - TypeScript types che rispecchiano gli schemas Pydantic del backend affects: - fase deploy (frontend buildato, pronto per docker multi-stage) - Phase 2+ (tutti i componenti riutilizzabili per future feature) # Tech tracking tech-stack: added: - (nessuna dipendenza aggiunta — tutto già in package.json) patterns: - "TanStack Query: useQuery per GET, useMutation per POST/PUT, refetchInterval condizionale per polling" - "Edit inline pattern: click-to-edit via EditableField component con blur/escape per conferma" - "Async job flow: mutation ritorna job_id -> ProgressIndicator polling -> navigate a OutputReview" - "Palette stone/amber: stone-950 sidebar, stone-900 background, amber-500 accent per B2B" key-files: created: - frontend/src/types.ts - frontend/src/api/hooks.ts - frontend/src/components/Layout.tsx - frontend/src/components/Sidebar.tsx - frontend/src/components/BadgePN.tsx - frontend/src/components/BadgeSchwartz.tsx - frontend/src/components/PostCard.tsx - frontend/src/components/SlideViewer.tsx - frontend/src/components/ProgressIndicator.tsx - frontend/src/pages/Dashboard.tsx - frontend/src/pages/Settings.tsx - frontend/src/pages/GenerateCalendar.tsx - frontend/src/pages/OutputReview.tsx - frontend/src/pages/GenerateSingle.tsx modified: - frontend/src/App.tsx (5 route + Layout wrapper) - frontend/src/api/client.ts (aggiunto apiGet, apiPost, apiPut, apiDownload, triggerDownload) key-decisions: - "Palette stone/amber invece di gradienti viola — design B2B industriale adatto a consulenti" - "EditableField come componente generico click-to-edit (non libreria esterna) per semplicità" - "useJobStatus: refetchInterval condizionale nel hook (non nel componente) — più pulito e testabile" - "SlideViewer mantiene copia locale del post (useState) e propaga modifiche via onEdit callback" - "OutputReview mantiene localResults separato da jobData per gestire edit inline + rigenerazioni" - "Download CSV: sempre POST /api/export/{jobId}/csv con edits (non GET) per includere modifiche inline" patterns-established: - "TanStack Query pattern: hook incapsula tutta la logica fetch, componente usa solo data/isPending/error" - "Stone/Amber palette: stone-800 card, stone-700 border, amber-500 accent, stone-400 text secondario" - "Disabled pattern: pulsanti disabilitati con disabled={!apiKeyOk} + banner con link a Impostazioni" # Metrics duration: 10min completed: 2026-03-08 --- # Phase 1 Plan 04: Web UI React Completa **Web UI React con Dashboard, GenerateCalendar (async polling), OutputReview (griglia+SlideViewer+edit inline+CSV), Settings (form API key/modello/nicchie), e 11 TanStack Query hooks che cablano tutti gli endpoint del backend** ## Performance - **Duration:** 10 min - **Started:** 2026-03-08T01:20:01Z - **Completed:** 2026-03-08T01:29:53Z - **Tasks:** 4 task auto + 1 checkpoint - **Files modified:** 16 ## Accomplishments - types.ts con 15+ interface/type che rispecchiano esattamente gli schemas Pydantic del backend - api/hooks.ts con 11 hooks TanStack Query: settings CRUD, generate bulk/single, job polling con refetchInterval condizionale, CSV export (GET e POST) - Layout sidebar stone/amber non generica, con NavLink active state e 4 link di navigazione - Dashboard con banner API key configurata/non configurata tramite useSettingsStatus() - Settings form completo: API key password con toggle visibilità, LLM model select, brand, tono, nicchie checkbox, frequenza - GenerateCalendar: form → async job_id → ProgressIndicator polling → navigate a OutputReview - ProgressIndicator: polling ogni 2s, barra progresso, lista post con icone stato individuale - OutputReview: griglia PostCard, stato locale per edit inline, download CSV via POST con edits - SlideViewer: 8 slide (Cover + 6 centrali + CTA), frecce laterali, keyboard nav, ogni campo editabile inline, caption Instagram - PostCard: 3 stati (success/failed/pending), badge PN + Schwartz, pulsante Riprova con useGenerateSingle ## Task Commits Ogni task committato atomicamente: 1. **Task 1: Layout, routing, API hooks, tipi TypeScript, Dashboard, Settings** - `738a877` (feat) 2. **Task 2a: Badge PN/Schwartz e PostCard con stati success/failed/pending** - `a2ebd72` (feat) 3. **Task 2b: SlideViewer con edit inline e ProgressIndicator con polling** - `9e5bddc` (feat) 4. **Task 2c: Pagine GenerateCalendar, OutputReview, GenerateSingle complete** - `a5d1c15` (feat) **Plan metadata:** (questo commit) (docs) ## Files Created/Modified - `frontend/src/types.ts` — 15+ interface TypeScript: CalendarSlot, GeneratedPost, PostResult, JobStatus, Settings, SettingsStatus, etc. - `frontend/src/api/client.ts` — aggiunto apiGet, apiPost, apiPut, apiDownload, triggerDownload - `frontend/src/api/hooks.ts` — 11 hooks TanStack Query per tutti gli endpoint - `frontend/src/components/Layout.tsx` — wrapper con sidebar a sinistra e area contenuto - `frontend/src/components/Sidebar.tsx` — nav con NavLink, logo, 4 link, palette stone/amber - `frontend/src/components/BadgePN.tsx` — 6 colori distinti per tipi PN - `frontend/src/components/BadgeSchwartz.tsx` — 5 livelli L1-L5 con tooltip - `frontend/src/components/PostCard.tsx` — 3 stati, badge, click expand, pulsante Riprova - `frontend/src/components/SlideViewer.tsx` — 8 slide, frecce, edit inline, caption Instagram - `frontend/src/components/ProgressIndicator.tsx` — polling job status, barra progresso, lista post - `frontend/src/pages/Dashboard.tsx` — banner API key, quick actions, step guide - `frontend/src/pages/Settings.tsx` — form completo con API key toggle, nicchie checkbox - `frontend/src/pages/GenerateCalendar.tsx` — form + async polling flow - `frontend/src/pages/OutputReview.tsx` — griglia + edit inline + CSV export - `frontend/src/pages/GenerateSingle.tsx` — form con anteprima PostCard - `frontend/src/App.tsx` — 5 route, Layout wrapper, QueryClientProvider ## Decisions Made - **Palette stone/amber**: scelta deliberatamente non generica. stone-950 per sidebar, amber-500 per accent — adatta a tool B2B, non sembra "AI slop". - **EditableField come componente generico**: implementato inline in SlideViewer senza dipendenze esterne. Click → input/textarea, blur/Escape per confermare. - **refetchInterval nel hook**: la logica di polling (2000ms se running, false altrimenti) è nel hook `useJobStatus`, non nel componente `ProgressIndicator`. Più testabile e riutilizzabile. - **Download sempre via POST**: `useDownloadEditedCsv` usa sempre POST /api/export/{jobId}/csv con i `results` correnti — garantisce che le modifiche inline siano sempre incluse nel CSV scaricato. - **localResults separato**: OutputReview mantiene uno stato locale `localResults` che parte da `jobData.results` ma viene aggiornato da edit inline e rigenerazioni — evita di mutare la cache TanStack Query. ## Deviations from Plan Nessuna deviazione significativa — piano eseguito come specificato. Unica nota implementativa: il task prevedeva di creare stub per GenerateCalendar/OutputReview/GenerateSingle in Task 1 e poi sostituirli in Task 2c. Questo è stato fatto correttamente, permettendo di verificare la build dopo ogni task. ## Issues Encountered Nessun problema durante l'implementazione. Tutti i task compilano senza errori TypeScript alla prima build. ## User Setup Required None — la UI è pronta per essere servita dal backend FastAPI tramite SPAStaticFiles. L'utente deve solo accedere a `/postgenerator/` e configurare la API key nelle Impostazioni. ## Checkpoint: Human Verification Il piano include un `checkpoint:human-verify` alla fine (task 5). Le verifiche richieste sono: 1. `cd frontend && npm run build` — **PASSATO** (build pulita, 316.07 kB JS, 27.69 kB CSS) 2. App.tsx ha 5 route con BrowserRouter basename="/postgenerator" — **VERIFICATO** 3. Struttura pagine e componenti coerente — **VERIFICATO** (4 task, 14 file creati/modificati) 4. API client usa /postgenerator/api come base — **VERIFICATO** (API_BASE='/postgenerator/api' in client.ts) 5. Opzionale: navigare su https://lab.mlhub.it/postgenerator/ — richiede deploy (non eseguito in questo piano) ## Next Phase Readiness - Frontend completo e buildabile — pronto per deploy via `vps-lab-deploy` - Phase 1 completata al 100%: backend (01-01/02/03) + frontend (01-04) - Per testare end-to-end: deploy su VPS + configurare API key in Impostazioni + generare calendario - Phase 2 (Image Pipeline) può riutilizzare tutti i componenti UI esistenti - Phase 3 (Advanced Features) può aggiungere nuove pagine/componenti alla struttura esistente --- *Phase: 01-core-generation-pipeline* *Completed: 2026-03-08*