- Svepte 51 hårdkodade strängar -> t() över konto, sök/bläddra, sparade recept,
kök, planera, skanna, byt måltid, inköp, minne, cooking, api-fel (+ locLabel/
kategorier via nycklar). 47 nya nycklar, översatta till alla 12 språk.
- NY: apps/mobile/scripts/i18n-check.mjs (i18n:check) – fäller bygget om ett språk
saknar en nyckel, en använd nyckel saknas, eller det finns hårdkodad UI-text.
Wire:ad i CI (.github/workflows/ci.yml) efter typecheck. => 'lägg till språk'
blir: kör vakten, den listar exakt vad som fattas. Aldrig mer leta för hand.
- Prettier-fixade 5 filer från tidigare leveranser så format:check blir grön.
- submit-recipe fri-text-payload + firebase dev-stubs markerade // i18n-ignore.
Co-Authored-By: Claude <noreply@anthropic.com>
- profile.tsx: samtyckesraden fick flex:1 på texten så längre språk (t.ex. spanska)
inte trycker på/av-knappen ur läge (låg till vänster förut)
- home.tsx: Dina sparade recept, Skicka in eget recept, matlager-underrubrik,
Allt/Öppna, platsnamn (Kyl/Frys/Skafferi...) -> t() (via typ, ej svenskt DB-namn)
- _layout.tsx: nav-titlar (Bläddra recept, Sparade recept, Matlager, Streckkod, Byt ut) -> t()
- 15 nya nycklar (home.*/nav.*) i alla 12 språk
Co-Authored-By: Claude <noreply@anthropic.com>
- cooking-skärmen renderade instructionSv (alltid svenska) -> nu instruction ?? instructionSv
- recept-skärmens täckningskort hårdkodade svenska (Du har X% hemma, Saknar N,
Du saknar, Lägg till i inköpslistan, Tillagt) -> t()-nycklar recipe.coverage.*
- coverage.missing fick översatt displayName i API:t (annars svenska ingrediensnamn)
- 7 nya recipe.coverage.*-nycklar i alla 12 språk
- persister-cache-nyckel -> -v2 (slänger gammal helsvensk cache en gang)
Co-Authored-By: Claude <noreply@anthropic.com>
Behaller maltidsfoto men informerar: 'Varje foto raknas som en skanning av din
kvot. Streckkod ar alltid gratis.' visas pa Skanna-skarmen under kvot-raden.
Ny i18n-nyckel scan.costNote x 12 sprak. Verifierat: mobil-typecheck gront.
Efter lyckad lasning/produktbidrag fanns bara 'Skanna igen'. Nu finns en tydlig
knapp som bekraftar och gar tillbaka dit man kom ifran (router.back):
'Stammer - klar' nar man just bidragit med foto, annars 'Klar'. 'Skanna igen'
finns kvar som sekundar, och 'Fota baksidan' visas nar info saknas.
Nya i18n-nycklar barcode.done + barcode.looksRight x 12 sprak.
Verifierat: mobil-typecheck gront.
Streckkod / produktbidrag:
- Tydlig bekraftelse 'Sparad i delade katalogen - tack!' visas nu efter att en
fotad produkt lasts av, sa man ser att bidraget gick fram (forut bara
'Skanna igen' utan aterkoppling).
- Naringsetiketter laser nu ocksa enkelomattat och fleromattat fett (t.ex.
olivolja visar tre fettrader). Nya valfria falt monounsaturatedFatG/
polyunsaturatedFatG i NutritionValues + READ_NUTRITION_LABEL + prompt +
produktpanelen. Obligatoriska EU-falt oforandrade.
Kvitto:
- Rader som ar samma vara (samma normaliserade namn + enhet) slas nu ihop till
EN vara med ratt antal - '2 x mjolk' pa kvittot blir en vara a 2 st i stallet
for tva rader a 1 st. Priser summeras, rabatter dras som forut. En kvittorad
raknas som minst 1 exemplar aven om antal saknas.
Verifierat: typecheck hela repot gront, nutrition-engine 19/19, ai-contracts
24/24, worker 23/23, api 104/104, samt repro mot testdatabas (2 mjolk-rader ->
1 vara a 2; olivolja sparar fett/mattat/enkel-/fleromattat).
Veckoplan/kalender:
- Byt ratt: PATCH satter nu titeln (och portioner/status) efter det nya
receptet, inte bara recipeId - annars visade kalendern kvar gamla ratten.
- Planera om veckan: ersatter nu veckans plan (raderar tidigare + entries via
kaskad) sa man aldrig far dubbletter och alltid ser den nya planen. Nytt
plan-id ger ocksa ny variation.
- Variation: liten deterministisk jitter per recept, seedad pa plan-id +
veckostart, sa olika veckor OCH omgenereringar blir olika. Tackning/utgang
dominerar fortfarande. Skalas av varietyLevel.
- Veckoplaneraren visar alltid mandag-sondag (mondayOf), oavsett dagens dag.
Streckkod (fota okand produkt):
- Fotar nu fram- OCH baksida (multi-foto) sa AI:n far bade namn (fram) och
naring/innehall (bak). Prompt uppdaterad for flera bilder.
- Worker uppdaterar en befintlig delad produkt aven utan nytt namn (behaller
namnet, fyller pa naring/innehall/allergener) - och sparar ny produkt aven
fran baksidesfoto (fallback-namn) sa data inte tappas.
- Produktpanelen visar 'Fota baksidan (naring & innehall)' nar info saknas, sa
man kan komplettera en halvfardig produkt. Fel visas som dialog utan att
tappa vyn.
- 5 nya i18n-nycklar x 12 sprak.
Verifierat: typecheck (ai-contracts/worker/api/mobil), worker 23/23,
ai-contracts 24/24, api 104/104, samt repro mot testdatabas (byt ratt satter
titel; planera om ger 1 plan; 3 veckor + omgenerering varierar; delvis produkt
kompletteras och behaller namnet).
Okand streckkod erbjuder nu 'Fota forpackningen' direkt i streckkodsvyn.
Fotot lases av (naring/allergener/innehall) och produkten UPSERTas i den
DELADE products-katalogen kopplat till GTIN (dataSource=user_scanned,
verificationStatus=unverified, createdByUserId=anvandaren) sa nasta person
som skannar samma kod far den direkt. Produkten laggs INTE till i lagret.
Naringsdeklaration-knappen tas bort som egen ingang - flodet vavs in i
streckkodsskanningen. product_package/nutrition_label -> READ_NUTRITION_LABEL
avslutar som 'completed' med result.product (ingen awaiting_confirmation).
- validation: barcode-falt i createScanInput.context
- worker: ny gren i processScanJob som skriver till products + returnerar tidigt
- mobil: inline contributePhoto (fota -> ladda upp -> polla -> visa info)
- scan: ta bort naringsdeklaration-knappen
- i18n: barcode.contributing.* + uppdaterad unknownBody pa 12 sprak
Verifierat: typecheck (validation/worker/api/mobil), worker 23/23, api 104/104,
och repro mot testdatabas (products-upsert, ingen inventory, idempotent aterskann).
- Byt rätt gav 'något gick fel': limit=30 översteg schemats tak (20).
Höjt taket till 50, byt rätt hämtar 40 + sök vilken rätt som helst.
- Veckonavigering: pilarna byter nu VECKA (weekOffset) i stället för att
bara flytta markerad dag -> går att planera nästa vecka. Titel visar
veckans datumintervall; bakåt spärras före denna vecka.
- Lägg till måltid: ny POST /v1/week-plans/:id/entries + knapp 'Lägg till
måltid' (väljer måltidstyp -> receptväljaren i lägg-till-läge) + knapp
'Planera om veckan'. Går nu att fylla en tom dag igen.
Verifierat: swap 200 (40 varierade), add-entry 201, delete 200, api 104/104.
communityPublish satts till false aven under trial (ovriga premium-
funktioner ingar fortfarande i provperioden). Endast betalda planer
(household/family/large_household) far skicka in egna recept. Uppdaterat
premium-meddelandet i appen (11 sprak + sv) sa det inte langre antyder
att provperioden lases upp funktionen. Verifierat: subscriptions 10/10,
api 104/104, typecheck gron.
QR-produktinfo (barcode.info.*), egna recept (submit.*) och 'har du
lagat denna' (cookedLog.*) fyllda i en/da/nb/de/nl/fr/es/it/pt/fi/pl
(39 nycklar/sprak). Slutar falla tillbaka pa svenska.
Ny knapp 'Skicka in eget recept' i Hem, direkt under 'Dina sparade
recept' (samma kort-stil). Ny skarm submit-recipe: enkel mall (titel +
ingredienser med mangd/gram/kilo + tillagning). Skickas som fritext ->
AAMOS strukturerar -> workern AI-granskar, dubblettkollar, finskriver
och auto-publicerar, markt med anvandarens namn.
Hanterar 402/PREMIUM_REQUIRED snyggt (egna recept ingar i Premium/trial;
gratisnivan ser uppgraderingsvy i stallet for ratt fel). Backend fanns
redan (POST /v1/recipes + STRUCTURE_RECIPE_TEXT).
QR/streckkod ar nu ett rent informationsflode: skanna for att SE vad
produkten innehaller. Panelen visar full naring per 100 g (energi,
fett/mattat, kolhydrat/socker, fiber, protein, salt), allergener,
'kan innehalla spar av', ingredienslista (Innehall) och kalla. Ingen
'lagg till'-knapp langre.
Buggfix: kameran triggar onBarcodeScanned manga ggr/sek och state-
flaggorna uppdaterades asynkront -> parallella uppslag staplade tva
Alert-rutor (okand forst, produkten bakom -> syntes forst efter Avbryt).
Nu synkront ref-las + panel i stallet for Alert.
- DIET_PATTERNS: +nordic, +carnivore, +paleo (migration 0029). Ingen separat
"lchf" - LCHF tacks av befintliga "low_carb" for att undvika dubblett med
keto/low_carb. UI visar low_carb med etiketten "LCHF".
- Mobil onboarding + profil: 9 rena val (allatare..carnivore), 12 sprak.
- recommendation-engine: ny mjuk dietAffinity-poangterm (0-1, neutral 0.5).
Rankar recept mot matvanan - ALDRIG hart filter (uteslutande matvanor,
religion, allergener hanteras redan deterministiskt i sakerhetsfiltret).
low_carb/keto: lag kolhydrat. carnivore: hog protein + lag kolhydrat.
paleo: glutenfri/laktosfri-proxyer. nordic: svenskt/nordiskt kok + sasong.
- 6 nya tester (35 grona). Full typecheck 20/20 + mobil gron.
TRIAL_DAYS var redan 14 i koden men auth.trialNote (12 sprak), butiksmetadata, juridik-utkast, API-ref, exec-summary och UX-doc sa 7. Nu 14 overallt. Rorde EJ icke-trial 7-dagar (inbjudningslank, backup, S3-lifecycle, grace, retention). Beslut: Johan (battre onboarding).
- Merge leftovers into existing meal_box when same recipeId + cookedAt date + frozen + available.
- Store mealBoxMutations JSONB on cooking_sessions for deterministic undo.
- Undo decrements portions/remaining, discards box at zero, appends correction ledger rows.
- Mobile: undo button in cooking/[id].tsx after-flow and meal-boxes.tsx within 24h window.
- i18n undo strings across all 12 locales; parity test green.
- 6 new integration tests: merge, no cross-date merge, frozen split, undo restore, undo discard, ledger invariant.
- Update FAS3 audit doc with 3d semantics.
Closes Fas 3d
- consumptionPortions = min(planned, actualPortionsEaten + leftoverEstimatePortions).
Meal boxes are a subset of leftovers; raw inventory is only retained for
portions that were never cooked.
- Added validation leftoverEstimatePortions >= mealBoxPortions with localized
400 error (cooked.leftoverLessThanBox) in server i18n + all 12 locales.
- Removed unused COOKING_SESSION_STATUSES / MEAL_BOX_STATUSES imports from
apps/api/src/lib/cooking.ts.
- Hardened test cleanup to delete mealBoxes/meals/recipeCooks/cookingSessions
by household before dropping storageLocations.
- New regression tests: meal-box double-counting, eaten+leftover split, and
leftover < box rejection.
- Updated FAS3-COOKING-SESSIONS-AUDIT.md with corrected physics semantics.
- cookRecipeInputSchema utökas med actualPortionsEaten, leftoverEstimatePortions, leftoverNote
- completeCookingSession-wrapper i apps/api/src/lib/cooking.ts hanterar summavalidering,
persistens av svar, profiluppdateringar och analytics (started+completed) för båda vägarna
- Legacy POST /v1/recipes/:id/cook använder wrappern med emitStartedEvent
- GET /v1/recipes/:id/cooking-assumptions väljer deterministiskt bland icke-valfria ingredienser
- i18n: nyckel cooked.portionsSumExceedsPlanned i samtliga 12 lokaler + server-i18n
- Nya tester för legacy /cook och cooking-assumptions med valfri första ingrediens
Refs: steg 3b-fix, granskningsrunda 2026-08-07
- Add PROGRESSIVE_ONBOARDING feature flag to KNOWN_FLAGS
- Add onboarding_step column to users table (a/b/c)
- New backend endpoints:
- GET /v1/onboarding/status – check current step + feature flag
- POST /v1/onboarding/quick-start – complete Step A (goal + precision)
- POST /v1/onboarding/complete-b – complete Step B (diet, allergens, household)
- POST /v1/onboarding/complete-c – complete Step C (health profile)
- POST /v1/onboarding/skip – GDPR-friendly skip
- Refactor mobile onboarding screen into 3 progressive layers
- Update auth store with onboardingStep state
- Update tab layout to only block on Step A
- Update registration to set onboardingStep='a'
- Add i18n keys for Step B/C titles across all 12 locales
- Add Zod validation schemas (quickStartInputSchema, onboardingStatusSchema)
- Add tests for validation and feature flag
- Preserve existing /v1/me/onboarding for backward compatibility
- Migration: 0004_progressive_onboarding.sql