From 23599e17366520718672131c16c06e1f3446dd79 Mon Sep 17 00:00:00 2001 From: Michele Date: Sun, 8 Mar 2026 02:31:42 +0100 Subject: [PATCH] =?UTF-8?q?docs(01-04):=20complete=20web=20UI=20plan=20?= =?UTF-8?q?=E2=80=94=204=20task,=2016=20file,=20build=20pulita?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tasks completed: 4/4 - Task 1: Layout, routing, API hooks, tipi TypeScript, Dashboard, Settings - Task 2a: Badge PN/Schwartz e PostCard con stati success/failed/pending - Task 2b: SlideViewer con edit inline e ProgressIndicator con polling - Task 2c: Pagine GenerateCalendar, OutputReview, GenerateSingle complete SUMMARY: .planning/phases/01-core-generation-pipeline/01-04-SUMMARY.md --- .planning/STATE.md | 40 ++-- .../01-04-SUMMARY.md | 171 ++++++++++++++++++ 2 files changed, 198 insertions(+), 13 deletions(-) create mode 100644 .planning/phases/01-core-generation-pipeline/01-04-SUMMARY.md diff --git a/.planning/STATE.md b/.planning/STATE.md index 4460bf6..4f0fa18 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -5,33 +5,33 @@ See: .planning/PROJECT.md (updated 2026-03-07) **Core value:** Generare un calendario di 13 caroselli Instagram strategicamente orchestrati, pronti per Canva Bulk Create, con un click dalla Web UI. -**Current focus:** Phase 1 — Core Generation Pipeline +**Current focus:** Phase 1 completata — pronta per deploy e Phase 2 ## Current Position Phase: 1 of 4 (Core Generation Pipeline) -Plan: 3 of 4 in current phase -Status: In progress — Plan 03 completato -Last activity: 2026-03-08 — Completato 01-03-PLAN.md (pipeline LLM + API routers) +Plan: 4 of 4 in current phase +Status: Phase 1 COMPLETATA — tutti e 4 i piani eseguiti +Last activity: 2026-03-08 — Completato 01-04-PLAN.md (Web UI React completa) -Progress: [███░░░░░░░] 18% (3/16 piani totali stimati) +Progress: [████░░░░░░] 25% (4/16 piani totali stimati) ## Performance Metrics **Velocity:** -- Total plans completed: 3 -- Average duration: ~7 min -- Total execution time: 23 min +- Total plans completed: 4 +- Average duration: ~8 min +- Total execution time: 33 min **By Phase:** | Phase | Plans | Total | Avg/Plan | |-------|-------|-------|----------| -| 01-core-generation-pipeline | 3/4 | 23 min | 7 min | +| 01-core-generation-pipeline | 4/4 COMPLETA | 33 min | 8 min | **Recent Trend:** -- Last 3 plans: 6 min, 9 min, 8 min -- Trend: baseline stabile ~7-8 min/piano +- Last 4 plans: 6 min, 9 min, 8 min, 10 min +- Trend: baseline stabile ~8 min/piano *Updated after each plan completion* @@ -54,14 +54,28 @@ Recent decisions affecting current work: - [01-03]: asyncio.to_thread wrappa LLM sync calls nel background task async - [01-03]: Settings.api_key merge: PUT non sovrascrive con None se non inclusa nel body - [01-03]: Pipeline singleton in generate.py per mantenere _jobs tra request, con fallback da disco +- [01-04]: Palette stone/amber per design B2B non generico (non gradienti viola) +- [01-04]: EditableField come componente generico click-to-edit (no dipendenze esterne) +- [01-04]: refetchInterval condizionale nel hook useJobStatus (non nel componente) +- [01-04]: Download CSV sempre via POST con edits inline (non GET originale) +- [01-04]: localResults separato in OutputReview per edit inline senza mutare cache TanStack Query ### Blockers/Concerns - [Phase 1]: Validare token usage reale per batch 13 post con claude-sonnet-4-5 — inter_request_delay=2.0s configurato, da validare in produzione - [Phase 1]: Baseline qualita' prompt italiani da validare dopo prima generazione reale +- [Deploy]: Phase 1 completa — serve vps-lab-deploy per testare end-to-end il sistema ## Session Continuity -Last session: 2026-03-08T01:15:06Z -Stopped at: Completato 01-03-PLAN.md — Pipeline LLM + CSVBuilder + 4 router API +Last session: 2026-03-08T01:29:53Z +Stopped at: Completato 01-04-PLAN.md — Web UI React completa con tutte le pagine e componenti Resume file: None + +## Next Actions + +Phase 1 completata. Prossimi passi suggeriti: +1. `vps-lab-deploy` per deployare su VPS e testare end-to-end +2. Configurare API key in Impostazioni UI +3. Generare primo calendario reale per validare qualita' prompt e token usage +4. Poi procedere con Phase 2 (Image Pipeline - URL Unsplash) o Phase 3 (Advanced Features) diff --git a/.planning/phases/01-core-generation-pipeline/01-04-SUMMARY.md b/.planning/phases/01-core-generation-pipeline/01-04-SUMMARY.md new file mode 100644 index 0000000..6b14029 --- /dev/null +++ b/.planning/phases/01-core-generation-pipeline/01-04-SUMMARY.md @@ -0,0 +1,171 @@ +--- +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*