diff --git a/apps/mobile/src/app/(tabs)/plan.tsx b/apps/mobile/src/app/(tabs)/plan.tsx
index d9fa895..dfccdba 100644
--- a/apps/mobile/src/app/(tabs)/plan.tsx
+++ b/apps/mobile/src/app/(tabs)/plan.tsx
@@ -178,6 +178,11 @@ export default function PlanScreen() {
text: t("common.skip"),
onPress: () => patchEntry.mutate({ planId, entryId: entry.id, status: "skipped" }),
},
+ {
+ text: "Byt rätt",
+ onPress: () =>
+ router.push(`/swap-meal/${entry.id}?planId=${planId}&mealType=${entry.mealType}`),
+ },
{ text: t("common.cancel"), style: "cancel" },
]);
};
diff --git a/apps/mobile/src/app/_layout.tsx b/apps/mobile/src/app/_layout.tsx
index 56595f7..6d55e70 100644
--- a/apps/mobile/src/app/_layout.tsx
+++ b/apps/mobile/src/app/_layout.tsx
@@ -77,6 +77,7 @@ export default function RootLayout() {
options={{ title: "", presentation: "fullScreenModal" }}
/>
+
diff --git a/apps/mobile/src/app/swap-meal/[entryId].tsx b/apps/mobile/src/app/swap-meal/[entryId].tsx
new file mode 100644
index 0000000..14deb82
--- /dev/null
+++ b/apps/mobile/src/app/swap-meal/[entryId].tsx
@@ -0,0 +1,75 @@
+import { router, useLocalSearchParams } from "expo-router";
+import { Alert } from "react-native";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+import { api } from "@/lib/api";
+import { t } from "@/lib/i18n";
+import {
+ Body,
+ Card,
+ EmptyState,
+ ErrorView,
+ LoadingView,
+ Row,
+ Screen,
+ Small,
+ Tag,
+ Title,
+} from "@/components/ui";
+
+interface Rec {
+ recipeId: string;
+ titleSv: string;
+ coveragePercent: number;
+}
+interface WhatToEatResponse {
+ recommendations: Rec[];
+}
+
+export default function SwapMealScreen() {
+ const params = useLocalSearchParams<{ entryId: string; planId: string; mealType: string }>();
+ const entryId = String(params.entryId);
+ const planId = String(params.planId);
+ const mealType = String(params.mealType || "dinner");
+ const queryClient = useQueryClient();
+
+ const query = useQuery({
+ queryKey: ["swap-options", mealType],
+ queryFn: () =>
+ api(`/v1/recommendations/what-to-eat?limit=10&mealType=${mealType}`),
+ });
+
+ const swap = useMutation({
+ mutationFn: (recipeId: string) =>
+ api(`/v1/week-plans/${planId}/entries/${entryId}`, { method: "PATCH", body: { recipeId } }),
+ onSuccess: () => {
+ void queryClient.invalidateQueries({ queryKey: ["week-plan"] });
+ router.back();
+ },
+ onError: (err) =>
+ Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
+ });
+
+ const recs = query.data?.recommendations ?? [];
+ const mealLabel = mealType === "lunch" ? "lunchen" : mealType === "breakfast" ? "frukosten" : "middagen";
+
+ return (
+
+ Byt ut måltiden
+ Välj en annan rätt för {mealLabel}:
+ {query.isLoading && }
+ {query.isError && void query.refetch()} />}
+ {query.data && recs.length === 0 && }
+ {recs.map((rec) => (
+ swap.mutate(rec.recipeId)}>
+
+ {rec.titleSv}
+ = 80 ? "success" : "neutral"}
+ />
+
+
+ ))}
+
+ );
+}