chore: aggiorna SOP e CLAUDE.md per migrazione a Flutter

Riscritto sop.md con stack Flutter + Docker (container dev noVNC +
container build headless). Aggiornato CLAUDE.md con roadmap, architettura
target e mapping Vue→Flutter come riferimento per la riscrittura.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-16 16:43:26 +02:00
parent 6293743fa1
commit 3f79e30ecd
2 changed files with 170 additions and 143 deletions
+59 -49
View File
@@ -4,63 +4,73 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
BitePlan is a mobile-first Vue 3 PWA for meal planning, raw↔cooked weight conversion, and shopping list management. It targets Android via Capacitor and is designed for a 480px-max viewport. All UI strings and documentation are in **Italian**.
BitePlan è un'app Android per meal planning, conversione crudo/cotto e lista della spesa. Il progetto è in **riscrittura completa da Vue 3 + Capacitor a Flutter**. Segui `sop.md` come piano di lavoro: ogni sezione del SOP corrisponde a una fase da completare in ordine. L'obiettivo finale è un APK Android buildabile via Docker. Tutta la UI e la UX sono in **italiano**.
## Commands
## Stato attuale
Il codice Vue 3 esistente (`src/`, `tests/`, `vite.config.mjs`, ecc.) è il riferimento funzionale da portare in Flutter — non va esteso. Il nuovo codice Flutter va creato da zero seguendo `sop.md`.
## Roadmap (da sop.md)
1. Struttura progetto Flutter (`lib/`, `pubspec.yaml`, asset JSON)
2. Container dev: Docker + Xvfb + noVNC su porta 6080 (`docker/dev/`)
3. Container build headless APK (`docker/build/`)
4. `StorageService` — persistenza con `shared_preferences`
5. `ConversionService` — rawToCooked / cookedToRaw + asset `lib/data/conversions.json`
6. Modelli dati: `MealPlan`, `DayPlan`, `ShoppingItem`
7. Pagina Meal Planner (accordion per giorno, 3 pasti, add/remove voci)
8. Pagina Converter (ricerca alimento → selezione metodo → calcolo bidirezionale)
9. Pagina Shopping List (checklist, import da meal planner, svuota)
10. `BottomNavigationBar` (Pasti | Converti | Spesa), portrait lock, Material 3
## Comandi (quando il progetto Flutter esisterà)
```bash
npm run dev # Dev server at http://localhost:5173
npm run build # Production build → dist/
npm run preview # Preview built app
# Sviluppo via container noVNC
cd docker/dev && docker compose up
# → http://localhost:6080 (desktop GUI nel browser)
# Nel terminale noVNC: cd /workspace && flutter pub get && flutter run
npm test # Vitest unit + integration tests (watch mode)
npm run test:coverage # Coverage report (v8 provider)
npm run test:e2e # Playwright e2e (requires dev server running)
npm run test:e2e:ui # Playwright interactive UI mode
# Single test file
npx vitest run tests/unit/conversion.test.js
# Android APK
bash docker/build.sh # Debug APK
bash docker/build.sh --release # Signed release APK
# Build APK
bash docker/build/build.sh # debug
bash docker/build/build.sh --release # release firmato → dist/
```
E2E tests simulate iPhone 14 Pro viewport (393×852) with Italian locale.
## Architettura target (Flutter)
## Architecture
**App.vue** is the root router — it conditionally renders three pages based on a `currentPage` ref (`meal`, `convert`, `shop`) and hosts the portrait-lock transform, `InfoPanel`, and `DocsPanel`.
**Three pages** in `src/pages/`:
- `MealPlanner.vue` — 7-day plan (MonSun), 3 meal slots each (colazione/pranzo/cena), per-day accordion via `MealCard.vue`, QR share, and "generate shopping list" export
- `Converter.vue` — real-time food search → select food+method → bidirectional raw↔cooked calculation using yield coefficients from `src/data/conversions.json`
- `ShoppingList.vue` — checklist with add/remove/check, importable from meal planner
**State & persistence**: No Pinia/Vuex — pages use Vue composables + direct `localStorage` via the wrappers in `src/utils/storage.js` (`save(key, val)` / `load(key, default)`).
**Conversion logic** lives entirely in `src/utils/conversion.js`:
```js
rawToCooked(food, method, rawGrams, db) = rawGrams * db[food][method].yield
cookedToRaw(food, method, cookedGrams, db) = cookedGrams / db[food][method].yield
```
`yield = cooked_weight / raw_weight`. The database in `src/data/conversions.json` has 50+ foods × 14 cooking methods with coefficients sourced from CREA, SINU, USDA (see `docs/conversioni.md`).
lib/
├── main.dart
├── app.dart # MaterialApp, routing, BottomNavigationBar
├── pages/
│ ├── meal_planner_page.dart
│ ├── converter_page.dart
│ └── shopping_list_page.dart
├── widgets/
│ ├── meal_card.dart
│ └── checkbox_item.dart
├── models/
│ ├── meal_plan.dart
│ └── shopping_item.dart
├── services/
│ ├── storage_service.dart
│ └── conversion_service.dart
└── data/
└── conversions.json # 50+ alimenti × metodi cottura, yield = cotto/crudo
```
**CSS**: Vanilla CSS only, no framework. Design tokens are CSS variables in `:root` in `src/style.css` (`--color-primary: #2d6a4f`, `--nav-height: 64px`, etc.). Buttons must be min 44px; layout is single-column.
**Stato**: Provider o Riverpod (nessuno store esterno pesante).
**Persistenza**: `shared_preferences`, chiavi `meals` e `shopping_list` (JSON serializzato).
**Conversione**: `rawToCooked(raw, yield) = raw * yield` / `cookedToRaw(cooked, yield) = cooked / yield`.
**UI**: Material 3, seed color `Color(0xFF2d6a4f)`, touch target minimo 48×48 dp.
## Testing
## Riferimento funzionale (Vue → Flutter)
- **Unit** (`tests/unit/`): Pure function tests for `conversion.js` and `storage.js`
- **Integration** (`tests/integration/`): Vue Test Utils component mounts with localStorage seeding
- **E2E** (`tests/e2e/`): Playwright against the running dev server
`tests/setup.js` clears localStorage before/after each test. Vitest uses `happy-dom` environment.
## Android Build
The Docker pipeline in `docker/` handles the full Android build:
1. `npm run build``dist/`
2. `cap sync` → copies dist into Android project
3. Gradle builds the APK; release APK is signed with `docker/biteplan.jks` (gitignored)
See `docker/README.md` for full APK build instructions.
| Vue (attuale) | Flutter (target) |
|---|---|
| `src/pages/MealPlanner.vue` | `lib/pages/meal_planner_page.dart` |
| `src/pages/Converter.vue` | `lib/pages/converter_page.dart` |
| `src/pages/ShoppingList.vue` | `lib/pages/shopping_list_page.dart` |
| `src/utils/storage.js` | `lib/services/storage_service.dart` |
| `src/utils/conversion.js` | `lib/services/conversion_service.dart` |
| `src/data/conversions.json` | `lib/data/conversions.json` (asset) |