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")} + +