Files
recipe-app/teknisk_beskrivning_flutter.md
T
Nils-Johan Gynther b31af6181c Refactor next_steps_flutter and teknisk_beskrivning_flutter for user-scope implementation
- Updated next_steps_flutter.md to reflect completed tasks for user-scoped PantryItem and MealPlanEntry, including API contract publication and migration application.
- Enhanced the prioritization plan with clear completion dates and added localization tasks.
- Expanded teknisk_beskrivning_flutter.md with details on inventory filtering, sorting, and user-scoped backend changes, including migration notes and localization setup.
- Improved error handling documentation and localization usage guidelines.
2026-04-22 19:37:12 +02:00

10 KiB

Teknisk Beskrivning - Flutter Frontend

Detta dokument beskriver vad som ar byggt, arkitekturval och teknisk kontext for Flutter-frontenden. Malgrupp: utvecklare och AI-assistent i denna chat.

Relaterade dokument:

Syfte

  • Isolerad Flutter-baserad frontend i separat Docker-service.
  • Web forst, men med arkitektur som kan ateranvandas for Android/iOS.
  • Stegvis migrering av funktioner fran befintlig Next.js-frontend.

Vad som ar gjort

  • Ny compose override: compose.flutter.yml.
  • Ny Flutter-service: recipe-flutter.
  • Service ansluten till natverk:
    • recipe-internal (backend access)
    • proxy (external Caddy reachability)
  • Flutter-container serverar web build via intern Caddy.
  • Exponering via extern Caddy med site test.gynther.se -> recipe-flutter:5000.
  • API anrop gar same-origin via /api och proxas internt till recipe-api:8080.

Inventarie (2026-04-22)

  • Filtrering per plats (alla/kyl/frys/skafferi) via inventoryLocationFilterProvider.
  • Sortering (namn A-O, bast fore stigande/fallande) via inventorySortFilterProvider.
  • Riverpod-query (InventoryQuery) skickar location och sort som queryparametrar till backenden.
  • Alla felmeddelanden gar via mapErrorToUserMessage(error, context).

Baslager/Pantry (2026-04-22)

  • Pantry-produkter grupperas nu pa kategori utifrån backend-relationen categoryRef (rekursiv parent-kedja -> categoryPath), med fallback till legacy product.category och sist Ovrigt.
  • PantryProduct har categoryId och categoryPath som parsas fran API-svaret.

Backend: user-scope for pantry och matplan (2026-04-22)

  • PantryItem och MealPlanEntry ar nu user-scopade i Prisma-schemat.
  • pantry-controller/service filtrerar alltid per userId fran JWT.
  • meal-plan-controller/service filtrerar alltid per userId; inventoryCompare anvander inloggad anvandares pantry.
  • Migration: 20260422130000_user_scope_pantry_meal_plan applicerad pa server.
  • Next.js-frontenden kravde inga funktionella andringar (forfrågningar gar redan via auth-proxy).

Arkitektur

Lager

  • Presentation: skarmar och widgets i flutter/lib/features/*/presentation.
  • State/Application: Riverpod providers/notifiers i flutter/lib/features/*/data.
  • Data/API: ApiClient i flutter/lib/core/api.
  • Platform abstraction: token storage interface i flutter/lib/core/platform.

Routing

  • GoRouter i flutter/lib/core/router/app_router.dart.
  • Nuvarande routes:
    • /login — loginskarm
    • /recipes — receptlista (ShellRoute med AppShell)
    • /recipes/create — nytt recept, utanfor ShellRoute
    • /recipes/:id — receptdetalj, utanfor ShellRoute
    • /recipes/:id/edit — redigera recept, utanfor ShellRoute
    • /profile — profil (ShellRoute med AppShell)
  • /recipes/create maste vara listad fore /recipes/:id i routelistan for att undvika konflikt.
  • Detaljsidor (detalj, skapa, redigera) ligger utanfor ShellRoute for att fa full-screen med automatisk back-knapp.

Auth

  • Login endpoint: POST /api/auth/login.
  • Backend kontrakt anvander username + password.
  • Token-falt i svar: accessToken.
  • Token lagras via ITokenStorage (web implementation med SharedPreferences).
  • Auth-gate i router: utloggad anvandare redirectas till /login, inloggad redirectas fran /login till /recipes.
  • Splash-skarm (/) visas medan auth-state lases fran storage vid app-start.
  • guardedApiCall() i flutter/lib/core/api/guarded_api_call.dart hanterar automatisk logout vid 401.

API-lager

  • ApiClient i flutter/lib/core/api/api_client.dart exponerar: getJson, postJson, patchJson, putJson, deleteJson.
  • Centralicerad HTTP-felklassning: 401 -> ApiErrorType.unauthorized, 403 -> forbidden, 5xx -> server, natverksfel -> network.
  • ApiException i flutter/lib/core/api/api_exception.dart ar den enda feltypen som propageras fran repositories.
  • mapErrorToUserMessage(error, context) i flutter/lib/core/api/api_error_mapper.dart oversatter fel till lokaliserade anvandarmedddelanden. Tar numera BuildContext som andra argument for att hämta korrekt sprak fran AppLocalizations.

