chore: initial project setup with documentation and design assets
Add project foundation: CLAUDE.md, requirements tracking system, technical architecture docs, Firestore setup guide, device testing guide, and Stitch design mockups for Precision Vitality app. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
312
docs/REQUIREMENTS.md
Normal file
312
docs/REQUIREMENTS.md
Normal file
@@ -0,0 +1,312 @@
|
||||
# Requisiti — CalorieTracker (Precision Vitality)
|
||||
|
||||
> Documento di riferimento per tutti i requisiti funzionali e sistemistici del progetto.
|
||||
> Ultimo aggiornamento: 16/04/2026
|
||||
|
||||
---
|
||||
|
||||
## Indice Requisiti
|
||||
|
||||
| ID | Tipo | Priorità | Titolo | Dipendenze |
|
||||
|----|------|----------|--------|------------|
|
||||
| REQ-001 | SISTEMISTICO | CRITICA | Scaffolding Ionic + Capacitor | — |
|
||||
| REQ-002 | SISTEMISTICO | CRITICA | Setup Firebase Firestore | REQ-001 |
|
||||
| REQ-003 | EVOLUTIVO | ALTA | Home screen + FAB | REQ-002 |
|
||||
| REQ-004 | EVOLUTIVO | ALTA | Modal input numerico | REQ-003 |
|
||||
| REQ-005 | EVOLUTIVO | ALTA | Modal input LLM | REQ-003, REQ-006 |
|
||||
| REQ-006 | EVOLUTIVO | ALTA | Servizio Claude API | REQ-001 |
|
||||
| REQ-007 | EVOLUTIVO | ALTA | CRUD pasti Firestore | REQ-002 |
|
||||
| REQ-008 | EVOLUTIVO | MEDIA | Statistiche giornaliere | REQ-007 |
|
||||
| REQ-009 | EVOLUTIVO | MEDIA | Statistiche settimanali | REQ-007 |
|
||||
| REQ-010 | EVOLUTIVO | MEDIA | Ricerca pasti | REQ-007 |
|
||||
| REQ-011 | REWORK | MEDIA | Design brief Google Stitch | — |
|
||||
|
||||
---
|
||||
|
||||
## REQ-001 — Scaffolding Ionic + Capacitor
|
||||
|
||||
**Tipo**: SISTEMISTICO | **Priorità**: CRITICA
|
||||
|
||||
**Obiettivo**: Scaffolding del progetto Ionic 7+ con Capacitor 5+. Configurazione build nativa Android/iOS. Setup ambiente con struttura cartelle, linting e variabili d'ambiente.
|
||||
|
||||
**Stato Target**:
|
||||
- Progetto Ionic Angular inizializzato con routing e tab layout (Journal, Stats, Plans, Profile)
|
||||
- Capacitor configurato per Android e iOS
|
||||
- Variabili ambiente: `ANTHROPIC_API_KEY`, `FIREBASE_*`
|
||||
- Struttura moduli: `core/`, `shared/`, `features/home`, `features/stats`, `features/search`
|
||||
- Proxy sviluppo configurato per CORS Anthropic API
|
||||
|
||||
**Passi Implementativi**:
|
||||
1. `ionic start calorie-tracker tabs --type=angular --capacitor`
|
||||
2. Aggiungere `@capacitor/android` e `@capacitor/ios`
|
||||
3. Configurare `capacitor.config.ts` con appId e server URL
|
||||
4. Creare struttura moduli `features/` con lazy loading
|
||||
5. Aggiungere `@ionic/storage-angular` per cache locale
|
||||
6. Configurare `environment.ts` e `environment.prod.ts`
|
||||
7. Verificare build `ionic build` + `npx cap sync`
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] `ionic serve` avvia l'app senza errori
|
||||
- [ ] `ionic build` produce `www/` senza errori
|
||||
- [ ] `npx cap sync` completa senza errori
|
||||
- [ ] Struttura a 4 tab visibile nel browser (Journal, Stats, Plans, Profile)
|
||||
- [ ] Variabili d'ambiente lette correttamente in `environment.ts`
|
||||
|
||||
---
|
||||
|
||||
## REQ-002 — Setup Firebase Firestore
|
||||
|
||||
**Tipo**: SISTEMISTICO | **Priorità**: CRITICA | **Dipende da**: REQ-001
|
||||
|
||||
**Obiettivo**: Setup Firebase con Firestore come database. Schema dati, regole sicurezza e SDK Angular.
|
||||
|
||||
**Schema Firestore**:
|
||||
```
|
||||
users/{userId}/
|
||||
meals/{mealId}/
|
||||
- id: string
|
||||
- timestamp: Timestamp
|
||||
- calories: number
|
||||
- inputType: 'manual' | 'llm'
|
||||
- description?: string
|
||||
- llmConfidence?: 'high' | 'medium' | 'low'
|
||||
- llmExplanation?: string
|
||||
- createdAt: Timestamp
|
||||
```
|
||||
|
||||
**Regole Sicurezza**:
|
||||
- Lettura/scrittura solo all'utente autenticato proprietario
|
||||
- Nessun accesso cross-user
|
||||
|
||||
**Auth**: Anonymous auth abilitato (upgrade Google Sign-In futuro)
|
||||
|
||||
**Passi Implementativi**:
|
||||
1. Creare Firebase project su console
|
||||
2. Abilitare Firestore in modalità produzione
|
||||
3. Abilitare Anonymous Authentication
|
||||
4. Scaricare `google-services.json` e `GoogleService-Info.plist`
|
||||
5. Installare `@angular/fire` e configurare in `app.module.ts`
|
||||
6. Definire regole Firestore in `firestore.rules`
|
||||
7. Creare `FirestoreService` con CRUD per collection `meals`
|
||||
8. Testare lettura/scrittura da `ionic serve`
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Scrittura documento su Firestore funzionante
|
||||
- [ ] Lettura documenti da Firestore funzionante
|
||||
- [ ] Regole sicurezza bloccano accesso non autenticato
|
||||
- [ ] `FirestoreService` espone: `addMeal()`, `getMealsByDate()`, `getMealsRange()`
|
||||
- [ ] Offline persistence abilitata e testata
|
||||
|
||||
---
|
||||
|
||||
## REQ-003 — Home Screen + FAB
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: ALTA | **Dipende da**: REQ-002
|
||||
|
||||
**Obiettivo**: Home screen (tab Journal) con totale kcal giornaliero, lista pasti e FAB per aggiunta.
|
||||
|
||||
**Specifiche UI** (da design Precision Vitality):
|
||||
- Header: data odierna centrata (es. "MERCOLEDÌ 16 APRILE")
|
||||
- Titolo: "Il tuo progresso giornaliero"
|
||||
- Numero kcal grande (56px, Lexend Bold, verde `#006b1b`)
|
||||
- Label "calorie oggi"
|
||||
- Barra progresso: kcal / obiettivo (default 2000)
|
||||
- Sezione "Diario Alimentare": lista card pasti (ora, descrizione, kcal)
|
||||
- Badge "AI" (arancione) o "M" (grigio) su ogni pasto
|
||||
- FAB arancione `#FF7043` in basso a destra con icona "+"
|
||||
- Empty state: "Nessun pasto registrato oggi. Inizia!"
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Totale kcal odierno visibile e aggiornato real-time
|
||||
- [ ] Lista pasti del giorno visibile e scrollabile
|
||||
- [ ] FAB visibile e cliccabile su tutti i device
|
||||
- [ ] Empty state quando nessun pasto registrato
|
||||
- [ ] Aggiornamento immediato dopo salvataggio nuovo pasto
|
||||
|
||||
---
|
||||
|
||||
## REQ-004 — Modal Input Numerico
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: ALTA | **Dipende da**: REQ-003
|
||||
|
||||
**Obiettivo**: Modal per inserimento diretto kcal con tastiera numerica.
|
||||
|
||||
**Specifiche UI** (da design):
|
||||
- Titolo: "Inserisci calorie"
|
||||
- Icona fulmine verde
|
||||
- Motivazionale: "Ogni dato conta per il tuo obiettivo."
|
||||
- Campo numerico grande (font 40px), placeholder "0", label "KCAL"
|
||||
- Campo "Descrizione (opzionale)"
|
||||
- Bottone "Salva" verde a tutta larghezza
|
||||
- Suggerimenti veloci: 150 (Spuntino), 450 (Pranzo), 600 (Cena)
|
||||
|
||||
**Validazione**: valore > 0 e ≤ 9999
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Modal si apre dal FAB
|
||||
- [ ] Tastiera numerica nativa su mobile
|
||||
- [ ] Validazione blocca valori ≤ 0 e > 9999
|
||||
- [ ] Salvataggio corretto su Firestore
|
||||
- [ ] Toast conferma dopo salvataggio
|
||||
- [ ] Modal si chiude e Home aggiorna totale
|
||||
|
||||
---
|
||||
|
||||
## REQ-005 — Modal Input LLM (Descrizione Pasto)
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: ALTA | **Dipende da**: REQ-003, REQ-006
|
||||
|
||||
**Obiettivo**: Modal per descrizione testuale del pasto con stima AI.
|
||||
|
||||
**Specifiche UI** (da design):
|
||||
- Titolo: "Descrivi il pasto"
|
||||
- Sottotitolo: "Usa il linguaggio naturale per stimare i tuoi nutrienti in pochi secondi."
|
||||
- Textarea "IL TUO PASTO" con placeholder
|
||||
- Bottone "Stima calorie" arancione
|
||||
- Risultato: badge "ALTA PRECISIONE" / "MEDIA" / "BASSA"
|
||||
- Kcal stimate in grande + breakdown (carbi, proteine, grassi)
|
||||
- Campo kcal modificabile
|
||||
- Bottone "Salva" verde
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Textarea accetta input testuale
|
||||
- [ ] Bottone "Stima calorie" chiama API (REQ-006)
|
||||
- [ ] Loading spinner durante chiamata
|
||||
- [ ] Risultato kcal e badge confidence corretti
|
||||
- [ ] Campo kcal modificabile dopo stima
|
||||
- [ ] Salvataggio su Firestore con `inputType: 'llm'`
|
||||
- [ ] Gestione errore timeout (messaggio + retry)
|
||||
|
||||
---
|
||||
|
||||
## REQ-006 — Servizio Claude API
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: ALTA | **Dipende da**: REQ-001
|
||||
|
||||
**Obiettivo**: Servizio Angular per stima calorica via Claude API con proxy sicuro.
|
||||
|
||||
**Architettura**: Firebase Cloud Function come proxy (API key mai nel bundle)
|
||||
|
||||
**Specifiche**:
|
||||
- Model: `claude-haiku-4-5-20251001`
|
||||
- Max tokens: 256
|
||||
- Food dictionary incluso nel system prompt
|
||||
- Parser JSON robusto (strip markdown code blocks)
|
||||
- Timeout: 10 secondi
|
||||
- Risposta: `{ calories, confidence, explanation }`
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Stima kcal corretta per descrizioni test
|
||||
- [ ] Food dictionary nel system prompt
|
||||
- [ ] API key non nel bundle app
|
||||
- [ ] Parser gestisce JSON wrapped in markdown
|
||||
- [ ] Timeout 10s con errore esplicito
|
||||
|
||||
---
|
||||
|
||||
## REQ-007 — CRUD Pasti Firestore
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: ALTA | **Dipende da**: REQ-002
|
||||
|
||||
**Obiettivo**: Servizio Angular per CRUD pasti su Firestore.
|
||||
|
||||
**Metodi**:
|
||||
- `addMeal(data)` — scrittura con timestamp e userId
|
||||
- `getMealsForDate(date)` — query filtrata per giorno (Observable)
|
||||
- `getMealsInRange(from, to)` — query per range date
|
||||
- `deleteMeal(mealId)` — hard delete
|
||||
- `getTotalCaloriesForDate(date)` — aggregazione client-side
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] `addMeal()` scrive documento corretto
|
||||
- [ ] `getMealsForDate()` restituisce solo pasti del giorno richiesto
|
||||
- [ ] `getMealsInRange()` restituisce pasti nel range
|
||||
- [ ] `deleteMeal()` rimuove documento
|
||||
- [ ] Observable aggiorna componenti senza reload
|
||||
- [ ] Funziona offline
|
||||
|
||||
---
|
||||
|
||||
## REQ-008 — Statistiche Giornaliere
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: MEDIA | **Dipende da**: REQ-007
|
||||
|
||||
**Obiettivo**: Vista giornaliera nel tab Stats con totale kcal, breakdown pasti e progresso obiettivo.
|
||||
|
||||
**Specifiche UI**:
|
||||
- Tab selector: "Oggi" | "Settimana"
|
||||
- Navigazione tra giorni (frecce)
|
||||
- Totale kcal, barra progresso (verde/rosso)
|
||||
- Lista pasti con swipe-to-delete
|
||||
- Obiettivo calorico: salvato in @ionic/storage (default 2000)
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Totale kcal giornaliero corretto
|
||||
- [ ] Navigazione tra giorni funzionante
|
||||
- [ ] Barra progresso aggiornata real-time
|
||||
- [ ] Colore cambia se obiettivo superato
|
||||
- [ ] Swipe-to-delete funzionante
|
||||
|
||||
---
|
||||
|
||||
## REQ-009 — Statistiche Settimanali
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: MEDIA | **Dipende da**: REQ-007
|
||||
|
||||
**Obiettivo**: Grafico a barre 7 giorni con media settimanale.
|
||||
|
||||
**Specifiche UI** (da design):
|
||||
- Periodo corrente (es. "14-20 apr") con frecce navigazione
|
||||
- Grafico barre: barre verdi ≤ obiettivo, rosse > obiettivo
|
||||
- Asse X: LUN, MAR, MER... (giorno corrente evidenziato)
|
||||
- Legenda: "In target" (verde), "Eccesso" (rosso)
|
||||
- Card "RIEPILOGO PRESTAZIONI": media kcal/giorno
|
||||
- Indicatori: variazione % vs settimana precedente, giorni in target
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Grafico a barre con dati reali
|
||||
- [ ] Colori corretti sopra/sotto obiettivo
|
||||
- [ ] Media settimanale calcolata
|
||||
- [ ] Navigazione settimane funzionante
|
||||
- [ ] Tap su barra apre dettaglio giornaliero
|
||||
- [ ] Grafico responsive
|
||||
|
||||
---
|
||||
|
||||
## REQ-010 — Ricerca Pasti
|
||||
|
||||
**Tipo**: EVOLUTIVO | **Priorità**: MEDIA | **Dipende da**: REQ-007
|
||||
|
||||
**Obiettivo**: Tab ricerca per trovare pasti passati per testo o intervallo date.
|
||||
|
||||
**Specifiche**:
|
||||
- Searchbar con debounce 300ms
|
||||
- Filtro date opzionale (da/a)
|
||||
- Risultati: data, ora, kcal, descrizione, badge tipo
|
||||
- Funzione "Ri-registra": crea nuovo pasto con stesse kcal e timestamp corrente
|
||||
- Ordinamento: data DESC
|
||||
- Range: ultimi 30 giorni (client-side)
|
||||
|
||||
**Criteri Accettazione**:
|
||||
- [ ] Ricerca per testo funzionante con debounce
|
||||
- [ ] Filtro date funzionante
|
||||
- [ ] Badge tipo visibili
|
||||
- [ ] "Ri-registra" crea nuovo documento
|
||||
- [ ] Empty state "Nessun risultato"
|
||||
|
||||
---
|
||||
|
||||
## REQ-011 — Design Brief Google Stitch
|
||||
|
||||
**Tipo**: REWORK | **Priorità**: MEDIA
|
||||
|
||||
**Stato**: COMPLETATO — I mockup sono disponibili in `stitch_calorietracker_design_brief_brief/`
|
||||
|
||||
**Schermate generate**:
|
||||
1. Home (Journal) — `home_calorietracker/`
|
||||
2. Bottom sheet scelta input — `scelta_input_calorietracker/`
|
||||
3. Modal input numerico — `inserisci_calorie_calorietracker/`
|
||||
4. Modal descrizione LLM — `descrizione_ai_calorietracker/`
|
||||
5. Statistiche settimanali — `statistiche_calorietracker/`
|
||||
|
||||
**Design System**: `vitality_pulse/DESIGN.md`
|
||||
Reference in New Issue
Block a user