--- phase: 03 plan: 01 subsystem: organization-layer tags: [swipe-file, fastapi, pydantic, tanstack-query, react, json-persistence, crud] requires: - 01-01 (FastAPI skeleton + React SPA + Docker) - 01-04 (Web UI con palette stone/amber) - 02-01 (pattern lazy init PromptService) provides: - SwipeService CRUD su data/swipe_file.json - 5 endpoint REST /api/swipe (list, add, update, delete, mark-used) - Pagina SwipeFile UI con form, filtro nicchia, modifica inline, eliminazione con conferma - TanStack Query hooks per CRUD swipe affects: - 03-02 (Swipe-to-calendar integration: useSwipeItems per picker nel form Genera Calendario) - 04-01 (Enrichment: mark-used per tracking utilizzo topic) tech-stack: added: [] patterns: - lazy-init singleton (stessa tecnica di PromptService) - json-file persistence (lista di dict, no ORM) - controlled inline editing (editingId + editForm state) - filter chips pattern (filterNicchia state + uniqueNicchie derived) key-files: created: - backend/schemas/swipe.py - backend/services/swipe_service.py - backend/routers/swipe.py - frontend/src/pages/SwipeFile.tsx modified: - backend/main.py - frontend/src/types.ts - frontend/src/api/hooks.ts - frontend/src/components/Sidebar.tsx - frontend/src/App.tsx key-decisions: - "SwipeService lazy init identico a PromptService (DATA_PATH creato nel lifespan FastAPI)" - "IDs brevi uuid4.hex[:12] per comodita' nei log e nei test" - "update_item non sovrascrive nicchia/note con None se il campo non e' nel payload — comportamento PATCH-like via PUT" - "apiFetch importato esplicitamente in hooks.ts per il DELETE (non coperto da apiGet/apiPost/apiPut)" - "Filtro nicchia derivato da items esistenti (no configurazione separata)" metrics: duration: "5 min" completed: "2026-03-09" --- # Phase 3 Plan 01: SwipeService CRUD + pagina SwipeFile UI completa **One-liner:** SwipeService CRUD su JSON + 5 endpoint REST FastAPI + pagina SwipeFile con form, filtro nicchia, modifica inline e dialog conferma eliminazione. ## Performance - **Duration:** ~5 min - **Tasks:** 2/2 completati - **Deviations:** 1 (regola 3 — bug fix import) ## Accomplishments 1. **SwipeService** — CRUD completo su `data/swipe_file.json` con ordinamento cronologico inverso, ID brevi, timestamp ISO UTC, mark_used 2. **Backend FastAPI** — 5 endpoint REST (`GET /`, `POST /`, `PUT /{id}`, `DELETE /{id}`, `POST /{id}/mark-used`), lazy init, error handling con ValueError → 404 3. **Frontend types** — 4 interfacce TypeScript (`SwipeItem`, `SwipeItemCreate`, `SwipeItemUpdate`, `SwipeListResponse`) allineate agli schemi Pydantic 4. **TanStack Query hooks** — 4 hook (`useSwipeItems`, `useAddSwipeItem`, `useUpdateSwipeItem`, `useDeleteSwipeItem`) con invalidazione cache 5. **Pagina SwipeFile** — Form aggiunta rapida inline, lista con `SwipeCard`, filtro per nicchia via chip, modifica inline con `editingId` state, dialog conferma eliminazione, badge "Usato", data relativa senza librerie 6. **Navigazione** — Voce "Swipe File" con `Lightbulb` icon aggiunta alla Sidebar tra Prompt Editor e Impostazioni 7. **Route** — `/swipe-file` registrata in App.tsx ## Task Commits | Task | Name | Commit | Files | |------|------|--------|-------| | 1 | Backend SwipeService + schemas + router | d64c7f4 | backend/schemas/swipe.py, backend/services/swipe_service.py, backend/routers/swipe.py, backend/main.py | | 2 | Frontend SwipeFile UI + hooks + navigazione | d379789 | frontend/src/pages/SwipeFile.tsx, frontend/src/types.ts, frontend/src/api/hooks.ts, frontend/src/components/Sidebar.tsx, frontend/src/App.tsx | ## Files Created | File | Scopo | |------|-------| | `backend/schemas/swipe.py` | Pydantic models: SwipeItem, SwipeItemCreate, SwipeItemUpdate, SwipeListResponse | | `backend/services/swipe_service.py` | SwipeService: _load/_save/list_items/add_item/update_item/delete_item/mark_used | | `backend/routers/swipe.py` | FastAPI router: 5 endpoint REST, lazy init, ValueError -> 404 | | `frontend/src/pages/SwipeFile.tsx` | Pagina completa con form, lista, filtro, edit inline, delete confirm | ## Files Modified | File | Modifica | |------|----------| | `backend/main.py` | Aggiunto import swipe router e `app.include_router(swipe.router)` | | `frontend/src/types.ts` | Aggiunta sezione Swipe File con 4 interfacce TypeScript | | `frontend/src/api/hooks.ts` | Aggiunta sezione Swipe File con 4 hook TanStack Query + import `apiFetch` | | `frontend/src/components/Sidebar.tsx` | Aggiunto import `Lightbulb` e voce nav "Swipe File" | | `frontend/src/App.tsx` | Aggiunto import `SwipeFile` e `` | ## Decisions Made | Decisione | Motivo | Data | |-----------|--------|------| | Lazy init SwipeService identico a PromptService | DATA_PATH creato nel lifespan FastAPI, non al momento dell'import | 2026-03-09 | | IDs brevi `uuid4.hex[:12]` | Leggibili nei log, non c'e' rischio collisione con volumi Swipe File | 2026-03-09 | | PUT con comportamento PATCH-like per nicchia/note | Permette di cancellare il valore passando None esplicito, senza sovrascrivere campi omessi | 2026-03-09 | | Filtro nicchia derivato dinamicamente da items | No configurazione separata, sempre allineato ai dati reali | 2026-03-09 | | Nessuna libreria per data relativa | Logica semplice basata su differenza ms, riduce bundle size | 2026-03-09 | ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 3 - Blocking] Import mancante di `apiFetch` in hooks.ts** - **Found during:** Verifica build frontend (Task 2) - **Issue:** `useDeleteSwipeItem` usava `apiFetch` che non era importato dal modulo `./client` - **Fix:** Aggiunto `apiFetch` all'import esistente in `hooks.ts` (riga 13) - **Files modified:** `frontend/src/api/hooks.ts` - **Commit:** d379789 (incluso nel commit del task, non separato) ## Issues Encountered Nessun problema bloccante. La build frontend al primo tentativo ha rilevato il missing import `apiFetch`, risolto immediatamente (deviation Rule 3). ## Next Phase Readiness **Phase 3 Plan 02 (Swipe-to-calendar integration):** - `useSwipeItems()` hook disponibile per il picker nel form Genera Calendario - `mark_used` endpoint pronto per segnare topic usati - Interfacce TypeScript `SwipeItem` disponibili in `types.ts` **Dipendenze soddisfatte:** - SwipeService stabile e testato con import check Python - Build frontend pulita (TypeScript + Vite) - 5 endpoint REST registrati e accessibili