From 0e057bc25d3bc929d833e00384f568cd3c455464 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 21:54:28 +0000 Subject: [PATCH] feat(egna-recept): knapp i Hem + inmatningsmall for egna recept 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). --- apps/mobile/src/app/(tabs)/home.tsx | 4 + apps/mobile/src/app/submit-recipe.tsx | 143 +++++++++++++++++++++++++ apps/mobile/src/locales/sv/common.json | 19 +++- 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 apps/mobile/src/app/submit-recipe.tsx diff --git a/apps/mobile/src/app/(tabs)/home.tsx b/apps/mobile/src/app/(tabs)/home.tsx index 3aa63ae..37a2c8d 100644 --- a/apps/mobile/src/app/(tabs)/home.tsx +++ b/apps/mobile/src/app/(tabs)/home.tsx @@ -135,6 +135,10 @@ export default function HomeScreen() { ⭐ Dina sparade recept + router.push("/submit-recipe")}> + ✍️ Skicka in eget recept + + {/* Matlager – städat, öppnas per plats eller som helhet (spec §8). */} 🧺 {t("home.inventory")} diff --git a/apps/mobile/src/app/submit-recipe.tsx b/apps/mobile/src/app/submit-recipe.tsx new file mode 100644 index 0000000..3f8e09c --- /dev/null +++ b/apps/mobile/src/app/submit-recipe.tsx @@ -0,0 +1,143 @@ +import { useState } from "react"; +import { router } from "expo-router"; +import { api, ApiError } from "@/lib/api"; +import { t } from "@/lib/i18n"; +import { Body, Button, Card, Heading, Input, Screen, Small, Spacer, Title } from "@/components/ui"; +import { spacing } from "@/lib/theme"; + +/** + * Skicka in eget recept (spec §35). Enkel mall: titel + ingredienser + * (mängd + gram/kilo) + tillagning. Skickas som fritext → AAMOS + * (STRUCTURE_RECIPE_TEXT) tolkar och strukturerar, workern AI-granskar, + * dubblettkollar, finskriver och auto-publicerar – märkt med ditt namn. + */ + +type Phase = "form" | "done" | "premium"; + +export default function SubmitRecipeScreen() { + const [title, setTitle] = useState(""); + const [ingredients, setIngredients] = useState(""); + const [steps, setSteps] = useState(""); + const [busy, setBusy] = useState(false); + const [error, setError] = useState(null); + const [phase, setPhase] = useState("form"); + + const canSubmit = + title.trim().length >= 3 && ingredients.trim().length >= 3 && steps.trim().length >= 3; + + const submit = async () => { + if (!canSubmit || busy) return; + setBusy(true); + setError(null); + // Bygg en tydlig fritext-mall som AI:n tolkar robust. + const text = [ + `Titel: ${title.trim()}`, + "", + "Ingredienser:", + ingredients.trim(), + "", + "Gör så här:", + steps.trim(), + ].join("\n"); + try { + await api("/v1/recipes", { method: "POST", body: { mode: "free_text", text } }); + setPhase("done"); + } catch (err) { + if (err instanceof ApiError && err.status === 402) { + setPhase("premium"); + } else { + setError(err instanceof Error ? err.message : t("common.error")); + } + } finally { + setBusy(false); + } + }; + + if (phase === "done") { + return ( + + + 🎉 {t("submit.successTitle")} + {t("submit.successBody")} + +