requireProfile(): - src/lib/client/profile.svelte.ts: neuer Helper, returnt das aktive Profile oder null nach standardisiertem alertAction - 5x in recipes/[id]/+page.svelte: setRating, toggleFavorite, logCooked, addComment, toggleWishlist verlieren je 7 Zeilen Guard-Klausel - profile-Variable im Closure macht den ! am profileStore.active obsolet asyncFetch(): - src/lib/client/api-fetch-wrapper.ts: returnt Response auf 2xx, null nach alertAction auf Fehler - 4 Call-Sites umgestellt: saveRecipe + saveTitle (recipes/[id]), saveEdit (admin/domains), rename (admin/profiles) - admin/domains add() bewusst nicht migriert — inline-Error-UX statt Modal Findings aus REVIEW-2026-04-18.md (Quick-Win 5) und redundancy.md
26 lines
873 B
TypeScript
26 lines
873 B
TypeScript
import { alertAction } from '$lib/client/confirm.svelte';
|
|
|
|
/**
|
|
* Fetch wrapper for actions where a non-OK response should pop a modal
|
|
* via alertAction(). Returns the Response on 2xx, or null after showing
|
|
* the alert. Caller should `if (!res) return;` after the call.
|
|
*
|
|
* Use this for *interactive* actions (rename, delete, save). For form
|
|
* submissions where the error should appear inline next to the field
|
|
* (e.g. admin/domains add()), keep manual handling.
|
|
*/
|
|
export async function asyncFetch(
|
|
url: string,
|
|
init: RequestInit | undefined,
|
|
errorTitle: string
|
|
): Promise<Response | null> {
|
|
const res = await fetch(url, init);
|
|
if (res.ok) return res;
|
|
const body = (await res.json().catch(() => null)) as { message?: string } | null;
|
|
await alertAction({
|
|
title: errorTitle,
|
|
message: body?.message ?? `HTTP ${res.status}`
|
|
});
|
|
return null;
|
|
}
|