fix(recipe): Favoriten-Markierung persistiert beim Neuladen
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 50s
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 50s
Bug: Beim Neuanzeigen einer Rezeptseite war der Favoriten-Button immer grau — isFav wurde als local $state(false) initialisiert und die checkFavorite()-Funktion war eine Stub-Implementation, die nichts gemacht hat. State lebte nur innerhalb einer Session. Fix: - Neue Server-Funktion listFavoriteProfiles(db, recipeId): number[] in $lib/server/recipes/actions.ts - +page.server.ts lädt favorite_profile_ids mit in die Page-Daten - +page.svelte macht isFav zum $derived aus favoriteProfileIds + aktivem Profil. toggleFavorite mutiert die lokale Liste (Add/Remove der aktiven Profil-ID) — beim nächsten Load ist die Server-Liste wieder Source of Truth. - Alte Stub-Funktion checkFavorite() entfernt (inkl. Aufruf in onMount).
This commit is contained in:
@@ -73,6 +73,17 @@ export function isFavorite(
|
||||
);
|
||||
}
|
||||
|
||||
export function listFavoriteProfiles(
|
||||
db: Database.Database,
|
||||
recipeId: number
|
||||
): number[] {
|
||||
return (
|
||||
db
|
||||
.prepare('SELECT profile_id FROM favorite WHERE recipe_id = ?')
|
||||
.all(recipeId) as { profile_id: number }[]
|
||||
).map((r) => r.profile_id);
|
||||
}
|
||||
|
||||
export function logCooked(
|
||||
db: Database.Database,
|
||||
recipeId: number,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getRecipeById } from '$lib/server/recipes/repository';
|
||||
import {
|
||||
listComments,
|
||||
listCookingLog,
|
||||
listFavoriteProfiles,
|
||||
listRatings
|
||||
} from '$lib/server/recipes/actions';
|
||||
|
||||
@@ -17,7 +18,8 @@ export const load: PageServerLoad = async ({ params }) => {
|
||||
const ratings = listRatings(db, id);
|
||||
const comments = listComments(db, id);
|
||||
const cooking_log = listCookingLog(db, id);
|
||||
const favorite_profile_ids = listFavoriteProfiles(db, id);
|
||||
const avg_stars =
|
||||
ratings.length === 0 ? null : ratings.reduce((s, r) => s + r.stars, 0) / ratings.length;
|
||||
return { recipe, ratings, comments, cooking_log, avg_stars };
|
||||
return { recipe, ratings, comments, cooking_log, favorite_profile_ids, avg_stars };
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
let ratings = $state<typeof data.ratings>([]);
|
||||
let comments = $state<CommentRow[]>([]);
|
||||
let cookingLog = $state<typeof data.cooking_log>([]);
|
||||
let isFav = $state(false);
|
||||
let favoriteProfileIds = $state<number[]>([]);
|
||||
let onWishlist = $state(false);
|
||||
let newComment = $state('');
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
ratings = [...data.ratings];
|
||||
comments = [...data.comments];
|
||||
cookingLog = [...data.cooking_log];
|
||||
favoriteProfileIds = [...data.favorite_profile_ids];
|
||||
});
|
||||
|
||||
const myRating = $derived(
|
||||
@@ -29,14 +30,9 @@
|
||||
: null
|
||||
);
|
||||
|
||||
async function checkFavorite() {
|
||||
if (!profileStore.active) {
|
||||
isFav = false;
|
||||
return;
|
||||
}
|
||||
// Fetch favorite status via list endpoint (quick hack: GET not implemented, infer from no-op)
|
||||
// Not critical for MVP — we mutate state on toggle.
|
||||
}
|
||||
const isFav = $derived(
|
||||
profileStore.active ? favoriteProfileIds.includes(profileStore.active.id) : false
|
||||
);
|
||||
|
||||
async function setRating(stars: number) {
|
||||
if (!profileStore.active) {
|
||||
@@ -64,13 +60,16 @@
|
||||
});
|
||||
return;
|
||||
}
|
||||
const profileId = profileStore.active.id;
|
||||
const method = isFav ? 'DELETE' : 'PUT';
|
||||
await fetch(`/api/recipes/${data.recipe.id}/favorite`, {
|
||||
method,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ profile_id: profileStore.active.id })
|
||||
body: JSON.stringify({ profile_id: profileId })
|
||||
});
|
||||
isFav = !isFav;
|
||||
favoriteProfileIds = isFav
|
||||
? favoriteProfileIds.filter((id) => id !== profileId)
|
||||
: [...favoriteProfileIds, profileId];
|
||||
}
|
||||
|
||||
async function logCooked() {
|
||||
@@ -183,7 +182,6 @@
|
||||
|
||||
onMount(() => {
|
||||
void requestWakeLock();
|
||||
void checkFavorite();
|
||||
void refreshWishlistState();
|
||||
const onVisibility = () => {
|
||||
if (document.visibilityState === 'visible' && !wakeLock) void requestWakeLock();
|
||||
|
||||
Reference in New Issue
Block a user