feat(03-01): SwipeService CRUD + Pydantic schemas + FastAPI router
- backend/schemas/swipe.py: SwipeItem, SwipeItemCreate, SwipeItemUpdate, SwipeListResponse - backend/services/swipe_service.py: SwipeService con load/save/add/update/delete/mark_used su swipe_file.json - backend/routers/swipe.py: 5 endpoint REST (GET/POST/PUT/DELETE/mark-used), lazy init pattern - backend/main.py: registra swipe.router prima del SPA catch-all mount
This commit is contained in:
52
backend/schemas/swipe.py
Normal file
52
backend/schemas/swipe.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""Pydantic schemas per il modulo Swipe File.
|
||||
|
||||
SwipeItem — Idea/topic salvata dall'utente
|
||||
SwipeItemCreate — Payload creazione (topic obbligatorio, nicchia/note opzionali)
|
||||
SwipeItemUpdate — Payload aggiornamento (tutti i campi opzionali per PATCH-like PUT)
|
||||
SwipeListResponse — Risposta lista con contatore totale
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class SwipeItem(BaseModel):
|
||||
"""Rappresenta una singola idea/topic salvata nello Swipe File."""
|
||||
|
||||
id: str # UUID breve generato dal backend (uuid4.hex[:12])
|
||||
topic: str # Testo principale obbligatorio (min 3 chars)
|
||||
nicchia: Optional[str] = None # Segmento/nicchia (es. "dentisti", "ecommerce")
|
||||
note: Optional[str] = None # Note libere opzionali
|
||||
created_at: str # ISO datetime UTC
|
||||
updated_at: str # ISO datetime UTC (aggiornato a ogni modifica)
|
||||
used: bool = False # True quando il topic e' stato usato in un calendario
|
||||
|
||||
|
||||
class SwipeItemCreate(BaseModel):
|
||||
"""Payload per la creazione di una nuova voce dello Swipe File."""
|
||||
|
||||
topic: str = Field(..., min_length=3, max_length=200, description="Idea o topic da salvare")
|
||||
nicchia: Optional[str] = Field(None, max_length=100)
|
||||
note: Optional[str] = Field(None, max_length=1000)
|
||||
|
||||
|
||||
class SwipeItemUpdate(BaseModel):
|
||||
"""Payload per l'aggiornamento di una voce esistente.
|
||||
|
||||
Tutti i campi sono opzionali: viene aggiornato solo cio' che e' fornito.
|
||||
Per cancellare nicchia o note, passare esplicitamente None.
|
||||
"""
|
||||
|
||||
topic: Optional[str] = Field(None, min_length=3, max_length=200)
|
||||
nicchia: Optional[str] = Field(None, max_length=100)
|
||||
note: Optional[str] = Field(None, max_length=1000)
|
||||
|
||||
|
||||
class SwipeListResponse(BaseModel):
|
||||
"""Risposta per GET /api/swipe — lista di tutte le idee con contatore."""
|
||||
|
||||
items: list[SwipeItem]
|
||||
total: int
|
||||
Reference in New Issue
Block a user