Files
Michele d64c7f4524 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
2026-03-09 00:22:12 +01:00

53 lines
1.9 KiB
Python

"""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