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
This commit is contained in:
@@ -66,7 +66,7 @@ Plans:
|
|||||||
**Plans**: 2 plans
|
**Plans**: 2 plans
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 03-01-PLAN.md — SwipeService CRUD backend + Pydantic schemas + FastAPI router + pagina SwipeFile UI con form aggiunta, modifica inline, eliminazione con conferma, filtro nicchia (Wave 1)
|
- [x] 03-01-PLAN.md — SwipeService CRUD backend + Pydantic schemas + FastAPI router + pagina SwipeFile UI con form aggiunta, modifica inline, eliminazione con conferma, filtro nicchia (Wave 1)
|
||||||
- [ ] 03-02-PLAN.md — Swipe-to-calendar integration: topic_overrides in CalendarRequest + picker Swipe File nel form Genera Calendario con mark-used (Wave 2)
|
- [ ] 03-02-PLAN.md — Swipe-to-calendar integration: topic_overrides in CalendarRequest + picker Swipe File nel form Genera Calendario con mark-used (Wave 2)
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -95,5 +95,5 @@ Phases execute in numeric order: 1 → 2 → 3 → 4
|
|||||||
|-------|----------------|--------|-----------|
|
|-------|----------------|--------|-----------|
|
||||||
| 1. Core Generation Pipeline | 4/4 | Complete | 2026-03-08 |
|
| 1. Core Generation Pipeline | 4/4 | Complete | 2026-03-08 |
|
||||||
| 2. Prompt Control + Output Review | 2/2 | Complete | 2026-03-08 |
|
| 2. Prompt Control + Output Review | 2/2 | Complete | 2026-03-08 |
|
||||||
| 3. Organization Layer | 0/2 | Not started | - |
|
| 3. Organization Layer | 1/2 | In progress | - |
|
||||||
| 4. Enrichment | 0/1 | Not started | - |
|
| 4. Enrichment | 0/1 | Not started | - |
|
||||||
|
|||||||
@@ -5,23 +5,23 @@
|
|||||||
See: .planning/PROJECT.md (updated 2026-03-07)
|
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.
|
**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 2 COMPLETA — Prompt Control + Output Review
|
**Current focus:** Phase 3 — Organization Layer (Plan 1/2 completato)
|
||||||
|
|
||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 2 of 4 (Prompt Control + Output Review)
|
Phase: 3 of 4 (Organization Layer)
|
||||||
Plan: 2 of 2 in current phase — PHASE COMPLETE
|
Plan: 1 of 2 in current phase — In progress
|
||||||
Status: Phase 2 complete — ready for Phase 3 or deploy
|
Status: In progress — Plan 03-01 completo, manca 03-02
|
||||||
Last activity: 2026-03-08 — Completed 02-02-PLAN.md (Per-item Regeneration + Summary Counter)
|
Last activity: 2026-03-09 — Completed 03-01-PLAN.md (SwipeService + pagina SwipeFile)
|
||||||
|
|
||||||
Progress: [██████░░░░] 66% (6/9 piani totali)
|
Progress: [███████░░░] 77% (7/9 piani totali)
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
**Velocity:**
|
**Velocity:**
|
||||||
- Total plans completed: 6
|
- Total plans completed: 7
|
||||||
- Average duration: ~7 min
|
- Average duration: ~6.5 min
|
||||||
- Total execution time: 42 min
|
- Total execution time: 47 min
|
||||||
|
|
||||||
**By Phase:**
|
**By Phase:**
|
||||||
|
|
||||||
@@ -29,10 +29,11 @@ Progress: [██████░░░░] 66% (6/9 piani totali)
|
|||||||
|-------|-------|-------|----------|
|
|-------|-------|-------|----------|
|
||||||
| 01-core-generation-pipeline | 4/4 COMPLETA | 33 min | 8 min |
|
| 01-core-generation-pipeline | 4/4 COMPLETA | 33 min | 8 min |
|
||||||
| 02-prompt-control-output-review | 2/2 COMPLETA | 9 min | 4.5 min |
|
| 02-prompt-control-output-review | 2/2 COMPLETA | 9 min | 4.5 min |
|
||||||
|
| 03-organization-layer | 1/2 In corso | 5 min | 5 min |
|
||||||
|
|
||||||
**Recent Trend:**
|
**Recent Trend:**
|
||||||
- Last 5 plans: 9 min, 8 min, 10 min, 5 min, 4 min
|
- Last 5 plans: 8 min, 10 min, 5 min, 4 min, 5 min
|
||||||
- Trend: velocita' in aumento
|
- Trend: stabile intorno a 5 min
|
||||||
|
|
||||||
*Updated after each plan completion*
|
*Updated after each plan completion*
|
||||||
|
|
||||||
@@ -62,21 +63,26 @@ Recent decisions affecting current work:
|
|||||||
- [02-01]: PromptService init lazy via _get_prompt_service() per sincronizzazione con lifespan directory
|
- [02-01]: PromptService init lazy via _get_prompt_service() per sincronizzazione con lifespan directory
|
||||||
- [02-02]: Regen notes passate via campo tono in GenerateRequest (pragmatico, no backend changes)
|
- [02-02]: Regen notes passate via campo tono in GenerateRequest (pragmatico, no backend changes)
|
||||||
- [02-02]: Edit detection manuale via JSON.stringify comparison (trascurabile con 13 post)
|
- [02-02]: Edit detection manuale via JSON.stringify comparison (trascurabile con 13 post)
|
||||||
|
- [03-01]: SwipeService lazy init identico a PromptService (DATA_PATH creato nel lifespan FastAPI)
|
||||||
|
- [03-01]: IDs brevi uuid4.hex[:12] — leggibili, no rischio collisione con volumi Swipe File
|
||||||
|
- [03-01]: PUT con comportamento PATCH-like per nicchia/note — None cancella il valore
|
||||||
|
- [03-01]: Filtro nicchia derivato dinamicamente da items (no config separata)
|
||||||
|
|
||||||
### Blockers/Concerns
|
### 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]: 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
|
- [Phase 1]: Baseline qualita' prompt italiani da validare dopo prima generazione reale
|
||||||
- [Deploy]: Phase 2 completa — serve vps-lab-deploy per testare end-to-end il sistema
|
- [Deploy]: Phase 2+3 plan1 complete — serve vps-lab-deploy per testare end-to-end il sistema
|
||||||
|
- [03-02]: La route `/swipe-file` e il hook `useSwipeItems` sono pronti per l'integrazione nel form Genera Calendario
|
||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-03-08
|
Last session: 2026-03-09
|
||||||
Stopped at: Completed 02-02-PLAN.md (Per-item Regeneration + Summary Counter) — Phase 2 COMPLETE
|
Stopped at: Completed 03-01-PLAN.md (SwipeService + SwipeFile UI) — Plan 1/2 Phase 3
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|
||||||
## Next Actions
|
## Next Actions
|
||||||
|
|
||||||
1. `vps-lab-deploy` per deployare su VPS e testare end-to-end
|
1. Eseguire 03-02-PLAN.md (Swipe-to-calendar integration: topic_overrides + picker Swipe File)
|
||||||
2. Pianificare Phase 3 (Canva-ready CSV polish + advanced export)
|
2. `vps-lab-deploy` per deployare su VPS e testare end-to-end il sistema
|
||||||
3. Eseguire Phase 3
|
3. Pianificare Phase 4 (Enrichment: Unsplash integration)
|
||||||
|
|||||||
130
.planning/phases/03-organization-layer/03-01-SUMMARY.md
Normal file
130
.planning/phases/03-organization-layer/03-01-SUMMARY.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user