fix(mobile): onError på 15 mutationer – inga tysta miss (MIKRO 52)
CI / Typecheck, test & build (push) Successful in 1m37s

This commit is contained in:
Sven (AAMOS AI)
2026-08-14 18:03:36 +07:00
parent ea1f9a113a
commit 491daace86
6 changed files with 32 additions and 2 deletions
+8
View File
@@ -51,19 +51,27 @@ export default function MemoryScreen() {
mutationFn: (id: string) =>
api(`/v1/me/memory/${id}`, { method: "PATCH", body: { verified: true } }),
onSuccess: invalidate,
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const pause = useMutation({
mutationFn: ({ id, paused }: { id: string; paused: boolean }) =>
api(`/v1/me/memory/${id}`, { method: "PATCH", body: { paused } }),
onSuccess: invalidate,
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const remove = useMutation({
mutationFn: (id: string) => api(`/v1/me/memory/${id}`, { method: "DELETE" }),
onSuccess: invalidate,
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const removeAll = useMutation({
mutationFn: () => api("/v1/me/memory", { method: "DELETE" }),
onSuccess: invalidate,
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
if (query.isLoading) return <LoadingView />;
+8
View File
@@ -73,15 +73,21 @@ export default function ProfileScreen() {
const togglePrecision = useMutation({
mutationFn: (mode: string) => api("/v1/me", { method: "PATCH", body: { precisionMode: mode } }),
onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["me"] }),
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const deleteAccount = useMutation({
mutationFn: () => api("/v1/me", { method: "DELETE" }),
onSuccess: () => void logout().then(() => router.replace("/(auth)/login")),
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const resend = useMutation({
mutationFn: () => api("/v1/auth/resend-verification", { method: "POST" }),
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
// Språkval (i18n M4): sparas i backend-preferenserna + lokalt, byter direkt.
@@ -96,6 +102,8 @@ export default function ProfileScreen() {
await persistLanguageTag(languageTag);
await queryClient.invalidateQueries();
},
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
if (me.isLoading) return <LoadingView />;
+4
View File
@@ -83,12 +83,16 @@ export default function RecipeScreen() {
mutationFn: (isFavorite: boolean) =>
api(`/v1/recipes/${id}/favorite`, { method: isFavorite ? "DELETE" : "POST" }),
onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["recipe", id] }),
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const rate = useMutation({
mutationFn: (stars: number) =>
api(`/v1/recipes/${id}/rate`, { method: "POST", body: { stars, feedbackTags: [] } }),
onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["recipe", id] }),
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
if (query.isLoading) return <LoadingView />;
+3 -1
View File
@@ -1,5 +1,5 @@
import { useState } from "react";
import { ActivityIndicator, View } from "react-native";
import { ActivityIndicator, Alert, View } from "react-native";
import { router } from "expo-router";
import { useMutation, useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api";
@@ -69,6 +69,8 @@ export default function ReconciliationScreen() {
router.back();
}
},
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
if (query.isLoading) return <LoadingView />;
@@ -1,5 +1,5 @@
import { useMemo, useState } from "react";
import { View } from "react-native";
import { Alert, View } from "react-native";
import { router, useLocalSearchParams } from "expo-router";
import { useMutation, useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api";
@@ -52,6 +52,8 @@ export default function ScanDiffReviewScreen() {
onSuccess: () => {
router.back();
},
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const rows = useMemo(() => query.data?.rows ?? [], [query.data]);
+6
View File
@@ -96,6 +96,8 @@ export default function ShoppingScreen() {
setNewItem("");
invalidate();
},
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const toggle = useMutation({
@@ -105,6 +107,8 @@ export default function ShoppingScreen() {
body: { checked: !item.checked },
}),
onSuccess: invalidate,
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
const complete = useMutation({
@@ -119,6 +123,8 @@ export default function ShoppingScreen() {
invalidate();
Alert.alert(t("shopping.completedTitle"), t("shopping.completedBody", { count: added }));
},
onError: (err) =>
Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")),
});
if (lists.isLoading || list.isLoading) return <LoadingView />;