Files
recipe-app/NEXT_STEPS.md
T

186 lines
10 KiB
Markdown

# Nästa 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.
---
## Status — senast genomgånget: 2026-04-19
| Funktion | Status |
|---|---|
| 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 |
| 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 |
| 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 (supplement, idempotent) | ✅ Klart |
| Kategoritilldelning i admin-UI | ✅ Klart |
| Taggning av produkter | ✅ Klart |
| Näringsvärden på produkter | ✅ Klart (schema + API) |
| Seed produktdata med kategoritilldelning | ⚠️ Script klart, ej aktiverat i init |
| Användarspecifika produkter (UserProduct) | ⚠️ Schema klart, UI basic |
| Användarroller (user / admin) | ✅ Klart |
| Användarhantering i admin-UI | ✅ Klart |
| Profilsida med flikar (Min profil / Användare / Databas) | ✅ 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 |
| Avancerad AI-integration (veckoplanering, receptförslag) | ❌ Planerad |
| EAN-skanning via Open Food Facts API | ❌ Planerad |
---
## Prioriterade förbättringar
### 1. Seed-data (002-seed-products.sql)
**Mål:** Möjliggöra demo och ny server utan manuell datainmatning.
`db/init/002-seed-products.sql` är inaktiverad (`.disabled`) tills produkterna har rätt `categoryId`. Skript för kategorimappning finns i `db/seeds/`:
- Kör `db/seeds/categories_supplement.sql` → lägger till saknade kategorier
- Kör `db/seeds/seed_product_categories.sql` → kopplar ~190 produkter till rätt kategori
- Verifiera att mappningarna ser rätt ut i admin-UI (filtrera på okategoriserade)
- Generera en ny `002-seed-products.sql` med korrekt `categoryId` per rad (via `SELECT` mot live-db)
- Ta bort `.disabled`-suffixet och testa fresh install
### 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')``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 (samma innehåll som `/admin/products`)
- `/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
---
## 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