Lokalisering (2026-04-22)

Anvandning av lokalisering

For att lagga till en ny lokaliserad strang:

  1. Lagg till nyckeln i app_sv.arb (och app_en.arb).
  2. Kör flutter gen-l10n lokalt (eller lat Docker-bygget gora det).
  3. Anvand context.l10n.dinNyckel i widgetkoden.

For felstrangar fran API: anvand alltid mapErrorToUserMessage(error, context) — lagg inte in hardkodade strängar.

Recipes

  • GET /api/recipes — receptlista.
  • GET /api/recipes/:id — receptdetalj inkl. ingredienser.
  • POST /api/recipes — skapa recept.
  • PATCH /api/recipes/:id — uppdatera recept (OBS: PATCH, inte PUT).
  • DELETE /api/recipes/:id — ta bort recept (returnerar 204, ingen body).
  • POST /api/recipes/parse-markdown — tolka Markdown, returnerar ParsedRecipe med ingrediensforslagslistor.
  • Flutter Recipe-model: name-fallback till title, null-safe parsing av Decimal-strang till double.

Gemensamma UI-komponenter

  • LoadingStateView, EmptyStateView, ErrorStateView i flutter/lib/core/ui/async_state_views.dart.
  • AppShell i flutter/lib/core/ui/app_shell.dart: responsiv NavigationRail (bred) / NavigationBar (smal), delad AppBar med logout.

Kanda API-fallgropar (viktigt!)

Regel: Kontrollera alltid HTTP-metod i TEKNISK_BESKRIVNING.md innan en ny repository-metod implementeras.

Operation Korrekt metod Fel som gjorts
Uppdatera recept PATCH /api/recipes/:id PUT — ger 404
Uppdatera inventariepost PATCH /api/inventory/:id Anvand PATCH
Uppdatera matplan POST /api/meal-plan (upsert) Ingen PUT/PATCH

Generell regel: NestJS-backenden anvander PATCH for partiella uppdateringar, inte PUT. PUT exponeras inte pa nagra resurser i detta projekt.

Drift och deploy

Build/run

  • Build argument i compose: API_BASE_URL=/api.
  • Build command:
    • docker compose -f compose.yml -f compose.flutter.yml build recipe-flutter
  • Run command:
    • docker compose -f compose.yml -f compose.flutter.yml up -d --no-deps recipe-flutter

Rekommenderat kommandomonster

For att minska risken for fel startordning eller missforstand mellan huvudappen och Flutter-sparet:

Nar huvudappen ska vara uppe:

  • docker compose up -d recipe-db recipe-api recipe-frontend

Nar Flutter-klienten ska vara uppe:

  • docker compose -f compose.yml -f compose.flutter.yml up -d --no-deps recipe-flutter

Nar bade huvudappen och Flutter testas parallellt:

  1. Starta huvudappen med compose.yml.
  2. Starta sedan Flutter med override-filen compose.flutter.yml.

Viktigt:

  • docker compose build ... bygger bara image.
  • docker compose up -d ... kravs alltid for att containern faktiskt ska starta.

Viktiga verifieringar

  • Compose merge valid:
    • docker compose -f compose.yml -f compose.flutter.yml config
  • Container reachable from external Caddy:
    • docker exec caddy wget -S -O- http://recipe-flutter:5000
  • Public endpoint:
    • curl -I https://test.gynther.se

Viktiga beslut

  • compose.yml lamnas orord; Flutter ligger i separat override-fil.
  • Flutter-web anvander same-origin API (/api) for att undvika mixed-content.
  • Intern Caddy i Flutter-container hanterar static hosting + /api proxy.
  • Feature migration sker stegvis enligt next_steps_flutter.md.

Kanda fallgropar

  • Om recipe-flutter inte ar i proxy natverket blir det 502 fran extern Caddy.
  • Om browser visar gammal JS kan gamla API-URL:er leva kvar i cache/service worker.
  • Login med email fungerar inte om backend forvantar username.
  • recipe-flutter kan stoppas av docker compose down --remove-orphans om kommandot kors utan override-filen och Flutter-sparat tidigare varit uppe.
  • En orphan-varning for recipe-flutter ar normalt forvantad nar man kor huvudappen med bara compose.yml; det betyder inte att backend eller Prisma ar trasiga.

Orphan-varning i praktiken

Om du ser en varning om orphan-containers under arbete med huvudappen betyder det oftast att recipe-flutter tidigare startats via:

  • docker compose -f compose.yml -f compose.flutter.yml up -d recipe-flutter

och att du nu kor ett kommando som bara anvander compose.yml.

Detta ar normalt och ofarligt sa lange du vet vilken stack du avser att kora.

Om test.gynther.se slutar svara efter städning med --remove-orphans, starta om Flutter-sparet med:

  • docker compose -f compose.yml -f compose.flutter.yml up -d --no-deps recipe-flutter

Nasta tekniska steg

Fortsatt migrering enligt prioritering i next_steps_flutter.md:

  1. Fortatt lokalisering av inventarie/pantry/recept-strangar till ARB.
  2. Matplan parity mot nu user-scopat API.
  3. Import parity.
  4. Profil/admin parity.