feat: stabilization + recipe edit/create UI

This commit is contained in:
clawd
2026-02-18 09:55:39 +00:00
commit ee452efa6a
75 changed files with 15160 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
import { Link } from 'react-router'
import { Heart, Clock } from 'lucide-react'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toggleFavorite } from '../../api/recipes'
import type { Recipe } from '../../api/types'
const gradients = [
'from-primary/60 to-secondary/60',
'from-secondary/60 to-sage/60',
'from-primary-light to-primary/40',
'from-sage/40 to-secondary/60',
]
export function RecipeCard({ recipe }: { recipe: Recipe }) {
const qc = useQueryClient()
const favMutation = useMutation({
mutationFn: () => toggleFavorite(recipe.id),
onSuccess: () => qc.invalidateQueries({ queryKey: ['recipes'] }),
})
const gradient = gradients[recipe.title.length % gradients.length]
const totalTime = recipe.total_time_min || ((recipe.prep_time_min || 0) + (recipe.cook_time_min || 0))
return (
<div className="bg-surface rounded-2xl overflow-hidden shadow-sm break-inside-avoid mb-4">
<Link to={`/recipe/${recipe.slug}`}>
{recipe.image_url ? (
<img src={recipe.image_url} alt={recipe.title} className="w-full h-auto object-cover" loading="lazy" />
) : (
<div className={`w-full aspect-[3/4] bg-gradient-to-br ${gradient} flex items-center justify-center`}>
<span className="text-4xl">🍰</span>
</div>
)}
</Link>
<div className="p-3">
<Link to={`/recipe/${recipe.slug}`}>
<h3 className="font-display text-base text-espresso line-clamp-2">{recipe.title}</h3>
</Link>
<div className="flex items-center justify-between mt-2">
{totalTime > 0 && (
<span className="flex items-center gap-1 text-warm-grey text-xs">
<Clock size={14} /> {totalTime} min
</span>
)}
<button
onClick={(e) => { e.preventDefault(); favMutation.mutate() }}
className="ml-auto"
>
<Heart
size={20}
className={recipe.is_favorite ? 'fill-primary text-primary' : 'text-warm-grey'}
/>
</button>
</div>
</div>
</div>
)
}