From 1320f936ec366373aea26b03ec18ea164004933b Mon Sep 17 00:00:00 2001 From: Nils-Johan Gynther Date: Sun, 3 May 2026 17:03:20 +0200 Subject: [PATCH] Refactor technical documentation for clarity and updates - Updated "teknisk_beskrivning_flutter.md" to streamline content and remove outdated sections, focusing on architecture, environment, and recent technical additions. - Enhanced "migrering-MSI.md" with post-migration updates and clarifications for target audience. - Revised "produktlansering.md" to serve as a release checklist, ensuring it complements existing documentation without duplication. Co-authored-by: Copilot --- NEXT_STEPS.md | 376 ++------------ README.md | 26 +- TEKNISK_BESKRIVNING.md | 17 +- _archive/microservice-ai/AI-FUNKTIONER.md | 10 + .../microservice-todo/microservice-todo.md | 9 + flutter/README.md | 132 ++--- flutter/next_steps_flutter.md | 477 +----------------- flutter/teknisk_beskrivning_flutter.md | 476 ++--------------- migrering-MSI.md | 11 + produktlansering.md | 86 ++-- 10 files changed, 243 insertions(+), 1377 deletions(-) diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md index d42c194a..c7395a4c 100644 --- a/NEXT_STEPS.md +++ b/NEXT_STEPS.md @@ -1,358 +1,40 @@ -# Nästa steg +# Nasta steg -> Förslag på vad vi kan ta tag i nästa gång vi öppnar projektet. -> Se [README.md](README.md) för funktionsöversikt och [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md) för teknisk detaljerinformation. -> Se [AI-FUNKTIONER.md](AI-FUNKTIONER.md) för planerade AI-funktioner. +Detta ar huvudroadmap for Recipe App. +All detaljhistorik och djup teknisk bakgrund finns i respektive tekniska dokument. ---- +## Dokumentstatus (2026-05-03) -|---|---| -| Inventorie (CRUD, konsumtion, historik) | ✅ Klart | -| Recept (skapa, visa, importera, matchning) | ✅ Klart | -| Receptredigering och borttagning (JWT-autentisering) | ✅ Klart | -| Snabbimport (URL/PDF/bild/ICA) | ✅ Klart | -| Kvittoimport (Mistral AI, OCR, alias) | ✅ Klart | -| Import-microservice (importer-api, backend-till-backend) | ✅ Klart (2026-04-30) | -| Kvittoimport — granskningsflöde i Flutter (edit, merge, destination) | ✅ Klart (2026-05-01) | -| Matplanering (veckovy, inköpslista) | ✅ Klart | -| Matplan — portionsjustering per dag | ✅ Klart | -| Matplan — inventariejämförelse (backend) | ✅ Klart | -| Matplan — inventariejämförelse (frontend-vy) | ✅ Klart (✅/⚠️/❌ integrerat i inköpslistan) | -| Baslager (lista, lägg till, ta bort) | ✅ Klart (global v1, user-scope planerad) | -| Admin: Produkter (edit, merge, duplicate, restore, reset) | ✅ Klart | -| Admin: Bulk-kategorisering | ✅ Klart | -| Receptredigering (frontend UX) | ✅ Klart | -| Receptbilder (upload URL) | ✅ Klart | -| Autentisering (JWT, Auth.js v5, User-modell) | ✅ Klart | -| Klient-side JWT via useAuthFetch() | ✅ Klart | -| SessionProvider i root layout | ✅ Klart | -| Användarprofil (firstName, lastName, email) | ✅ Klart | -| Produktkategorier — hierarkisk struktur (3 nivåer) | ✅ Klart | -| Kategori-seed (seed_all.sql, komplett träd, enda sanningskällan) | ✅ Klart | -| Kategoritilldelning i admin-UI | ✅ Klart | -| Taggning av produkter | ✅ Klart | -| Näringsvärden på produkter | ✅ Klart (schema + API) | -| Seed produktdata med kategoritilldelning | ✅ Ersatt — seed innehåller nu enbart kategorier (2026-05-02) | -| Användarspecifika produkter (UserProduct) | ✅ Klart (2026-05-02) — `Product.ownerId` obligatorisk, globala produkter borttagna | -| Användarroller (user / admin) | ✅ Klart | -| Användarhantering i admin-UI | ✅ Klart | -| Profilsida med flikar (Min profil / Användare / Databas med undertabbar) | ✅ Klart | -| Teknisk skuld — oanvända InventoryItem-fält | ✅ Klart (migration 20260418) | -| Teknisk skuld — redirect-routes städade | ✅ Klart | -| Premium-plan (isPremium på User, Free/Paid-dropdown) | ✅ Klart | -| AI-modul (AiService, Mistral-kategorisering, fallback) | ✅ Klart | -| Admin: AI-kategorisering per produkt ("Fråga AI") | ✅ Klart | -| Admin: AI-bulk-kategorisering av okategoriserade produkter | ✅ Klart | -| Produktstatus (pending / active / rejected) | ✅ Klart | -| Admin: Väntande produktförslag (pending-sida) | ✅ Klart | -| Kvittoimport — AI-kategorisuggestion för premium-användare | ✅ Klart | -| Säkerhetshuvuden — Caddy (globala headers) | ✅ Klart | -| Säkerhetshuvuden — Next.js CSP | ✅ Klart | -| Säkerhetshuvuden — NestJS Helmet (backup) | ✅ Klart (aktiveras vid nästa rebuild) | -| Buggfix: "Vad behöver jag köpa" — flimmer och scroll | ✅ Klart | -| Startsida — produktadmin-länk borttagen | ✅ Klart | -| Avancerad AI-integration (veckoplanering, receptförslag) | ❌ Planerad | -| EAN-skanning via Open Food Facts API | ❌ Planerad | +- Fokus: en gemensam prioriteringslista for produkt, utveckling och drift. +- Delplaner for underomraden ska referera hit, inte duplicera hela roadmapen. -## Status — senast genomgånget: 2026-05-02 +## Nyligen klart -### Nyheter och förbättringar -- **Kvittoimport — brödregler och guardrails utökade (2026-05-03)** — `ruleBasedCategorySuggestion()` och `applyContradictionGuard()` täcker nu fler brödsignaler (t.ex. roast'n toast, toastbröd, formbröd, lantbröd, fullkornsbröd, franska, limpan/brod) och remappar felaktiga AI-träffar till `Bröd & Kakor > Bröd`/`Rostbröd`. -- **Prisma-schema justerat för Product (2026-05-03)** — `Product.brand` är borttaget från Prisma-modellen och från produktuppdatering i backend eftersom kolumnen saknas i aktuell databas. Detta förhindrar Prisma-felet `The column recipe_app.Product.brand does not exist in the current database` vid t.ex. `findUnique`. -- **Produkter user-scoped — ny databasarkitektur (2026-05-02)** — `Product.ownerId` är nu obligatorisk (non-nullable). Alla globala seed-produkter är borttagna. Varje produkt ägs av en enskild användare och raderas vid kontoradering (CASCADE). `seed_all.sql` innehåller nu enbart kategorier. Kvittoimportens matchning filtrerar på `ownerId = userId` från JWT. Se TEKNISK_BESKRIVNING.md för fullständig beskrivning. -- **Kategorier utökade (2026-05-02)** — Nya L2/L3-noder: `Bröd & Kakor > Kondis & fika > Kaffebröd` (wienerbröd, donuts, munkar m.m.) och `Dryck > Te & choklad > Te` (chai, vanilla chai, ceylon te m.m.). Nya L3-noder under `Mejeri, ost & ägg > Allergi mejeri`: Laktosfri mjölk, Filmjölk & Yoghurt, Kvarg & Cottage cheese, Matfett, Allergi matlagning. -- **Regelbaserad kategoridetektion utökad (2026-05-02)** — `ruleBasedCategorySuggestion()` täcker nu Te (te, tea, chai, tepas) och Kaffebröd (wienerbröd, donut, munk, croissant, kanelbulle, bakelse, semla m.fl.) utöver befintliga mejeri-regler. -- **AI-guardrail (2026-05-02)** — `AiService.suggestCategory()` remappar nu `low`/`medium`-konfidenspoäng till L1-föräldern istället för att returnera potentiellt fel L2/L3-kategori. -- **Förbättrad produktmatchning (2026-05-02)** — `findWordMatch` normaliserar nu diakritik (ä→a, ö→o, å→a) före jämförelse och tillåter enstaka stark partiell matchning för ord ≥5 tecken (löser t.ex. "vispgrädde" → produkt "grädde"). -- **Kategorisuggest för matchade produkter (2026-05-02)** — `matchProducts()` läser nu in `categoryRef` för matchade produkter och sätter `categorySuggestion` direkt. `enrichWithAiCategories()` körs för alla items utan `categorySuggestion`, inte bara ej matchade. -- **Kvittoimport Fas 6b klar (2026-05-01)** — Flutter-granskningsflödet färdigt: per-rad checkbox, redigeringsdialog med destination-väljare (Inventarie/Baslager), merge-förhandsvisning, parallell laddning av inventarie och baslager, snackbar med separat räkning. -- **Kvittoimport Fas 6c klar (2026-05-01)** — Separering av AI-chip och produktsuggestions-chip, produktnamns-normalisering, och validering av AI-kategorier. -- **Microservice-importer integrerad (2026-04-30)** — All import-logik (URL-skrapning, OCR, PDF-parsning, AI-kvittoparsning) delegeras nu till `importer-api` som körs som intern Docker-tjänst. `recipe-api` behåller produktmatchning och AI-kategorisering. Se [migrering-MSI.md](migrering-MSI.md) för detaljer. -- **User-scope för pantry och matplan** — Alla baslager- och matplansdata är nu per användare. Backend och Prisma-schema är migrerade. -- **Robust bildimport** — Bild-URL normaliseras, laddas ner och optimeras i backend. Bilden kopplas till receptet och raderas vid delete. Diagnostikloggning på alla steg. -- **Importflöde** — Quick-import och receipt-import har förbättrats med robust multipart-hantering, timeout, och felhantering. -- **Flutter-parity** — Matplan, inventarie, baslager och receptflöden är nu fullt migrerade till Flutter med user-scope och robust felhantering. +- Kvittoimport: forbattrad antal/forpackningsinferens och robustare regelmotor. +- Kategorisering: utokade brodregler + contradiction guards. +- Kategoritrad: ny nod `Korvbrod` under `Fastfoodbrod` i seed-data. +- Flutter: klientpersistens for pagande kvittoimport. +- Produktmodell: user-scoped produkter och seed renodlad till kategorier. -### Kända begränsningar -- Kvittoimport: användare utan egna produkter får inga produktmatchningar — enbart kategorisuggestioner via regler/AI (förväntat beteende, byggs upp allt eftersom). -- `ReceiptAlias` är ännu inte user-scoped (alias är fortfarande globala — se aliasstrategin nedan). -- `receipt_import_tab.dart` (~1 400 rader) och `swipeable_inventory_tile.dart` är ännu inte lokaliserade. -- Vissa adminfunktioner och avancerad AI-integration är planerade men ej migrerade. +## Huvudprioriteringar ---- +1. Aliasstrategi i kvittoimport: user-scope som standard, global fallback via admin. +2. Stabilisera bildimport och diagnostik i alla miljoer. +3. Lokalisera kvarvarande stora Flutter-vyer i import/inventarie. +4. Forbereda avancerad AI-integration med tydlig loggning/audit. +5. Pa borja EAN-stod via Open Food Facts. -## Nästa steg +## Beslut som styr arbetet -1. Bygg upp UI-flöde för att skapa/spara egna produkter vid kvittobekräftelse (POST /products med `ownerId` från JWT). -2. Inför user-scope för `ReceiptAlias` (lägg till `userId`, unika index, admin-godkänd global fallback). -3. Implementera automatisk alias-inlärning vid manuell korrigering i importflödet. -4. Kvittoimport steg 2: persistenta förpackningsfält i inventarie (packCount, packSizeQuantity, packSizeUnit) + visning/redigering i inventory-UI. -5. Lokalisera `receipt_import_tab.dart` och `swipeable_inventory_tile.dart`. -6. Smoke-test på testdomän och avstämning. -7. Planera och påbörja avancerad AI-integration och EAN-skanning. -8. AI-kategorisering: kandidatbegränsning före AI (narrowing till relevant gren/kandidatlista istället för hela kategoriträdet). -9. AI-kategorisering: egen confidence-score i backend (regel/lexikal signal + AI-signal), inte enbart modellens confidence. -10. AI-kategorisering: logga användarkorrigeringar och bygg feedbackloop för nya regler/synonymer. -11. AI-kategorisering: utvärdera alternativ modell för kategorisering med A/B-test på historiska kvittorader. +- User-scope for data som ar personligt agd. +- Backend-kontrakt ar sanningskalla; klienter foljer kontrakten. +- Importfunktionalitet ar delegerad till microservice-importer dar det ar beslutat. -## Beslut 2026-05-02 - Aliasstrategi för kvittoimport +## Relaterade dokument -- Alias ska vara hybrid: user-scope som standard, globalt alias endast via admin-verifiering. -- Syfte: minimera felträffar mellan användare och samtidigt bygga en kvalitetssäkrad global kunskapsbas. -- Tekniskt nästa steg i backend: -- Lägg till user-scope för `ReceiptAlias` (t.ex. `userId` + relevanta unika index). -- Behåll global alias som fallback för admin-godkända mappningar. -- Tekniskt nästa steg i klient: -- Spara manuell korrigering som alias (default: user-scope). -- Eventuell admin-toggle för att spara alias globalt. - ---- - -## Beslut 2026-04-22 — Pantry och matplan på user-nivå - -Pantry och matplan ska inte vara globala. De ska vara användarspecifika i backend. - -### Varför -- Nuvarande implementation delar baslager och matplan mellan alla användare. -- Det ger felaktig inköpslogik och otydligt ägarskap i multi-user-läge. - -### Krävda backend-ändringar (prio) -1. **PantryItem user-scope i Prisma** -- Lägg till `userId` i `PantryItem` + relation till `User`. -- Ändra unik regel från global `productId` till kombinationen `userId + productId`. -- Lägg index på `userId`. - -2. **Pantry API user-scope** -- `GET /api/pantry` ska returnera inloggad användares baslager. -- `POST /api/pantry` ska skapa för inloggad användare. -- `DELETE /api/pantry/:id` ska bara kunna ta bort poster som ägs av inloggad användare. - -3. **MealPlan user-scope i Prisma och service** -- Lägg till `userId` i `MealPlanEntry` + relation till `User`. -- Ändra unik regel från global `date` till `userId + date`. -- Filtrera `findByRange`, `upsert` och `removeByDate` per inloggad användare. - -4. **Matplanens inventory-compare ska använda user-scope pantry** -- Pantry-uppslag i `inventoryCompare` ska filtreras på samma `userId`. - -### Migrering och release-strategi -1. Ta migration för `PantryItem` + `MealPlanEntry`. -2. Backfill: tilldela befintliga poster till vald default-användare (eller rensa och starta om datan i testmiljö). -3. Uppdatera backend-kontrollers till `@CurrentUser()`-mönster. -4. Verifiera med två testanvändare att data är isolerad. -5. Därefter uppdateras Flutter/Next-klienterna mot de nya kontrakten. - ---- - -## Notering 2026-04-20 - -## Notering 2026-04-21 - -- Rollskydd i frontend (middleware) och backend (admin på endpoints) är nu heltäckande. -- Rate limiting, CORS-låsning och JWT_SECRET-krav är på plats. -- Konsol-loggar borttagna ur backend. -- Kvar: Kryptering av PII (e-post, namn i databasen), automatisering av seed_all.sql vid fresh install. - -Den senaste versionen av `db/seeds/seed_all.sql` är pushad till utvecklingsmiljön, men har **ännu inte körts** på databasen. Nästa gång vi vill uppdatera kategoriträdet måste seed-scriptet köras manuellt: - -```bash -docker exec -i recipe-db mariadb -uroot -p"$DB_PASS" recipe_app < db/seeds/seed_all.sql -``` - -Se även TEKNISK_BESKRIVNING.md för detaljer om seed-processen. - ---- - -## Vägen till produktlansering - -- [Säkerhet & Data](produktlansering.md#1-säkerhet--data) -- [DevOps & Stabilitet](produktlansering.md#2-devops--stabilitet) -- [Testning & Kvalitet](produktlansering.md#3-testning--kvalitet) -- [Funktionella förbättringar](produktlansering.md#4-funktionella-förbättringar) -- [Risker & Flaskhalsar](produktlansering.md#5-risker--flaskhalsar) - ---- - -## Prioriterade förbättringar - -### 1. ICA-skraparen missar receptbild ✅ -**Problem:** Vid import av ICA-recept via URL hämtas inte receptbilden korrekt. - -- Felsök parsern i `recipe-document-converter/src/parser.ts` — kontrollera att ICA:s bild-selektor fortfarande matchar sidans HTML-struktur -- ICA kan ha ändrat klassnamn eller lazy-load-mekanism sedan skraparen skrevs -- Verifiera med ett konkret ICA-recept-URL och logga vad `imageUrl` returnerar - -### 2. Seed-data ✅ -**Klart.** `db/seeds/seed_all.sql` är den enda sanningskällan för kategorier och produkter. - -Filen: -- TRUNCATEar `Category` och nollställer `Product.categoryId` -- Bygger hela kategoriträdet (nivå 1–3) utan dubbletter -- Insertar ~190 produkter (INSERT IGNORE) -- Kopplar produkterna till rätt kategori via JOIN-subqueries - -Körs manuellt: `docker exec -i recipe-db mariadb -uroot -p"$DB_PASS" recipe_app < db/seeds/seed_all.sql` - -### 2. Refactor: seed_all.sql som del av fresh install -**Mål:** Fresh install ska inte kräva ett manuellt seed-steg. - -Nuläge: -- `db/init/001-init.sql` (MariaDB auto-init) skapar bara en bootstrap-check-tabell -- Prisma-migrationen `20260417310000_add_category_tree` seedar kategorier en gång, men seed_all.sql skriver över dem -- `seed_all.sql` körs **inte** automatiskt vid deploy eller fresh install - -Alternativ: -- **Alt A:** Flytta seed_all.sql-logiken till `db/init/001-init.sql` — körs automatiskt av MariaDB-containern vid första start -- **Alt B:** Skapa en `prisma/seed.ts` som körs via `prisma db seed` — standard NestJS/Prisma-mönster, kan inkluderas i deploy.sh -- **Alt C:** Lägg till `seed_all.sql` som ett steg i `deploy.sh` (körs alltid, idempotent p.g.a. TRUNCATE+INSERT IGNORE) - -Oavsett alternativ bör de gamla kategori-INSERTs i `20260417310000_add_category_tree/migration.sql` tas bort eller kommenteras ur för att undvika förvirring. - -### 2. Användarroller och full användarhantering ✅ -**Klart.** - -Systemet har nu fullständig rollbaserad åtkomstkontroll och ett komplett användarhanteringsgränssnitt inbyggt i profilsidan. - -**Rollsystemet:** -- **Prisma-migration** (`20260418100000_add_user_role`) — fältet `role String @default("user")` lades till på `User`-modellen -- **`@Roles('admin')`-dekoratorn** (`auth/decorators/roles.decorator.ts`) — använder `SetMetadata` för att markera endpoints -- **`RolesGuard`** (`auth/roles.guard.ts`) — registrerad globalt som `APP_GUARD`; läser rollmetadata, kastar 403 om rätt roll saknas -- **JWT inkluderar nu `role`** — `jwt.strategy.ts` returnerar `{userId, username, role}`, `auth.service.ts` signerar med `role` i payload -- **Bootstrap-användare** (`users/admin-bootstrap.service.ts`) — `OnApplicationBootstrap` skapar/uppdaterar Nadmin, Padmin, user1 och user2 vid varje uppstart via miljövariabler -- **Skyddade produkt-endpoints** — `@Roles('admin')` på `merge`, `delete`, `restore`, `reset-all`, `bulk-update`, `backfill-canonical` i `products.controller.ts` - -**Backend-endpoints för användarhantering (alla kräver admin-roll):** -- `GET /api/users` — lista alla användare -- `PATCH /api/users/:id/role` — ändra roll -- `POST /api/users` — skapa ny användare (validering: unikt användarnamn och e-post) -- `DELETE /api/users/:id` — ta bort användare (skyddad: kan inte ta bort sig själv) -- `POST /api/users/:id/reset-password` — genererar tillfälligt lösenord, returnerar meddelandetext + lösenord -- `PATCH /api/users/:id/email` — uppdatera e-postadress - -**Profilsidan med flikar (`/profil`):** -- `?tab=profil` — Min profil (alla användare) -- `?tab=anvandare` — Användare (enbart admin): skapa, ta bort, rollbyte, e-postbyte, lösenordsåterställning med kopierings-modal -- `?tab=databas` — Databas (enbart admin): produktadmin, nu med undertabbar: - - **Varor:** lista och redigera aktiva produkter - - **Skapa / Slå ihop:** skapa ny produkt, återställ produktdatabas, slå ihop dubbletter - - **Papperskorg:** visa mjukraderade produkter, återställ eller radera permanent -- `/admin/users` omdirigerar till `/profil?tab=anvandare` -- Navigeringslänken "👥 Användare" går direkt till `/profil?tab=anvandare` - -### 3. Matplan-vy (frontend-polish) ✅ -**Klart.** - -Inköpslistan och inventariejämförelsen är sammanslagna till en enhetlig vy med tre statusnivåer: -- ❌ Saknas helt — visar hur mycket som behövs köpas -- ⚠️ Delvis hemma — visar hur mycket mer som behövs + vad som finns -- ✅ Finns hemma — markeras nedtonat, ingen köpindikering - -Listan sorteras automatiskt: saknade ingredienser överst, hemma-ingredienser underst. En sammanfattningsrad visar totalt antal per statuskategori. - -### 4. Teknisk skuld (underhåll) -**Mål:** Minska komplexitet och risk för buggar. - -#### A. CanonicalNameForm och NameForm ✅ -Filerna var redan borttagna — inga aktiva imports hittades. Inget att göra. - -#### B. Oanvända fält på InventoryItem ✅ -Följande 6 fält togs bort via Prisma-migration (`20260418000000_remove_unused_inventory_fields`): -`priority`, `shelfNote`, `isOnSale`, `priceLevel`, `proteinType`, `isLeftover` -- Schema, DTOs (create + update), service och frontend-typen är städade. -- `opened` och `suitableFor` behölls — de används i UI. - -#### C. Validering av DTO:er i admin-actions ✅ -Redan implementerat — `trim()` + max 100 tecken på alla fält i `actions.ts`. Inget att göra. - -#### D. Routing-städning för kvitto och import ✅ -`frontend/app/kvitto/page.tsx` och `frontend/app/recipes/import/page.tsx` är borttagna. -`/import` täcker båda use-cases via flikar. - -#### E. Seed-data i versionshantering ✅ -`data/matvaror_sverige.csv` och `data/seed_products.sql` behålls i git för reproducerbarhet. Inga ändringar i `.gitignore`. - -### 5. Avancerad AI-integration -**Mål:** Smarta receptförslag och veckoplanering baserat på inventarie och kampanjdata. - -AI-infrastrukturen är nu på plats (`AiService`, `mistral-small-2603`, premium-plan). Kategorisering för produkter och kvittoimport är implementerat. Nästa steg: - -- **"Vad ska jag laga idag?"** — Receptförslag baserat på vad som finns i inventariet; kan byggas direkt ovanpå befintliga inventory- och recipe-endpoints -- **Veckoplanering med AI** — Generera ett veckoschemat baserat på inventarie, preferenser och ev. kampanjpriser (kräver extern datakälla) -- Kräver: tydlig API-design, kostnadskontroll och modellval per use-case - ---- - -## AI-loggning och audit - -- detta behöver ske innan nästa Ai-integration (receptförslag, veckoplanering) implementeras, för att säkerställa att vi har en robust lösning på plats för att spåra och analysera AI-anrop och resultat -- Utforska och utveckla lösning för loggning och audit av AI-input och output -- Syfte: möjliggöra spårbarhet, felsökning och kvalitetssäkring av AI-funktioner -- Implementera loggning på ett sätt som inte lagrar personuppgifter eller känslig data i klartext -- Utvärdera om loggar ska lagras i separat databas eller fil, och hur de kan användas för analys och förbättring - ---- - -## Enhetsstöd och konvertering - -- Se över om vi behöver utöka antalet stödda enhetstyper (t.ex. fler volym- eller portionsenheter) -- Utveckla och förbättra normaliseringen i `recipeservice.normalizeUnit` -- Se över och testa konverteringslogiken för enheter (t.ex. edge cases, felhantering) -- Fundera på om AI kan användas för att tolka, normalisera eller konvertera enheter och mängder smartare - ---- - -## Enhetstester - -Jest + ts-jest är uppsatt. Tester finns för: -- `normalize-name.ts` — 10 tester -- `base.parser.ts` (`parseIngredientLine`) — 12 tester -- `recipes.service.ts` (`normalizeUnit`, `convertUnit`) — 17 tester - -Kör med `npm test` i `backend/`. - ---- - -## Planerade funktioner - -### Säkerhet — kryptering av känslig användardata -**Mål:** Kryptera känsliga fält (t.ex. e-postadresser, personuppgifter) i databasen med en hybridlösning. - -Förslag på approach: -- **AES-256-GCM** för symmetrisk kryptering av data i vila (kolumnnivå i MariaDB eller på applikationsnivå i Prisma middleware) -- **Nyckelhantering** via miljövariabel eller extern nyckelhanteringstjänst (t.ex. HashiCorp Vault) -- Kräver genomtänkt migrering av befintlig data och påverkar sökbarhet (krypterade fält kan inte indexeras direkt) - -### EAN-skanning — import via streckkod (Open Food Facts) -**Mål:** Låt användaren skanna eller skriva in en EAN-streckkod och få produktinformation (namn, kategori, näringsvärden) ifyllt automatiskt. - -Open Food Facts är ett öppet, gratis API utan API-nyckel för grundläggande användning. - -**Exempelanrop (EAN 7310960010016):** -``` -GET https://world.openfoodfacts.org/api/v0/product/{ean}.json -``` -Svaret innehåller: -- `product.product_name` — produktnamn -- `product.categories` — kategoristräng (kommaseparerad) -- `product.nutriments` — näringsvärden (energi, protein, fett, kolhydrater, m.fl.) -- `product.code` — EAN-koden bekräftad - -**Förslag på implementation:** - -1. **Backend-endpoint** — `GET /api/products/ean/:code` — slår upp i Open Food Facts, returnerar normaliserat produktförslag (namn, kategori, näringsvärden) utan att spara -2. **Frontend-import** — nytt fält i produktformuläret (eller separat import-flöde): ange EAN → knapp "Hämta" → formuläret förifylls -3. **Alternativt:** kamerabaserad skanning i mobil webbläsare via `BarcodeDetector` API (eller externt bibliotek som `zxing-js`) -4. **Kategorimappning** — Open Food Facts-kategorier är på engelska/franska; en mappningstabell eller fuzzy-matchning mot systemets kategorier behövs -5. **Näringsdata** — om `product.nutriments` finns kan det sparas direkt i Prisma-modellens näringsvärdesfält (redan schema-klara) - -**Begränsningar att ha i åtanke:** -- Produkttäckning varierar — svenska dagligvaror är välrepresenterade men inte allt finns -- Produktnamn är ofta på originalspråk; kan behöva redigeras -- Rate limiting: för hög användning rekommenderar Open Food Facts att kontakta dem - -### Byta @Post till @Patch på backfill-canonical -Konsekvenser: ⚠️ Bryta ändring. - -Frontend anropar /api/products/backfill-canonical med POST från AdminProductList. -Caddy och Next.js API-routes kan ha hårdkodade metoder. -Kräver synkroniserad ändring i backend + alla anropsställen i frontend, annars slutar funktionen fungera. +- `README.md` - anvandarperspektiv. +- `TEKNISK_BESKRIVNING.md` - teknisk huvudreferens. +- `produktlansering.md` - releasechecklista. +- `migrering-MSI.md` - migreringshistorik for importer. +- `flutter/next_steps_flutter.md` - Flutter-specifik plan. +- `_archive/microservice-ai/AI-FUNKTIONER.md` - AI-strategi och historik. diff --git a/README.md b/README.md index be9aaa41..b9a7e2fd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,31 @@ En fullstack-applikation för hantering av hemmavaror och recept. Håll koll på > För teknisk detaljinformation, se [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md). > För förslag på nästa steg i projektet, se [NEXT_STEPS.md](NEXT_STEPS.md). -> För planerade AI-funktioner, se [AI-FUNKTIONER.md](AI-FUNKTIONER.md). +> För planerade AI-funktioner, se [_archive/microservice-ai/AI-FUNKTIONER.md](_archive/microservice-ai/AI-FUNKTIONER.md). + +## Dokumentkarta + +- [README.md](README.md): användaröversikt och funktioner. +- [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md): teknisk referens för drift och utveckling. +- [NEXT_STEPS.md](NEXT_STEPS.md): gemensam roadmap och prioriteringar. +- [produktlansering.md](produktlansering.md): releasechecklista. +- [migrering-MSI.md](migrering-MSI.md): migreringshistorik för importer. +- [flutter/README.md](flutter/README.md): Flutter ur användarperspektiv. +- [flutter/teknisk_beskrivning_flutter.md](flutter/teknisk_beskrivning_flutter.md): Flutter teknisk referens. +- [flutter/next_steps_flutter.md](flutter/next_steps_flutter.md): Flutter roadmap. + +## Dokumentstatus (2026-05-03) + +### Målgrupp +Detta dokument är skrivet för användare och produktägare. Fokus är vad som fungerar i appen och vad som förbättrats i det dagliga flödet. + +### Nytt sedan senaste sessionerna +- Kvittoimporten har blivit mer träffsäker för förpackningar och mängder (t.ex. rader med multipack och "2st"). +- Kategorisering av brödrelaterade produkter har förbättrats så att färre varor hamnar fel. +- Ny underkategori i kategoriträdet: `Bröd & Kakor > Bröd > Fastfoodbröd > Korvbröd`. +- Importerat kvitto i Flutter ligger kvar i klientens session vid navigering/refresh, så användaren kan fortsätta utan att börja om. +- Produkter är user-scopade (personliga per användare), vilket minskar felmatchningar mellan olika användare. +- Ingen ny serverlagring infördes för kvitto-sessionen; persistensen sker i klienten. --- diff --git a/TEKNISK_BESKRIVNING.md b/TEKNISK_BESKRIVNING.md index 19e64f49..9359d5f9 100644 --- a/TEKNISK_BESKRIVNING.md +++ b/TEKNISK_BESKRIVNING.md @@ -2,7 +2,22 @@ > Se [README.md](README.md) för användarinformation och kom-igÃ¥ng-guide. > Se [NEXT_STEPS.md](NEXT_STEPS.md) för förslag pÃ¥ nästa steg i projektet. -> Se [AI-FUNKTIONER.md](AI-FUNKTIONER.md) för planerade AI-funktioner och modellval. +> Se [_archive/microservice-ai/AI-FUNKTIONER.md](_archive/microservice-ai/AI-FUNKTIONER.md) för planerade AI-funktioner och modellval. + +## Dokumentstatus (2026-05-03) + +### Målgrupp +Detta dokument är skrivet för systemadministratörer och programmerare. Fokus är arkitektur, datamodell, integrationer och driftkonsekvenser. + +### Tillägg från senaste sessionerna +- **Kvittoimport, regelmotor:** förbättrad tolkning av multipack och enheter i importerade kvittorader. +- **Kategori-guardrails:** utökade regler för bröd/rostbröd samt contradiction guards för att minska felaktiga AI-träffar. +- **Kategori-seed:** ny kategori `Korvbröd` under `Fastfoodbröd` i seed-data. +- **Klientpersistens i Flutter:** kvittoimportens arbetssession sparas i klienten och återläses vid behov. +- **Dataperspektiv:** kvittosessionen lagras inte server-side; backend-kontraktet är oförändrat för den delen. + +### Driftnotering +Verifiera efter deploy att seed-körning inkluderar uppdaterat kategoriträd och att kvittoflödet använder den senaste regelbaserade parserlogiken. ## Översikt diff --git a/_archive/microservice-ai/AI-FUNKTIONER.md b/_archive/microservice-ai/AI-FUNKTIONER.md index 71f4cad0..1e88603e 100644 --- a/_archive/microservice-ai/AI-FUNKTIONER.md +++ b/_archive/microservice-ai/AI-FUNKTIONER.md @@ -2,6 +2,16 @@ > Se [README.md](README.md) för funktionsöversikt, [TEKNISK_BESKRIVNING.md](TEKNISK_BESKRIVNING.md) för teknisk arkitektur och [NEXT_STEPS.md](NEXT_STEPS.md) för prioriterade nästa steg. +## Dokumentstatus (2026-05-03) + +### Målgrupp +Detta arkivdokument är för teknisk planering och historik kring AI-strategi. + +### Komplettering från senaste sessionerna +- AI-förslag för kategorier används tillsammans med regelbaserad parser, inte som ensam källa. +- Contradiction guards och domänregler (bl.a. bröd/rostbröd) prioriteras för att reducera felklassning. +- Klientens UX separerar produktförslag från AI-kategoriförslag för tydligare semantik i granskningen. + Detta dokument beskriver de AI-funktioner som implementeras eller planeras som **premium-funktioner** i **recipe-app**. Varje funktion är kopplad till en rekommenderad Mistral-modell, med fokus på att använda de enklaste och mest kostnadseffektiva alternativen. --- diff --git a/_archive/microservice-todo/microservice-todo.md b/_archive/microservice-todo/microservice-todo.md index 21a1573d..55a313be 100644 --- a/_archive/microservice-todo/microservice-todo.md +++ b/_archive/microservice-todo/microservice-todo.md @@ -1,5 +1,14 @@ Read memory [](file:///c%3A/Users/Nils-JohanGynther/AppData/Roaming/Code/User/workspaceStorage/e6ea1b0bd55239bec87a0a6ab7819f74/GitHub.copilot-chat/memory-tool/memories/NTkxM2ZhMmYtYjViYi00YTE0LTg2NGEtNmYyYzZjMTcxNWEw/microservice-todo.md) +## Dokumentstatus (2026-05-03) + +### Målgrupp +Detta arkivdokument är en historisk plan för framtida todo-microservice och riktar sig till utvecklare/arkitekter. + +### Kommentar utifrån senaste sessionerna +- Fokus i senaste sessionerna har legat på kvittoimport, kategoriregler och klientpersistens i befintliga system. +- Ingen aktiv implementation av todo-microservice har påbörjats i denna period. + Jag kan inte direkt flytta filer mellan minnesområdet och projektmappen, men här är hela planen. Kopiera och spara innehållet nedan som recipe-app/microservice-todo.md i din projektmapp: --- diff --git a/flutter/README.md b/flutter/README.md index 994fa1aa..5b5ca3a0 100644 --- a/flutter/README.md +++ b/flutter/README.md @@ -1,113 +1,47 @@ -# Flutter Frontend - Användarguide +# Flutter Frontend - Anvandarguide -Detta dokument beskriver hur du använder Flutter-frontenden för Recipe App ur ett användar- och operatörsperspektiv. +Detta dokument ar for anvandare och operativa testare. +Har beskriver vi vad som fungerar i Flutter-klienten och hur den anvands i praktiken. -## Senaste ändringar (2026-04-25) +## Dokumentstatus (2026-05-03) -**Arkitektur- och UX-förbättringar:** -- Grid-vy för recept: Kolumnval (2/4/6/8) via ikon i AppShell, med Riverpod-provider och SharedPreferences. -- RecipesScreen är nu body-only, ingen egen Scaffold/AppBar. -- AppShell visar grid-ikon endast på /recipes. -- Buggfix: Produktväljaren i pantry/inventarie (ProductPickerField) — bottenark implementeras. -- Kodkvalitet: Inga absoluta Windows-sökvägar. +- Fokus: anvandarflode, inte implementation. +- Teknisk detaljniva finns i `teknisk_beskrivning_flutter.md`. +- Planering och backlog finns i `next_steps_flutter.md`. -**Nyheter och förbättringar:** -- **Fas 5: Matplan parity** — Veckovy, portionsjustering per dag, inköpslista och inventariejämförelse mot användarens pantry är nu fullt migrerade och user-scopade. -- **Fas 6a: Receptimport** — Importflöde för recept (fil/URL) är nu robust, med stöd för PDF, bild och ICA-länkar. Prefill av markdown och bild-url fungerar i Flutter. -- **Bildimport** — Backend och Flutter har förbättrats med robust bildhantering, normalisering av URL:er, fallback och diagnostikloggning. -- **User-scope för pantry och matplan** — Alla baslager- och matplansdata är nu per användare (inte globala). -- **UI/UX-förbättringar** — Produktval med bottenark (ProductPickerField), swipe-för-±1 på inventarielistan (SwipeableInventoryTile), och förbättrad felhantering. +## Vad appen ar -## Vad appen är +Flutter-webben ar en klient for Recipe App som kors i Docker och exponeras via Caddy. +Den anvands parallellt med Next-frontenden under migrering och verifiering. -Flutter-webben för Recipe App är en webbklient byggd med Flutter och körs i Docker med Caddy som proxy. Den är avsedd att ersätta den befintliga Next.js-frontenden och stödja framtida mobilklienter. +## Senaste forbattringar -## Aktuella användarflöden -- Inloggning med användarnamn och lösenord. -- Receptlista efter inloggning. -- Profil-sida (grundversion). -- Utloggning från recept- och profil-sidor. +- Kvittoimportens granskningsflode ar klart och stabiliserat. +- Pagande kvittoimport sparas i klientens session och kan atertas efter refresh/navigation. +- Tolkning av antal/forpackning i kvittorader ar forbattrad, inklusive format som `2st`. +- AI-kategoriforslag och produktforslag visas separerat for tydligare val. -## Var man kommer åt appen -- Testmiljö: `https://test.gynther.se` +## Aktuella anvandarfloden -## Inloggningsdetaljer -- Inloggning förväntar sig användarnamn, inte e-post. -- Exempel på seedad admin-användare i backend: `Nadmin`. -- Lösenordet kontrolleras av servermiljövariabeln (`ADMIN_NADMIN_PASSWORD`). +- Inloggning med anvandarnamn och losenord. +- Recept: lista, skapa, redigera, radera. +- Inventarie och baslager: skapa, redigera, konsumera. +- Matplan: veckovy, portionsjustering, inkopslista. +- Import: receptimport och kvittoimport med granskningssteg. -## Kända begränsningar -- Kvittoimport (Fas 6b) är påbörjad men granskningssteg och bulk-spara återstår. -- Bildimport kräver att containrar är uppdaterade med senaste kod — kontrollera att diagnostikloggar syns vid felsökning. -- Vissa adminfunktioner och avancerad AI-integration är planerade men ej migrerade. +## Kanda begransningar -## Felsökning (användarnivå) -1. Om sidan visar gammalt beteende efter deployment: hård uppdatering eller öppna i inkognitoläge. -2. Om inloggning misslyckas: verifiera användarnamn/lösenord (inte e-post). +- Vissa adminfunktioner och avancerad AI-integration ar planerade men ej fullt migrerade. +- Bildimport forutsatter att containrar ar uppdaterade med senaste kod. + +## Felsokning (anvandarniva) + +1. Om sidan visar gammalt beteende efter deploy: hard uppdatering eller inkognito. +2. Om inloggning misslyckas: verifiera anvandarnamn/losenord (inte e-post). +3. Om importfloden fastnar: rapportera webblasarkonsolens fel till utvecklingsteamet. ## Relaterade dokument -- [next_steps_flutter.md](next_steps_flutter.md) -- [teknisk_beskrivning_flutter.md](teknisk_beskrivning_flutter.md) -## Vad appen är - -Detta är en Flutter Web frontend för Recipe App, som körs i Docker och exponeras via Caddy. Den är avsedd att bete sig som den befintliga webbfrontenden, men är byggd i Flutter för att stödja framtida Android- och iOS-klienter. - -## Aktuella användarflöden -- Inloggning med användarnamn och lösenord. -- Receptlista efter inloggning. -- Profil-sida (grundversion). -- Utloggning från recept- och profil-sidor. - -## Var man kommer åt appen -- Testmiljö: `https://test.gynther.se` - -## Inloggningsdetaljer -- Inloggning förväntar sig användarnamn, inte e-post. -- Exempel på seedad admin-användare i backend: `Nadmin`. -- Lösenordet kontrolleras av servermiljövariabeln (`ADMIN_NADMIN_PASSWORD`). - -## Kända begränsningar -- Kvittoimport (Fas 6b) är påbörjad men granskningssteg och bulk-spara återstår. -- Bildimport kräver att containrar är uppdaterade med senaste kod — kontrollera att diagnostikloggar syns vid felsökning. -- Vissa adminfunktioner och avancerad AI-integration är planerade men ej migrerade. - -## Felsökning (användarnivå) -1. Om sidan visar gammalt beteende efter deployment: hård uppdatering eller öppna i inkognitoläge. -2. Om inloggning misslyckas: verifiera användarnamn/lösenord (inte e-post). -3. Om recept inte laddas: rapportera fel i webbläsarkonsolen/nätverksfelen till utvecklingsteamet. - -## Förväntningar vid release - -Denna frontend är tillgänglig för iterativ testning. Funktionell parity med den nuvarande produktionsfrontenden levereras stegvis. - -## Konverteringsvägen och Onboarding -- **CTA (Call-to-Action):** Tydliga och lockande CTAs som "Se vad du kan laga med det du har hemma." -- **Förenkla onboarding:** Gästinloggning eller demo-läge, sociala inloggningar, välkomstguide, och pop-up-tips. -- **Snabb start med exempeldata:** Förifyllt exempeldata och "Snabbstart"-knapp. -- **Fokusera på "Aha!"-momentet:** Omedelbara receptförslag och automatiska inköpslistor. -- **Tydliga instruktioner och feedback:** Instruktioner för varje steg och omedelbar feedback. -- **Användarvänlig design:** Fokus på kärnfunktioner och enkelhet. -- **Möjlighet att hoppa över onboarding:** Knapp för att hoppa över onboarding. - -## Testa och iterera -- Gå igenom appen som en ny användare för att identifiera eventuella problem. -- A/B-testa olika CTAs och onboarding-flöden. -- Implementera analytik för att spåra var användare hoppar av och varför. - -## Anpassa till målgruppen -- Anpassa marknadsföring och CTAs till målgruppen (t.ex. familjer, matintresserade, meal preppers). -- Var tydlig med appens värdeproposition, t.ex. "Slipp slösa mat – vi visar vad du kan laga med det du har hemma." - ---- - -## Nyheter och förbättringar (2026-04-24) - -- **Navigations- och UX-förbättringar:** - - Tydliga navigationslänkar mellan recept, inventarie, baslager och matplan för att förenkla användarflödet. - - Efter att ett recept redigerats, navigeras användaren nu automatiskt till receptdetaljer. - - Efter konsumtion av inventariepost navigeras användaren automatiskt tillbaka till inventarielistan. - - Efter import av recept navigeras användaren automatiskt till receptlistan. - - Mjukare scrollning i receptdetaljvyn och förbättrad bakgrundsbildshantering. -- **Kodkvalitet:** - - Säkerställt att inga absoluta Windows-sökvägar används i koden, för att stödja bygg och drift på Linux/Ubuntu. +- `next_steps_flutter.md` - roadmap och prioriteringar. +- `teknisk_beskrivning_flutter.md` - teknisk referens for drift/utveckling. +- `../README.md` - overgripande produktinformation. diff --git a/flutter/next_steps_flutter.md b/flutter/next_steps_flutter.md index 1097df49..92d5f89c 100644 --- a/flutter/next_steps_flutter.md +++ b/flutter/next_steps_flutter.md @@ -1,462 +1,41 @@ -# Senaste ändringar (2026-04-24) +# Nasta steg: Flutter-migrering -**Arkitektur- och UX-förbättringar:** -- Grid-vy för recept: Kolumnval (2/4/6/8) via ikon i AppShell, med Riverpod-provider och SharedPreferences. -- RecipesScreen är nu body-only, ingen egen Scaffold/AppBar. -- AppShell visar grid-ikon endast på /recipes. -- Buggfix: Produktväljaren i pantry/inventarie (ProductPickerField) — bottenark implementeras. -- Sprint 2: Databas > Produkter visar nu en riktig adminpanel i profilflödet med sök, okategoriserat-filter och bulk-kategorisering. -- Sprint 2: Användare-fliken stödjer nu Premium av/på direkt från användarmenyn. -- Kodkvalitet: Inga absoluta Windows-sökvägar. -- Dokumentation och next_steps uppdaterade. -# Nästa steg: Flutter-migrering +Detta dokument ar Flutter-teamets roadmap och prioriteringslista. +All historik och implementationdetaljer finns i `teknisk_beskrivning_flutter.md`. -Relaterade dokument: -- [README.md](README.md) -- [teknisk_beskrivning_flutter.md](teknisk_beskrivning_flutter.md) +## Dokumentstatus (2026-05-03) -## Mål och prioriteringar för produktion +- Fokus: aktiv planering framat. +- Endast en roadmap for Flutter for att undvika dubbletter. -### Övergripande mål -- **Funktionell parity:** Säkerställa att alla kärnfunktioner är stabila och fungerar som förväntat. -- **Användarupplevelse:** Förenkla onboarding och säkerställa att användare snabbt förstår appens värde. -- **Produktionsklar:** Säkerställa att appen är redo för lansering genom att adressera kritiska buggar och förbättra prestanda. +## Klart senaste sessionerna -### Icke-förhandlingsbara ramar +- Fas 6b: granskningsflode for kvittoimport (edit, destination, merge, spara). +- Fas 6c: separering av AI-kategorichip och produktforslagschip. +- Fas 6d: klientpersistens for pagande kvittoimport + forbattrad antal/forpackningsinferens. -1. Inget ska tas bort eller ändras i `recipe-api` utom explicit beslutade backend-ändringar för användarscope i pantry och matplan. -2. Inget ska tas bort eller ändras i `recipe-frontend`. -3. Migreringen sker i Flutter-spåret som separat klient mot befintliga API-kontrakt. -4. Next-frontend körs parallellt tills Flutter har verifierad parity i kärnflöden. +## Pagande arbete -## Arbetsplan +- Robust bildimport och diagnostik i drift. +- Aliasstrategi i kvittoimport (hybrid user-scope + global fallback via admin). +- Utokad adminfunktionalitet i Flutter-sparet. -### Pågående arbete -- **Kvittoimport (Fas 6b):** ✅ Klar (2026-05-01) — Granskning, redigering, val av destination (inventarie/baslager), merge och spara implementerat. -- **Kvittoimport (Fas 6c):** ✅ Klar (2026-05-01) — Separering av AI-chip och produktsuggestions-chip, produktnamns-normalisering, och validering av AI-kategorier. -- **Bildimport:** Säkerställa att containrar är uppdaterade med senaste kod och att diagnostikloggar syns vid felsökning. -- **Adminfunktioner:** Avancerad AI-integration och ytterligare adminfunktioner planeras men är ej migrerade. +## Prioriterade nasta steg -### Tillfällig MVP-notering (att ta bort senare) -- [ ] Ta bort tillfällig diagnostikbanner i kvittoimporten när MVP är verifierad. - Banner finns i `lib/features/import/presentation/receipt_import_tab.dart` och visar felkällor för `auth/token`, `categories`, `products:list`, `products:mine`. +1. Verifiera bildimport och felhantering end-to-end i testmiljo. +2. Implementera alias-inlarning vid manuell korrigering i importflodet. +3. Forbattra UI/UX i granskningsfloden for kvittoimport. +4. Fortsatt migrering av kvarvarande adminfloden. +5. Lokalisera kvarvarande delar i import- och inventarievyer. -### Prioriterade nästa steg -1. Säkerställa robust bildimport och diagnostik. -2. Implementera hybrid alias-stöd i kvittoimport tillsammans med backend: user-scope alias som standard och global alias via admin. -3. Stödja alias-inlärning i UI vid manuell korrigering (default: user-scope), samt visa scope tydligt för admin. -4. Implementera avancerad AI-integration för produktkategorisering. -5. Utöka adminfunktioner för användarhantering och produktadministration. -6. Förbättra UI/UX för användarflöden, inklusive onboarding och profilhantering. +## Viktiga beslut -## Notering 2026-05-02 - Aliasstrategi kvittoimport +- Flutter ar separat klient mot befintliga API-kontrakt. +- Ingen klientspecifik speciallogik for datamatchning; backend ar sanningskalla. +- Next-frontenden kor parallellt tills verifierad parity ar uppnadd. -- Flutter ska följa backend-kontraktet för hybrid alias-modell. -- Ingen klientspecifik speciallogik för matchning; klienten ska bara exponera tydliga val för scope vid manuell korrigering. -- Målet är färre felträffar mellan användare och bättre precision i personliga kvittoflöden. +## Relaterade dokument -## Beslut 2026-04-22 - User-scope för pantry och matplan - -- Pantry och matplan ska vara per användare, inte globala. -- Detta kräver backend-ändringar i `recipe-api` innan Flutter kan nå full parity för dessa flöden. -- Flutter ska följa de nya kontrakten när de finns på plats, utan klientspecifik speciallogik. - -## Malbild för v1 (funktionell parity) - -För v1 ska dessa flöden vara stabila i Flutter: -- [x] Auth: login, session, logout, auth-guard. -- [x] Recept: lista, detalj, skapa, uppdatera, ta bort. -- [x] Inventarie: lista, skapa, uppdatera, konsumera, historik. -- [x] Matplan: veckovy, val av recept per dag, portionsjustering, inköpslista, inventariejämförelse. -- [x] Import: quick-import + parse-markdown-flöde. -- [x] Produktadmin: lista, sök, sortera, filtrera, AI-kategorisering, merge, restore, inline kategori. -- [x] Användaradmin: lista, premium, e-post, skapa, ta bort, återställ lösenord. - -## Arbetsordning för produktion - -### Fas 1: Kritiska funktioner och buggfixar -- **Mål:** Säkerställa att alla kärnfunktioner är stabila och buggfria. - -- **Åtgärder:** - - [x] **Kvittoimport (OCR, bulk-spara) — KLAR 2026-05-01:** - - [x] Granskningssteg med checkbox, redigering och destination-väljare. - - [x] Bulk-spara till inventarie (ny/merge) eller baslager (ny/hoppa-över). - - [x] `file_picker: ^8.0.0` integrerat för filval på Flutter Web. - - - [ ] **UI/UX-förbättringar för adminpaneler:** - - [ ] Lägg till tydlig placeholder-text i sökfältet. - - [ ] Gör filtreringsalternativen mer visuellt tydliga. - - [ ] Lägg till bekräftelsedialog för bulk-åtgärder. - - [ ] Förbättra laddningsindikatorn för AI-kategorisering. - - - [ ] **Receptvy:** - - [ ] Lägg till tydlig växlingsknapp för grid- och listvy. - - [ ] Implementera sorteringsalternativ. - - [ ] Förbättra det tomma tillståndet med en tydlig CTA. - - - [ ] **Receptdetaljvy:** - - [ ] Lägg till stöd för att visa receptbilder i större format. - - [ ] Gör ingredienslistan mer läsbar. - - - [ ] **Gemensamma UI-komponenter:** - - [ ] Förbättra felmeddelanden med tydliga instruktioner. - - [ ] Använd en visuellt tilltalande laddningsindikator. - - - [ ] **Allmänt:** - - [ ] Säkerställa tillgänglighet med tydliga `tooltip`-texter och tillräcklig kontrast. - - [ ] Lägg till bekräftelsemeddelanden efter åtgärder. - -### Fas 2: Förbättra konverteringsvägen och onboarding -- **Mål:** Säkerställa att användare snabbt får värde och förstår appens fördelar. - -- **Åtgärder:** - - **CTA (Call-to-Action):** - - [ ] Skapa tydliga och lockande CTAs som "Se vad du kan laga med det du har hemma." - - [ ] Placera CTAs strategiskt i appen för att maximera synlighet. - - - **Förenkla onboarding:** - - [ ] Implementera en gästinloggning eller demo-läge så att användare kan prova appen utan att registrera sig direkt. - - [ ] Minska antalet obligatoriska fält vid registrering och implementera sociala inloggningar (t.ex. Google, Facebook). - - [ ] Skapa en kort välkomstguide för nya användare som visar de viktigaste funktionerna. - - [ ] Använd pop-up-tips eller tooltips för att visa hur man använder olika funktioner. - - - **Snabb start med exempeldata:** - - [ ] Låt användare börja med förifyllt exempeldata, t.ex. en standardinköpslista eller vanliga ingredienser. - - [ ] Lägg till en "Snabbstart"-knapp som automatiskt fyller i exempeldata och visar receptförslag. - - - **Fokusera på "Aha!"-momentet:** - - [ ] Visa omedelbara receptförslag när användaren lägger till sina första ingredienser. - - [ ] Generera en automatisk inköpslista baserad på de recept användaren väljer. - - - **Tydliga instruktioner och feedback:** - - [ ] Visa tydliga instruktioner för varje steg i onboarding-processen. - - [ ] Ge omedelbar feedback när användaren utfört en åtgärd. - - - **Användarvänlig design:** - - [ ] Håll gränssnittet enkelt och fokuserat på kärnfunktioner. - - [ ] Visa endast de viktigaste funktionerna för nya användare. - - - **Möjlighet att hoppa över onboarding:** - - [ ] Lägg till en knapp som låter användare hoppa över onboarding och börja använda appen direkt. - -### Fas 3: Testa och iterera -- **Mål:** Identifiera friktion och förbättra konverteringsvägen. - -- **Åtgärder:** - - [ ] Gå igenom appen som en ny användare för att identifiera eventuella problem. - - [ ] A/B-testa olika CTAs och onboarding-flöden för att se vad som fungerar bäst. - - [ ] Implementera analytik för att spåra var användare hoppar av och varför. - -### Fas 4: Anpassa till målgruppen -- **Mål:** Se till att marknadsföring och CTAs talar direkt till målgruppen. - -- **Åtgärder:** - - [ ] Anpassa marknadsföring och CTAs till målgruppen (t.ex. familjer, matintresserade, meal preppers). - - [ ] Var tydlig med appens värdeproposition, t.ex. "Slipp slösa mat – vi visar vad du kan laga med det du har hemma." - -### 3. Avancerade adminfunktioner -- [ ] Implementera "Visa endast ändrade rader" i produktadmin. -- [ ] Säkerställa att AI-integration för kategorisering är robust. - -### 4. Dokumentation och testning -- [ ] Uppdatera `README.md` med senaste ändringar. -- [ ] Lägg till testfall för nya funktioner. -- [ ] Validera med `flutter analyze` och fixa eventuella varningar. - -### 5. Övrigt -- [ ] Säkerställa att alla containrar är uppdaterade för robust bildhantering. - -## Prioriterad plan (ordning) - -## Fas 0 - Backend-förarbete för user-scope (KLAR 2026-04-22) -- [x] Gör `PantryItem` user-scopad (userId + productId unik per användare). -- [x] Gör matplan user-scopad och filtrera list/upsert/delete per inloggad användare. -- [x] Uppdatera matplanens inventory-jämförelse till användarspecifikt pantry. -- [x] Publicera uppdaterade API-kontrakt innan vidare Flutter-parity för matplan/baslager. -- [x] Migration 20260422130000_user_scope_pantry_meal_plan applicerad. - -## Fas 1 - Stabil app-shell (KLAR 2026-04-22) -- [x] Bygg tydlig auth-gate i router. -- [x] Centralisera API-fel (401/403/500) i ett gemensamt lager (`mapErrorToUserMessage`). -- [x] Skapa gemensamma UI-komponenter för loading, empty, error. -- [x] Sätt en enhetlig navigationsstruktur (web först, mobil-redo). -- [x] Lokalisering: ARB-infrastruktur på plats (`flutter_localizations`, `l10n.yaml`, `app_sv.arb`, `synthetic-package: false`, `flutter gen-l10n` i Dockerfile). -- [x] Regressionstest för svenska strängkvalitet tillagd. - -## Fas 2 - Auth parity (KLAR 2026-04-22) -- [x] Hårdna loginflödet (tydliga felmeddelanden, retries där relevant). -- [x] Verifiera token-livscykel (reload/hard refresh/logout). -- [x] Implementera automatisk hantering av utgången token (401 -> logout -> login). - -## Fas 3 - Recept parity (KLAR 2026-04-22) -- [x] Lista -> detalj -> skapa -> redigera -> ta bort. -- [x] Knyt ihop med parse-markdown-proxy. -- [x] Behåll backend som enda plats för matchning, validering och affärslogik. - -## Fas 4 - Inventarie parity (KLAR 2026-04-22) -- [x] Lista med filter/sortering (plats + sort via Riverpod-querystate). -- [x] Skapa och uppdatera inventariepost. -- [x] Konsumtion och konsumtionshistorik. - -## Fas 5 - Matplan parity (KLAR 2026-04-22) -- [x] Veckovy med receptval per dag mot user-scopat `GET /api/meal-plan?from=&to=`. -- [x] Portionsjustering per dag. -- [x] Inköpslista och inventariejämförelse mot användarens pantry. - -## Fas 6 - Import parity - -### 6a — Recept-import -- [x] URL via JSON-body `{ input: string }`. -- [x] Svar: `{ markdown: string, source: 'ica'|'pdf'|'image'|'other', imageUrl?: string }`. -- [x] På lyckat resultat: navigera till `/recipes/create` med markdown-texten förifylld. - -### 6b — Kvittoimport (KLAR 2026-05-01) -- [x] Endpoint: `POST /api/receipt-import` -- [x] Läge: filuppladdning, `multipart/form-data`, fält `file`, max 15 MB. -- [x] Svar: `ParsedReceiptItem[]` med fälten `rawName`, `quantity`, `unit`, `suggestedProductId?`, `suggestedProductName?`, `categorySuggestion?`. -- [x] Granskningssteg: checkboxlista med per-rad redigering (produkt, antal, enhet, destination). -- [x] Destination per rad: **Inventarie** eller **Baslager** via SegmentedButton i redigeringsdialogen. -- [x] Inventarie: ny post skapas, eller befintlig post slås ihop (PATCH quantity) med merge-förhandsvisning. -- [x] Baslager: produkt läggs till om den inte redan finns, annars hoppas den över. -- [x] AI-kategorisuggestion visas som chip (grön, `AI: kategori`) för premium-användare. -- [x] Snackbar med separat räkning: skapade/sammanslagna i inventarie + tillagda/redan-i-baslager. - -## UI/UX-förbättringar (KLAR 2026-04-22) -- [x] Produktval med bottenark (ProductPickerField) i inventarie/pantry. -- [x] Swipe-för-±1 på inventarielistan (SwipeableInventoryTile med visuell ledtråd). - -## Prioriterad plan (ordning) - -## Fas 0 - Backend-forarbete for user-scope (KLAR 2026-04-22) -- [x] Gor `PantryItem` user-scopad (userId + productId unik per anvandare). -- [x] Gor matplan user-scopad och filtrera list/upsert/delete per inloggad anvandare. -- [x] Uppdatera matplanens inventory-jamforelse till anvandarspecifikt pantry. -- [x] Publicera uppdaterade API-kontrakt innan vidare Flutter-parity for matplan/baslager. -- [x] Migration 20260422130000_user_scope_pantry_meal_plan applicerad. - -## Fas 1 - Stabil app-shell (KLAR 2026-04-22) -- [x] Bygg tydlig auth-gate i router. -- [x] Centralisera API-fel (401/403/500) i ett gemensamt lager (`mapErrorToUserMessage`). -- [x] Skapa gemensamma UI-komponenter for loading, empty, error. -- [x] Satt en enhetlig navigationsstruktur (web forst, mobil-redo). -- [x] Lokalisering: ARB-infrastruktur pa plats (`flutter_localizations`, `l10n.yaml`, `app_sv.arb`, `synthetic-package: false`, `flutter gen-l10n` i Dockerfile). -- [x] Regressionstest for svenska strangkvalitet tillagd. - -## Fas 2 - Auth parity (KLAR 2026-04-22) -- [x] Hardna loginflodet (tydliga felmeddelanden, retries dar relevant). -- [x] Verifiera token-livscykel (reload/hard refresh/logout). -- [x] Implementera automatisk hantering av utgangen token (401 -> logout -> login). - -## Fas 3 - Recept parity (KLAR 2026-04-22) -- [x] Lista -> detalj -> skapa -> redigera -> ta bort. -- [x] Knyt ihop med parse-markdown-proxy. -- [x] Behall backend som enda plats for matchning, validering och affarslogik. - -## Fas 4 - Inventarie parity (KLAR 2026-04-22) -- [x] Lista med filter/sortering (plats + sort via Riverpod-querystate). -- [x] Skapa och uppdatera inventariepost. -- [x] Konsumtion och konsumtionshistorik. - -## Fas 5 - Matplan parity (KLAR 2026-04-22) -- [x] Veckovy med receptval per dag mot user-scopat `GET /api/meal-plan?from=&to=`. -- [x] Portionsjustering per dag. -- [x] Inkoplista och inventariejamforelse mot anvandarens pantry. - -## UI/UX-förbättringar (KLAR 2026-04-22) -- [x] Produktval med bottenark (ProductPickerField) i inventarie/pantry. -- [x] Swipe-för-±1 på inventarielistan (SwipeableInventoryTile med visuell ledtråd). - -## Fas 6 - Import parity - -### Analys (2026-04-22) - -#### 6a — Recept-import - (2) URL via JSON-body `{ input: string }`. -- Svar: `{ markdown: string, source: 'ica'|'pdf'|'image'|'other', imageUrl?: string }`. -- På lyckat resultat: navigera till `/recipes/create` med markdown-texten förifylld. - -- Endpoint: `POST /api/receipt-import` -- Läge: filuppladdning, `multipart/form-data`, fält `file`, max 15 MB, -- Svar: `ParsedReceiptItem[]` med fälten `rawName`, `quantity`, `unit`, - `suggestedProductId?`, `suggestedProductName?`, `categorySuggestion?`. -- På lyckat resultat: granskningssteg där användaren bekräftar/skippar rader -- Komplexitetsgrad: hög — granskningsvyn är det tyngsta steget. - -**Nytt paket som krävs:** -- `file_picker: ^8.0.0` — hanterar filval på Flutter web (ger `Uint8List bytes`, - ingen filsökväg). Läggs till i `pubspec.yaml`. - -**Fil-/mappstruktur:** -``` -flutter/lib/features/import/ - domain/ - quick_import_result.dart # { markdown, source, imageUrl? } - parsed_receipt_item.dart # { rawName, quantity, unit, ... } - data/ - import_repository.dart # API-anrop (multipart + JSON URL-läge) - import_providers.dart # Riverpod-providers - presentation/ - import_screen.dart # TabBar: "Recept" | "Kvitto" - recipe_import_tab.dart # Fas 6a — fil + URL, laddningsindikator - -**Router och shell:** -- Ny route `/import` inuti `ShellRoute` i `app_router.dart`. - placeras efter "Baslager" och innan "Profil". -- Multipart-uppladdning kan ta 5–30 s (OCR, LLM) — `LinearProgressIndicator` - med text "Tolkar…" under hela anropet, inte en vanlig spinner. -- Timeout via `http`-klienten: sätt `Duration(seconds: 120)` för import-anrop. -- Nätverks- och serverfel mappas via befintlig `mapErrorToUserMessage`. - -**Genomförandeordning:** -1. Lägg till `file_picker` i `pubspec.yaml`. -2. Utöka `CreateRecipeScreen` med `initialMarkdown`-parameter + GoRouter extra-stöd. -3. Bygg `domain/` + `data/` (modeller, repository, providers). -4. Bygg `recipe_import_tab.dart` (fas 6a — enklare). -- [x] Registrera `/import` i router och lägg till nav-destination i AppShell. -- [ ] Verifiera recept-import end-to-end (fil + URL → create-screen). -- [ ] Bygg `presentation/receipt_import_tab.dart` (uppladdning + granskningssteg). -- Adminfunktioner migreras sist for att minimera risk i karnfloden. - -1. Verifiera request/response mot befintligt backendkontrakt. -3. Kontrollera felbanor innan UI-polish. - -Ingen ad-hoc backendforandring goras for att "fa Flutter att funka". -Backend-andringar for user-scope i pantry/matplan ar explicit beslutade och ska goras kontrollerat forst. - -## Kvalitetsgrind (Definition of Done) - -En feature ar klar nar allt nedan ar uppfyllt: -2. Auth/rollskydd fungerar (inklusive 401/403). -3. Loading/empty/error ar konsekvent hanterat. -4. Navigation in/ut ur feature fungerar utan specialfall. -5. Smoke-test i testmiljo ar godkant. - -## Leveransmodell - -- Leverera 1 feature i taget till testdoman. -- Demo och snabb feedback innan nasta feature. -- Hall dubbel drift (Next + Flutter) tills karnfloden ar stabila. -- Flytta trafik gradvis nar parity ar verifierad. - - -## Nästa konkreta sprint (rekommenderad) - -1. Fas 6: Import parity (URL/PDF/bild, robust felhantering). -2. Fas 7: Profil/admin parity. -3. Fortsatt flytt av UI-strängar till ARB (inventarie, pantry, recept). -4. Smoke-test på testdomän och avstämning. - -## Tumregel - -- Sikta pa funktionell parity forst. -- Pixel-perfect parity tas efter stabil funktion. - -## Utförda förbättringar och nästa steg (2026-04-24) - -- Navigationslänkar har lagts till mellan recept, inventarie, baslager och matplan för att förenkla användarflödet. -- Efter redigering av recept och konsumtion av inventariepost sker nu automatisk navigering till relevant vy. -- Efter import av recept sker automatisk navigering till receptlistan. -- Receptdetaljvyn har fått förbättrad bakgrundsbildshantering och mjukare scrollning. -- Kodbasen har granskats för att säkerställa att inga absoluta Windows-sökvägar används. - -**Nästa steg:** -- Fortsatt användartestning av nya navigationsflöden och insamling av feedback. -- Finslipa UI och tillgänglighet i samband med de nya navigationsmöjligheterna. -- Färdigställ kvittoimport och adminfunktioner enligt plan. -- Lägg till snabbfilter i Produkt-admin: "Visa endast ändrade rader" för inline-kategoribyten (planerad förbättring till nästa pass). - -# Nästa steg: Flutter-migrering - -Relaterade dokument: -- [README.md](README.md) -- [teknisk_beskrivning_flutter.md](teknisk_beskrivning_flutter.md) - -## Mål och prioriteringar för produktion - -### Övergripande mål -- **Funktionell parity:** Säkerställa att alla kärnfunktioner är stabila och fungerar som förväntat. -- **Användarupplevelse:** Förenkla onboarding och säkerställa att användare snabbt förstår appens värde. -- **Produktionsklar:** Säkerställa att appen är redo för lansering genom att adressera kritiska buggar och förbättra prestanda. - -### Icke-förhandlingsbara ramar - -1. Inget ska tas bort eller ändras i `recipe-api` utom explicit beslutade backend-ändringar för användarscope i pantry och matplan. -2. Inget ska tas bort eller ändras i `recipe-frontend`. -3. Migreringen sker i Flutter-spåret som separat klient mot befintliga API-kontrakt. -4. Next-frontend körs parallellt tills Flutter har verifierad parity i kärnflöden. - -## Arbetsplan - -### Pågående arbete -- **Kvittoimport (Fas 6b):** ✅ Klar (2026-05-01) — granskningssteg, destination-väljare, merge och spara klart. -- **Bildimport:** Säkerställa att containrar är uppdaterade med senaste kod och att diagnostikloggar syns vid felsökning. -- **Adminfunktioner:** Avancerad AI-integration och ytterligare adminfunktioner planeras men är ej migrerade. - -### Prioriterade nästa steg -1. ~~Slutför kvittoimport och bulk-spara.~~ ✅ Klart (2026-05-01) -2. Säkerställa robust bildimport och diagnostik. -3. Implementera avancerad AI-integration för produktkategorisering. -4. Utöka adminfunktioner för användarhantering och produktadministration. -5. Förbättra UI/UX för användarflöden, inklusive onboarding och profilhantering. - -## Plan för Implementering av Fas 6b - -### 1. Slutför Kvittoimport -- **Aktiviteter:** - - Implementera parsers för kvitton (PDF, bildbaserade kvitton). - - Utveckla gränssnitt för att granska importerade kvitton. - - Implementera bulk-spara-funktionalitet för kvitton. - -- **Tekniska Detaljer:** - - Använd `pdf-parse` och `tesseract.js` för att extrahera data från kvitton. - - Säkerställa att API-endpoints (`/receipt-import`) hanterar filuppladdning och returnerar strukturerad data. - -### 2. Förbättra Bildhantering -- **Aktiviteter:** - - Säkerställa att `downloadAndOptimizeImage` fungerar korrekt i Docker-miljön. - - Implementera robust felhantering och diagnostikloggning för bildimport. - -- **Tekniska Detaljer:** - - Använd miljövariabler för att definiera sökvägar för bildlagring. - - Säkerställa att bilder optimeras och lagras korrekt på servern. - -### 3. Säkerställa Kompatibilitet med Linux/Ubuntu -- **Aktiviteter:** - - Kontrollera att alla sökvägar är relativa eller konfigurerbara via miljövariabler. - - Säkerställa att Docker-miljön är korrekt konfigurerad för att köra på Ubuntu. - -- **Tekniska Detaljer:** - - Använd `path.join()` för att bygga sökvägar på ett plattformsoberoende sätt. - - Säkerställa att `IMAGE_DEST_DIR` är korrekt konfigurerad för Linux/Ubuntu. - -### 4. Förbättra API-Integration -- **Aktiviteter:** - - Säkerställa att API-endpoints har korrekt felhantering och tidsgränser. - - Implementera robusta tidsgränser och återförsöksmekanismer för API-anrop. - -- **Tekniska Detaljer:** - - Använd `http.Client` med korrekta tidsgränser för API-anrop. - - Implementera återförsöksmekanismer för tillfälliga fel. - -## Verifiering och Testning - -### 1. Enhets- och Integrationstester -- **Aktiviteter:** - - Skapa enhets- och integrationstester för nya parsers och API-endpoints. - - Säkerställa att alla tester körs i Docker-miljön. - -- **Tekniska Detaljer:** - - Använd `flutter test` för att köra enhetstester. - - Använd `jest` eller `supertest` för att testa API-endpoints. - -### 2. Manuell Testning -- **Aktiviteter:** - - Manuell testning av kvittoimport och bulk-spara-funktionalitet. - - Säkerställa att bildhantering fungerar korrekt i Docker-miljön. - -- **Tekniska Detaljer:** - - Använd Postman eller liknande verktyg för att testa API-endpoints. - - Säkerställa att gränssnittet för kvittoimport fungerar som förväntat. - -## Slutsats -För att slutföra Fas 6b krävs implementering av parsers för kvitton, förbättringar av bildhantering, och säkerställande av kompatibilitet med Linux/Ubuntu. En robust API-integration och omfattande testning är avgörande för att säkerställa att importfunktionen fungerar som förväntat i produktion. \ No newline at end of file +- `README.md` - anvandarperspektiv. +- `teknisk_beskrivning_flutter.md` - teknisk referens. +- `../NEXT_STEPS.md` - overgripande roadmap for hela produkten. diff --git a/flutter/teknisk_beskrivning_flutter.md b/flutter/teknisk_beskrivning_flutter.md index 7b904008..d605bdf7 100644 --- a/flutter/teknisk_beskrivning_flutter.md +++ b/flutter/teknisk_beskrivning_flutter.md @@ -1,456 +1,78 @@ # Teknisk Beskrivning - Flutter Frontend -Viktigt att komma ihåg vid implementering av nya funktioner och kodning är att inte använda Windows-sökvägar. Använd inte `c:/dev/recipe-app/...` eftersom bygg- och testmiljön är på en remote Ubuntu-server. Utveckling sker lokalt och test samt drift sker på remote server. Säkerställ att inga absoluta Windows-sökvägar används i koden, för att stödja bygg och drift på Linux/Ubuntu. +Detta dokument ar teknisk referens for systemadministratorer och programmerare. +Mallet ar en sammanhallen teknisk sanning utan duplicerade roadmap- eller anvandarsektioner. -## Senaste ändringar (2026-05-01, session 3) +## Dokumentstatus (2026-05-03) -### Separering av AI-chip och produktsuggestions-chip +- Fokus: arkitektur, drift och kanda gotchas. +- User guide finns i `README.md`. +- Planering finns i `next_steps_flutter.md`. -**Problem:** AI-chipet visade felaktigt produktnamnsförslag som om de vore kategoriförslag, vilket skapade förvirring när användaren såg "AI-förslag: Dryck Multivitamin" (ett produktnamn) istället för en kategori. +## Viktigt om miljo -**Lösning:** -- **Blå chip** "Förslag: [produktnamn]" — när systemet hittat en trolig produkt via ordmatchning (inga AI-anrop inblandade). Klick väljer produkten. -- **Grön chip** "AI-kategori: [kategoriväg]" — när AI:n föreslagit en kategori från databasen. Klick öppnar produktpickern filtrerad på den kategorin. +Anvand inte absoluta Windows-sokvagar i kod eller scripts. +Bygg och drift sker pa Linux/Ubuntu i containeriserad miljo. -**Kodändringar:** -- `aiLabel` beräknas enbart från `categorySuggestionName`/`categorySuggestionPath` (kategoriförslag). -- Nytt fält `suggestedProductLabel` för produktsuggestions-chip. -- Separata villkor och UI-block för de två chipen i `_EditDialogState.build()`. +## Senaste tekniska tillagg -### Produktnamns-normalisering - -**Problem:** Kvittonamn i VERSALER (t.ex. "APRIKOSMARMELAD 284G") såg oprofessionella ut i UI:n. - -**Lösning:** Ny funktion `_normalizeProductName()` som tillämpar smarta regler: -- Token med `/` (förkortningar) lämnas i versaler: `KY/KAL/LE/TO` -- Token som börjar med siffra (mängd/storlek) görs till gemener: `284G` → `284g`, `12X85G` → `12x85g` -- Övriga token: första bokstav versal, resten gemen: `APRIKOSMARMELAD` → `Aprikosmarmelad`, `JUICE TROPISK` → `Juice Tropisk` - -**Implementering:** -- Top-level-funktion i `receipt_import_tab.dart` -- Tillämpas när "Ny produkt"-fältet prefylls: `_newProductNameCtrl.text = _normalizeProductName(widget.current.productName ?? widget.item.rawName)` - -### AI-kategorisering — validering i backend - -**Problem:** Användaren rapporterade att AI föreslog kategorin "Dryck Multivitamin", som inte fanns i databasen. - -**Undersökning:** -- Backend-AI:n (`ai.service.ts`) validerar redan att `categoryId` finns i `categories`-listan och faller tillbaka på "Övrigt" om inte. -- Problemet var att frontend visade produktnamnsförslag som om de vore kategoriförslag. - -**Lösning:** -- Separering av chipen (se ovan) gör det tydligt att AI-kategoriförslag alltid kommer från databasen. - ---- - -## Senaste ändringar (2026-05-01, session 2) - -### Tvåstegs-picker: Kategori → Produkt - -Problembeskrivning: AI:n kan föreslå en kategori men produktpickern sökte bara på produktnamn, vilket gav nollresultat när kategorinamnet matades in som söktext. Lösningen är ett nytt separat arbetsflöde för produktval via kategoriträdet. - -**Ny widget: `lib/core/ui/category_then_product_picker.dart`** - -`CategoryThenProductPicker.show()` är en statisk metod som orkestrerar hela flödet: - -1. **Steg 1 — Välj kategori:** Öppnar ett bottenark (`_CategoryPickerSheet`) med hela kategoriträdet (L1 → L2 → L3). Trädet är sökbart — sökfältet filtrerar till matchande lövnoder och visar hela sökvägen som brödsmula (t.ex. *Mat > Frukt & Grönt > Äpplen*). -2. **Steg 2 — Välj produkt:** Öppnar `ProductPickerField.showSheet()` filtrerad på alla produkter som tillhör den valda kategorin **eller någon av dess ättlingar** (L1 samlar alltså in L2- och L3-produkter rekursivt via `_collectIds()`). - -**Inbyggt AI-stöd:** Om `preselectedCategoryId` skickas in (från AI-förslaget) hoppar `show()` direkt till steg 2 — kategoriträdet visas aldrig. Om kategorin inte hittas i trädet faller den tillbaka till att visa trädet. - -**Fallback för L1/L2-noder:** Mellanliggande noder (L1, L2) som inte är löv har en liten "Välj"-knapp till höger i raden. Klick på kategorinamnet/pilen expanderar/kollapsar som vanligt; klick på "Välj" väljer kategorin och öppnar produktpickern direkt. - -**Trädknapp i redigeringsdialogen:** Bredvid det vanliga produktsökfältet finns nu en `OutlinedButton` med trädikon (🌳). Klick öppnar tvåstegs-pickern utan AI-förval. - -### Skapa ny privat produkt i importflödet - -Om inget i produktlistan matchar kvittoradens vara kan användaren skapa en egen produkt direkt från produktpickern. - -**Flöde:** -1. Välj kategori (via trädet eller AI-direkthopp). -2. Produktpickern visas med en **"Skapa ny"**-knapp i rubrikraden. -3. En enkel dialog öppnas med ett namnfält (förfyllt med söksträngen om sådan finns). -4. Vid bekräftelse anropas `POST /products/private` — produkten skapas som privat och user-scopad. -5. Den nya produkten läggs till i den lokala produktlistan och väljs direkt. - -**Privata produkter — arkitektur:** - -| | Globala produkter | Privata produkter | -|---|---|---| -| Endpoint (hämta) | `GET /products` | `GET /products/mine` | -| Endpoint (skapa) | `POST /products` (admin) | `POST /products/private` (alla inloggade) | -| Synlighet | Alla användare | Bara ägaren | -| `isPrivate` | `false` | `true` | -| `normalizedName` | `normalize(name)` | `private:{userId}:{normalize(name)}` | -| Kategori | Global (admin-only) | Väljs vid skapandet, global kategori | - -Importfliken laddar globala och privata produkter parallellt via `Future.wait` och slår ihop dem till en gemensam `_products`-lista. Den lokala `_localProducts`-listan i `_EditDialogState` utökas om en ny produkt skapas under dialogen, utan att en ny nätverksanrop krävs. - -### Redigeringsdialog — sammanfattning av alla fält - -`_EditDialog` i `receipt_import_tab.dart` innehåller nu: -- **AI-chip (grön):** Klickbar. Om AI föreslog en matchad produkt direkt → väljer den. Om AI föreslog en kategori → öppnar produktpickern filtrerad på den kategorin (utan att visa trädet). -- **Destinationsväljare:** `SegmentedButton` — Inventarie eller Baslager. -- **Produktfält + trädknapp:** `ProductPickerField` (fritext-sökning) + knapp för att öppna tvåstegs-picker. -- **Antal/Enhet:** Visas bara vid Inventarie-destination. - -### Designregel bekräftad: User-scope - -User-scope-principen dokumenterades formellt i båda tekniska beskrivningarna (2026-05-01). Privata produkter är det första exemplet på mönstret för resurser som är varken globala (alla ser dem) eller fullt user-owned (bara ägaren ser dem): -- `Product.isPrivate = true` + `Product.ownerId = userId` -- `normalizedName`-prefix undviker databaskollision med globala produkter -- Migration: `20260501000000_add_product_is_private - -## Senaste ändringar (2026-05-01, session 1) - -**Kvittoimport Fas 6b — komplett:** -- Granskningssteg i `receipt_import_tab.dart` med per-rad checkbox, redigeringsdialog och destinationsväljare. -- Destinationsväljare: **Inventarie** eller **Baslager** via `SegmentedButton<_Destination>` i redigeringsdialogen. -- Vid vald destination **Baslager** dolt antal/enhet-fält med informationstext. -- Inventarie-flöde: skapar ny post eller slår ihop (PATCH quantity) med befintlig post. Förhandsvisning av ny mängd visas i listan. -- Baslager-flöde: lägger till produkten om den inte redan finns. Befintliga baslagerprodukter visas med orange chip. -- Snackbar visar separat räkning: skapade/sammanslagna i inventarie + tillagda/hoppa-över i baslager. -- `_loadInventory()` laddar nu inventarie och baslager i parallell via `Future.wait`. -- AI-kategorisuggestion chip (grön) visas för premium-användare i granskningslistan. - -## Senaste ändringar (2026-04-25) - -**Arkitektur- och UX-förbättringar:** -- Grid-vy för recept: Kolumnval (2/4/6/8) via ikon i AppShell, med Riverpod-provider och SharedPreferences. -- RecipesScreen är nu body-only, ingen egen Scaffold/AppBar. -- AppShell visar grid-ikon endast på /recipes. -- Buggfix: Produktväljaren i pantry/inventarie (ProductPickerField) — bottenark implementeras. -- Kodkvalitet: Inga absoluta Windows-sökvägar. - -**Tekniska förbättringar:** -- Förbättrad bildhantering med normalisering av URL:er, fallback och diagnostikloggning. -- Robustare importflöde för recept med stöd för PDF, bild och ICA-länkar. -- User-scope för pantry och matplan: Alla baslager- och matplansdata är nu per användare. - -## Syfte och mål -- Isolerad Flutter-baserad frontend i separat Docker-service. -- Web först, men med arkitektur som kan återanvändas för Android/iOS. -- Stegvis migrering av funktioner från befintlig Next.js-frontend. +- Sessionpersistens i klienten for pagande kvittoimport. +- Forbattrad inferens for antal/forpackning (inklusive uttryck som `2st`). +- Tydlig separation i UI mellan AI-kategoriforslag och produktforslag. +- Ingen server-side persistens introducerad for kvittosession. ## Arkitektur ### Lager -- **Presentation:** Skärmar 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`. +- Presentation: `flutter/lib/features/*/presentation` +- State/Application: Riverpod providers/notifiers i `flutter/lib/features/*/data` +- Data/API: `flutter/lib/core/api` +- Platform abstraction: token storage i `flutter/lib/core/platform` ### Routing -- GoRouter i [flutter/lib/core/router/app_router.dart](flutter/lib/core/router/app_router.dart). -- Nuvarande routes: - - `/login` — loginskärm - - `/recipes` — receptlista (ShellRoute med AppShell) - - `/recipes/create` — nytt recept, utanför ShellRoute - - `/recipes/:id` — receptdetalj, utanför ShellRoute - - `/recipes/:id/edit` — redigera recept, utanför ShellRoute - - `/profile` — profil (ShellRoute med AppShell) -- `/recipes/create` måste vara listad före `/recipes/:id` i routelistan för att undvika konflikt. -- Detaljsidor (detalj, skapa, redigera) ligger utanför ShellRoute för att få full-screen med automatisk back-knapp. +- GoRouter i `flutter/lib/core/router/app_router.dart` +- ShellRoute for huvudnavigation +- Fullscreen-routes for skapa/redigera/detalj ### Auth -- Login endpoint: `POST /api/auth/login`. +- Login via `POST /api/auth/login` +- Token-falt: `accessToken` +- Auth-gate i router med redirect logik +- `guardedApiCall()` hanterar logout vid 401 -## Kända fallgropar och API-gotchas +## API- och kontraktsprinciper -### Designregel: User-scope vid ny funktionalitet +- Flutter foljer backend-kontrakt, ingen lokal speciallogik for matchning. +- 2xx-svar accepteras generellt i importanrop (inte hardkodning till enbart 200). +- Kvittoimport och receptimport ar separata floden med olika svarstyper. -> **Regel:** Kontrollera alltid om ny data tillhör en specifik användare. Om ja — data **måste** ha user-scope i backend (`userId`-fält, filtrering i service) och Flutter-klienten får **inte** returnera/visa andra användares data. -> -> Resurser och deras scope: -> | Resurs | Scope | -> |---|---| -> | Produkter (globala) | Publik — `GET /products` | -> | Produkter (privata) | Per användare — `GET /products/mine`, `POST /products/private` | -> | Kategorier | Global (admin-only att skapa) | -> | Inventarie | Per användare — alltid filtrera på `userId` | -> | Baslager | Per användare — alltid filtrera på `userId` | -> | Matplan | Per användare — alltid filtrera på `userId` | -> | Recept | Per användare (ägare) eller delat | -> -> I Flutter: ladda user-scopad data med token, kombinera globala och egna produktlistor vid behov. +## Kvittoimport - tekniska noter -### Flutter Web och PDF MIME-typ -- Flutter Web skickar PDF-filer med MIME-typ `application/octet-stream` istället för `application/pdf`. -- Backend (`receipt-import.controller.ts`) måste tillåta båda: `application/pdf` och `application/octet-stream` i `ALLOWED_MIMES`. -- Symptom om detta saknas: HTTP 400 "Otillåten filtyp. Använd JPEG, PNG, WebP eller PDF." - -### NestJS @Post() returnerar HTTP 201 som standard -- NestJS returnerar 201 (Created) för alla `@Post()`-endpoints som standard. -- Flutter-klienten (`ImportRepository`) accepterar nu alla 2xx-svar (`statusCode < 200 || statusCode >= 300`). -- Alternativt: lägg till `@HttpCode(200)` på backend-controllern för att returnera 200. -- Detta gjordes i `receipt-import.controller.ts` (2026-04-30). - -### Kvittoimport — backend och arkitektur -- `/receipt-import` hanteras av en **dedikerad** `ReceiptImportController` och `ReceiptImportService`, **inte** av `QuickImportController`. -- `ReceiptImportService` använder **Mistral AI** för att parsa kvitton till strukturerade `ParsedReceiptItem[]` direkt — inget markdown. -- Svaret från `/receipt-import` är en array av `ParsedReceiptItem`, inte `{ markdown: "..." }`. -- `{ markdown: "..." }` är svaret från `/quick-import` (receptimport) — inte kvittoimport. - -## Övrigt -- **Kvittoimport (Fas 6b):** ✅ Klar (2026-05-01) — granskningssteg, destination-väljare, merge och spara till inventarie/baslager. -- **Bildimport:** Säkerställa att containrar är uppdaterade med senaste kod och att diagnostikloggar syns vid felsökning. -- **Adminfunktioner:** Avancerad AI-integration och ytterligare adminfunktioner planeras men är ej migrerade. - -## Syfte och mål -- Isolerad Flutter-baserad frontend i separat Docker-service. -- Web först, men med arkitektur som kan återanvändas för Android/iOS. -- Stegvis migrering av funktioner från befintlig Next.js-frontend. - -## Relaterade dokument -- [next_steps_flutter.md](next_steps_flutter.md) -- [README.md](README.md) -- [teknisk_beskrivning.md](../TEKNISK_BESKRIVNING.md) (för backend-kontext) - -## Arkitektur - -### Lager -- **Presentation:** Skärmar 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](flutter/lib/core/router/app_router.dart). -- Nuvarande routes: - - `/login` — loginskärm - - `/recipes` — receptlista (ShellRoute med AppShell) - - `/recipes/create` — nytt recept, utanför ShellRoute - - `/recipes/:id` — receptdetalj, utanför ShellRoute - - `/recipes/:id/edit` — redigera recept, utanför ShellRoute - - `/profile` — profil (ShellRoute med AppShell) -- `/recipes/create` måste vara listad före `/recipes/:id` i routelistan för att undvika konflikt. -- Detaljsidor (detalj, skapa, redigera) ligger utanför ShellRoute för att få full-screen med automatisk back-knapp. - -### Auth -- Login endpoint: `POST /api/auth/login`. -- Backend kontrakt använder `username` + `password`. -- Token-fält i svar: `accessToken`. -- Token lagras via `ITokenStorage` (web implementation med SharedPreferences). -- Auth-gate i router: utloggad användare redirectas till `/login`, inloggad redirectas från `/login` till `/recipes`. -- Splash-skärm (`/`) visas medan auth-state läses från 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`. -- Centraliserad HTTP-felklassning: 401 -> `ApiErrorType.unauthorized`, 403 -> `forbidden`, 5xx -> `server`, nätverksfel -> `network`. -- `ApiException` i `flutter/lib/core/api/api_exception.dart` är den enda feltypen som propageras från repositories. -- `mapErrorToUserMessage(error, context)` i `flutter/lib/core/api/api_error_mapper.dart` översätter fel till lokaliserade användarmeddelanden. Tar numera `BuildContext` som andra argument för att hämta korrekt språk från `AppLocalizations`. - -### Lokalisering -- Flutter `flutter_localizations` + `intl` tillagda i `pubspec.yaml` med `generate: true`. -- Konfigurationsfil: [flutter/l10n.yaml](flutter/l10n.yaml) med `synthetic-package: false`. -- Källsträngar i [flutter/lib/l10n/app_sv.arb](flutter/lib/l10n/app_sv.arb) och [flutter/lib/l10n/app_en.arb](flutter/lib/l10n/app_en.arb). -- Genererade filer hamnar i `flutter/lib/l10n/generated/` och checkas inte in. -- Hjälpare `context.l10n` i [flutter/lib/core/l10n/l10n.dart](flutter/lib/core/l10n/l10n.dart). -- `MaterialApp.router` konfigurerad med `localizationsDelegates`, `supportedLocales` och `locale: const Locale('sv')`. -- Dockerfilen kör `flutter gen-l10n` innan `flutter build web` för att generera Dart-koden i containerbygget. -- Regressionstest i [flutter/test/core/swedish_strings_regression_test.dart](flutter/test/core/swedish_strings_regression_test.dart) misslyckas om vanliga ASCII-varianter (Välj, Lägg, Försök, etc.) dyker upp igen i `lib/`. - -#### Användning av lokalisering -För att lägga till en ny lokaliserad sträng: -1. Lägg till nyckeln i `app_sv.arb` (och `app_en.arb`). -2. Kör `flutter gen-l10n` lokalt (eller låt Docker-bygget göra det). -3. Använd `context.l10n.dinNyckel` i widgetkoden. - -För felsträngar från API: använd alltid `mapErrorToUserMessage(error, context)` — lägg inte in hårdkodade strängar. - -## Vad som är gjort - -### Infrastruktur -- Ny compose override: [compose.flutter.yml](compose.flutter.yml). -- Ny Flutter-service: `recipe-flutter`. -- Service ansluten till nätverk: - - `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 går same-origin via `/api` och proxas internt till `recipe-api:8080`. - -### Inventarie (2026-04-22) -- Filtrering per plats (alla/kyl/frys/skåfferi) via `inventoryLocationFilterProvider`. -- Sortering (namn A-Ö, bäst före stigande/fallande) via `inventorySortFilterProvider`. -- Riverpod-query (`InventoryQuery`) skickar `location` och `sort` som queryparametrar till backenden. -- Alla felmeddelanden går via `mapErrorToUserMessage(error, context)`. - -### Baslager/Pantry (2026-04-22) -- Pantry-produkter grupperas nu på kategori utifrån backend-relationen `categoryRef` (rekursiv `parent`-kedja -> `categoryPath`), med fallback till legacy `product.category` och sist `Övrigt`. -- `PantryProduct` har `categoryId` och `categoryPath` som parsas från API-svaret. - -### Backend: User-scope för pantry och matplan (2026-04-22) -- `PantryItem` och `MealPlanEntry` är nu user-scopade i Prisma-schemat. -- `pantry`-controller/service filtrerar alltid per `userId` från JWT. -- `meal-plan`-controller/service filtrerar alltid per `userId`; `inventoryCompare` använder inloggad användares pantry. -- Migration: `20260422130000_user_scope_pantry_meal_plan` applicerad på server. -- Next.js-frontenden krävde inga funktionella ändringar (förfrågningar går 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](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) -- Flutter `flutter_localizations` + `intl` tillagda i `pubspec.yaml` med `generate: true`. -- Konfigurationsfil: [flutter/l10n.yaml](flutter/l10n.yaml) med `synthetic-package: false`. -- Kallstrangar i [flutter/lib/l10n/app_sv.arb](flutter/lib/l10n/app_sv.arb) och [flutter/lib/l10n/app_en.arb](flutter/lib/l10n/app_en.arb). -- Generade filer hamnar i `flutter/lib/l10n/generated/` och checkas inte in. -- Hjalpare `context.l10n` i [flutter/lib/core/l10n/l10n.dart](flutter/lib/core/l10n/l10n.dart). -- `MaterialApp.router` konfigurerad med `localizationsDelegates`, `supportedLocales` och `locale: const Locale('sv')`. -- Dockerfilen kor `flutter gen-l10n` innan `flutter build web` for att generera Dart-koden i containerbygget. -- Regressionstest i [flutter/test/core/swedish_strings_regression_test.dart](flutter/test/core/swedish_strings_regression_test.dart) failar om vanliga ASCII-varianter (Valj, Lagg, Forsok, etc.) dyker upp igen i `lib/`. - -#### 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. - -## Kända API-fallgropar (viktigt!) - -> **Regel:** Kontrollera alltid HTTP-metod i [TEKNISK_BESKRIVNING.md i /recipe-app] 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` | Använd PATCH | -| Uppdatera matplan | `POST /api/meal-plan` (upsert) | Ingen PUT/PATCH | - -Generell regel: NestJS-backenden använder `PATCH` för partiella uppdateringar, inte `PUT`. `PUT` exponeras inte på några resurser i detta projekt. +- Granskningsflode med radredigering och destination (inventarie/baslager). +- Produktval stoder tradbaserat kategori -> produkt-flode. +- AI-kategorihint ar endast ett forslag; slutanvandaren validerar i granskningssteget. ## 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 kommandomönster - -För att minska risken för fel startordning eller missförstånd mellan huvudappen och Flutter-spåret: - -**När huvudappen ska vara uppe:** -- `docker compose up -d recipe-db recipe-api recipe-frontend` - -**När Flutter-klienten ska vara uppe:** -- `docker compose -f compose.yml -f compose.flutter.yml up -d --no-deps recipe-flutter` - -**När både 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 ...` krävs alltid för att containern faktiskt ska starta. +### Bygg och start (Flutter) +```bash +docker compose -f compose.yml -f compose.flutter.yml build recipe-flutter +docker compose -f compose.yml -f compose.flutter.yml up -d --no-deps recipe-flutter +``` ### 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` +- Compose merge: `docker compose -f compose.yml -f compose.flutter.yml config` +- Reachability via proxy/Caddy +- Runtime-loggar for importfloden vid felsokning -## Viktiga beslut -- `compose.yml` lämnas orörd; Flutter ligger i separat override-fil. -- Flutter-web använder same-origin API (`/api`) för att undvika mixed-content. -- Intern Caddy i Flutter-container hanterar static hosting + `/api` proxy. -- Feature migration sker stegvis enligt [next_steps_flutter.md](next_steps_flutter.md). +## Kanda fallgropar -## Kända fallgropar -- Om `recipe-flutter` inte är i `proxy` nätverket blir det 502 från extern Caddy. -- Om webbläsaren visar gammal JS kan gamla API-URL:er leva kvar i cache/service worker. -- Login med e-post fungerar inte om backend förväntar sig användarnamn. -- `recipe-flutter` kan stoppas av `docker compose down --remove-orphans` om kommandot körs utan override-filen och Flutter-spåret tidigare varit uppe. -- En orphan-varning för `recipe-flutter` är normalt förväntad när man kör huvudappen med bara `compose.yml`; det betyder inte att backend eller Prisma är trasiga. +- PDF-mime kan komma som `application/octet-stream` i Flutter Web. +- Orphan-varning ar normal nar huvudstack och Flutter-stack kors separat. +- Cache/service worker kan visa gammal frontend efter deploy. -### Orphan-varning i praktiken +## Relaterade dokument -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 kör ett kommando som bara använder `compose.yml`. - -Detta är normalt och ofarligt så länge du vet vilken stack du avser att köra. - -Om `test.gynther.se` slutar svara efter städning med `--remove-orphans`, starta om Flutter-spåret med: - -- `docker compose -f compose.yml -f compose.flutter.yml up -d --no-deps recipe-flutter` - - ---- - -## Nyheter och förbättringar (2026-04-22) - -- **User-scope för pantry och matplan** — Flutter-klienten använder nu user-scopade endpoints för baslager och matplan. JWT används för filtrering i alla anrop. -- **Robust bildimport** — Bild-URL normaliseras och skickas hela vägen till UI. Flutter hanterar både markdown och bild-url vid import. -- **Importflöde** — Quick-import och receipt-import har förbättrats med robust multipart-hantering, timeout, och felhantering. Prefill av markdown och bild-url fungerar i Flutter. -- **Flutter-parity** — Matplan, inventarie, baslager och receptflöden är nu fullt migrerade till Flutter med user-scope och robust felhantering. -- **Felsökningslogg** — Se `../IMPORT_IMAGE_DEBUG_2026-04-22.md` för detaljerad felsökningshistorik kring bildimport och importflöde. - -### Kända begränsningar -- Kvittoimport (Fas 6b) är påbörjad men granskningssteg och bulk-spara återstår. -- Bildimport kräver att containrar är uppdaterade med senaste kod — kontrollera att diagnostikloggar syns vid felsökning. -- Vissa adminfunktioner och avancerad AI-integration är planerade men ej migrerade. - -## Nyheter och tekniska förbättringar (2026-04-24) - -- **Navigationsflöden:** - - Navigationslänkar har lagts till mellan recept, inventarie, baslager och matplan för att förbättra användarupplevelsen och minska antalet klick. - - Efter redigering av recept och konsumtion av inventariepost sker nu automatisk navigering till relevant vy. - - Efter import av recept sker automatisk navigering till receptlistan. -- **UX och UI:** - - Receptdetaljvyn har fått förbättrad bakgrundsbildshantering och mjukare scrollning. -- **Plattformsoberoende kod:** - - Genomgång av kodbasen för att säkerställa att inga absoluta Windows-sökvägar används, vilket gör projektet robust för Linux/Ubuntu-baserad bygg- och driftmiljö. - -Se även README.md och next_steps_flutter.md för mer detaljer om användarflöden och leveransplan. +- `README.md` - anvandarguide. +- `next_steps_flutter.md` - aktiv planering. +- `../TEKNISK_BESKRIVNING.md` - backend/systemovergripande teknik. diff --git a/migrering-MSI.md b/migrering-MSI.md index 91f741f7..714d5441 100644 --- a/migrering-MSI.md +++ b/migrering-MSI.md @@ -2,6 +2,17 @@ ## Status: ✅ GENOMFÖRD 2026-04-30 +## Dokumentstatus (2026-05-03) + +### Målgrupp +Detta dokument är för systemadministratörer och utvecklare som ansvarar för integrationen mellan recipe-app och microservice-importer. + +### Tillägg efter genomförd migrering +- Kvittoparsningens regelbaserade tolkning har förbättrats för multipack och enheter. +- Brödrelaterade kategoriregler och contradiction guards har utökats för högre träffsäkerhet. +- Klientens kvittosession i Flutter är nu persistent utan att ändra backendkontrakt eller införa serverlagring av sessionen. +- Kategoriträdet i seed-data har utökats med `Korvbröd` under `Fastfoodbröd`. + - **Scope:** quick-import, parse-markdown, receipt-import - **Arkitektur:** Backend-till-backend — recipe-app NestJS-backend anropar microservice-importer internt via HTTP. Frontend ändras inte. - **OCR:** Implementerat i microservice-importer (tesseract.js + Alpine apk-paket) diff --git a/produktlansering.md b/produktlansering.md index d44bc195..7c9dee00 100644 --- a/produktlansering.md +++ b/produktlansering.md @@ -1,68 +1,48 @@ -# Plan för produktlansering +# Plan for produktlansering -Denna plan bryter ner de viktigaste områdena som behöver åtgärdas för att ta Recipe App till produktionsredo lansering. Varje rubrik motsvarar en punkt i NEXT_STEPS.md och innehåller konkreta delmål och åtgärder. +Detta dokument ar en releasechecklista. +Det kompletterar `NEXT_STEPS.md` och ska inte duplicera backloggen. -## 1. Säkerhet & Data +## Dokumentstatus (2026-05-03) -- Kryptera känsliga användaruppgifter i databasen (t.ex. e-post, namn) med AES-256-GCM -- Inför rate limiting på API och AI-endpoints (t.ex. @nestjs/throttler) -- ✅ Lägg till säkerhetshuvuden (Helmet i backend, CSP i frontend) — **Klart 2026-04-21** - - Caddy: globala headers (HSTS, X-Frame-Options, CORP, COOP, COEP, Referrer-Policy, Permissions-Policy) - - Next.js: CSP via `next.config.js` med `headers()`-funktionen - - NestJS: Helmet konfigurerat i `main.ts` som backup (aktiveras vid nästa rebuild) - - Dokumenterat i TEKNISK_BESKRIVNING.md under "Säkerhetshuvuden" -- Se över hantering av miljövariabler och secrets (ingen hårdkodning) -- Kontrollera och dokumentera rollhantering och accesskontroller +- Malgrupp: produktagare, systemadministratorer, utvecklingsteam. +- Fokus: vad som maste vara verifierat innan release. -### Steg-för-steg: -1. Identifiera alla fält som ska krypteras och implementera kryptering/dekryptering i backend -2. Lägg till och konfigurera rate limiting i NestJS -3. ✅ Lägg till Helmet och CSP-konfiguration — **Klart** -4. Gå igenom compose.yml och kodbas för att säkerställa att alla hemligheter ligger i .env -5. Dokumentera och testa roll/accesskontroller +## 1. Sakerhet och data -## 2. DevOps & Stabilitet +- [ ] Kansliga uppgifter krypterade enligt beslutad modell. +- [ ] Rate limiting aktiv pa relevanta API/AI-endpoints. +- [ ] Secret-hantering verifierad (inga hardkodade hemligheter). +- [ ] Roll- och accesskontroller testade i praktiken. -- Sätt upp CI/CD-pipeline för automatiska tester och deployment (t.ex. GitHub Actions eller Gitea Actions) -- Automatisera databas-migreringar och seedning vid deployment -- Lägg till central loggning och monitorering (t.ex. Winston/Pino, health endpoints) -- Säkerställ backup-rutiner för datavolymer (MariaDB, bilder) +## 2. DevOps och stabilitet -### Steg-för-steg: -1. Skapa pipeline för build, test och deploy -2. Automatisera körning av prisma migrate deploy och seed_all.sql -3. Implementera loggning och monitorering -4. Dokumentera och testa backup/restore-rutiner +- [ ] CI/CD for build, test och deploy pa plats. +- [ ] Migreringar + seedning kor konsekvent vid release. +- [ ] Health checks och loggning verifierade. +- [ ] Backup/restore testad for datavolymer. -## 3. Testning & Kvalitet +## 3. Kvalitet och test -- Utöka integrationstester och E2E-tester (t.ex. Playwright) -- Striktare validering av API-data (class-validator) -- Säkerställ testtäckning för kritiska flöden (auth, CRUD, AI) +- [ ] Kritiska floden har testtackning (auth, import, CRUD, AI). +- [ ] Minst en end-to-end verifiering i testmiljo per release. +- [ ] DTO-validering och felhantering kontrollerad. -### Steg-för-steg: -1. Identifiera kritiska flöden och skriv tester -2. Lägg till E2E-tester för frontend och backend -3. Gå igenom och skärp validering i DTOs +## 4. Funktionell releaseklarhet -## 4. Funktionella förbättringar +- [ ] Kvittoimport fungerar end-to-end med granskningssteg. +- [ ] User-scoped produktmodell verifierad med flera testanvandare. +- [ ] Kategoritrad seedat och validerat i aktuell miljo. +- [ ] Bildimport och fallbackfloden fungerar i driftmiljo. -- Implementera EAN-skanning (Open Food Facts) -- Utveckla AI-baserade receptförslag ("Vad ska jag laga idag?") -- Förbättra enhetskonvertering och UX kring enheter +## 5. Riskhantering -### Steg-för-steg: -1. Planera och implementera EAN-skanning -2. Utveckla och testa AI-funktion för receptförslag -3. Förbättra och testa enhetslogik och gränssnitt +- [ ] AI-kostnad, timeout och fallback beteende verifierat. +- [ ] Ingen osynk mellan migrationer och seedskript. +- [ ] Kanda release-risker dokumenterade med ansvarig agare. -## 5. Risker & Flaskhalsar +## Relaterade dokument -- Optimera AI-anrop och fallback-logik -- Säkerställ backup av datavolymer -- Undvik osynk mellan SQL-seeds och migrationer - -### Steg-för-steg: -1. Gå igenom och optimera AI-anrop (kostnad, fallback) -2. Dokumentera och testa backup/restore -3. Se över och dokumentera seed/migration-processen +- `NEXT_STEPS.md` - overgripande prioriteringar. +- `TEKNISK_BESKRIVNING.md` - teknisk implementation. +- `flutter/next_steps_flutter.md` - Flutter-specifik leveransplan.