Files
Michele babdf8a250 docs(03-01): complete SwipeService CRUD + SwipeFile UI plan
Tasks completed: 2/2
- Task 1: Backend — SwipeService + Pydantic schemas + FastAPI router
- Task 2: Frontend — TypeScript types + TanStack hooks + pagina SwipeFile + navigazione

SUMMARY: .planning/phases/03-organization-layer/03-01-SUMMARY.md
2026-03-09 00:27:24 +01:00

131 lines
6.3 KiB
Markdown

---
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 `<Route path="/swipe-file">` |
## 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