feat: dedicated favorites page for recipes
Favoriting already worked (heart toggle on the recipe detail page, DB table, API route) but there was nowhere to see what you'd favorited — the actual missing piece behind "add a favorites feature". - New /recipes/favorites page: paginated grid of favorited recipes (cover photo, difficulty, time, author), sorted by most-recently favorited. A previously-favorited recipe stays visible even if the author later goes private, matching the existing private-accounts scope decision (existing access isn't revoked, only new discovery is affected). - Unfavoriting from that page removes the card immediately — added an optional onToggle callback to FavoriteButton for this. - Added a lightweight "My Recipes / Favorites" tab pair at the top of /recipes linking between the two, rather than a new top-level nav item (nav is already at 8 entries). Deliberately out of scope: favorite toggles on the main recipe grid, feed cards, or search/explore results — favoriting your own recipes is odd UX, and wiring session-aware favorited state into the public (unauthenticated) search route is a separate, bigger change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Heart } from "lucide-react";
|
||||
import { FavoriteRecipeCard, type FavoriteRecipe } from "@/components/recipe/favorite-recipe-card";
|
||||
|
||||
export function FavoritesGrid({
|
||||
initialRecipes,
|
||||
emptyLabel,
|
||||
}: {
|
||||
initialRecipes: FavoriteRecipe[];
|
||||
emptyLabel: string;
|
||||
}) {
|
||||
const [recipes, setRecipes] = useState(initialRecipes);
|
||||
|
||||
function handleUnfavorited(recipeId: string) {
|
||||
setRecipes((prev) => prev.filter((r) => r.id !== recipeId));
|
||||
}
|
||||
|
||||
if (recipes.length === 0) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-64 border-2 border-dashed rounded-xl gap-4">
|
||||
<Heart className="h-12 w-12 text-muted-foreground/40" />
|
||||
<p className="text-muted-foreground text-sm text-center max-w-xs">{emptyLabel}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 items-start">
|
||||
{recipes.map((recipe) => (
|
||||
<FavoriteRecipeCard key={recipe.id} recipe={recipe} onUnfavorited={handleUnfavorited} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user