112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { Heart, Clock, Share2 } from 'lucide-react'
|
|
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
|
|
import { Badge } from "@/components/ui/badge"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Recipe } from "@/types/recipe"
|
|
import { RecipeModal } from "@/components/recipe-modal"
|
|
|
|
interface RecipeCardProps {
|
|
recipe: Recipe
|
|
}
|
|
|
|
export function RecipeCard({ recipe }: RecipeCardProps) {
|
|
const [isFavorite, setIsFavorite] = useState(recipe.isFavorite)
|
|
const [isModalOpen, setIsModalOpen] = useState(false)
|
|
|
|
const toggleFavorite = (e: React.MouseEvent) => {
|
|
e.stopPropagation()
|
|
setIsFavorite(!isFavorite)
|
|
}
|
|
|
|
const shareRecipe = (e: React.MouseEvent) => {
|
|
e.stopPropagation()
|
|
// In a real app, this would use the Web Share API or copy to clipboard
|
|
alert(`Sharing recipe: ${recipe.title}`)
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Card
|
|
className="overflow-hidden transition-all duration-200 hover:shadow-md cursor-pointer h-full flex flex-col"
|
|
onClick={() => setIsModalOpen(true)}
|
|
>
|
|
<div className="relative h-48 overflow-hidden">
|
|
<img
|
|
src={recipe.imageUrl || "/placeholder.svg"}
|
|
alt={recipe.title}
|
|
className="w-full h-full object-cover transition-transform duration-300 hover:scale-105"
|
|
/>
|
|
<div className="absolute top-2 right-2">
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="rounded-full bg-background/80 backdrop-blur-sm hover:bg-background/90"
|
|
onClick={toggleFavorite}
|
|
>
|
|
<Heart
|
|
className={`h-5 w-5 ${isFavorite ? 'fill-red-500 text-red-500' : 'text-slate-600'}`}
|
|
/>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
<CardHeader className="pb-2">
|
|
<div className="flex justify-between items-start">
|
|
<h3 className="font-semibold text-lg line-clamp-1">{recipe.title}</h3>
|
|
</div>
|
|
<div className="flex items-center text-muted-foreground text-sm">
|
|
<Clock className="h-3.5 w-3.5 mr-1" />
|
|
<span>{recipe.cookingTime} mins</span>
|
|
<span className="mx-2">•</span>
|
|
<span className="capitalize">{recipe.difficulty}</span>
|
|
</div>
|
|
</CardHeader>
|
|
|
|
<CardContent className="pb-2 flex-grow">
|
|
<p className="text-muted-foreground text-sm line-clamp-2 mb-3">
|
|
{recipe.description}
|
|
</p>
|
|
<div className="flex flex-wrap gap-1.5">
|
|
{recipe.tags.slice(0, 3).map(tag => (
|
|
<Badge key={tag} variant="secondary" className="text-xs">
|
|
{tag}
|
|
</Badge>
|
|
))}
|
|
{recipe.tags.length > 3 && (
|
|
<Badge variant="outline" className="text-xs">
|
|
+{recipe.tags.length - 3} more
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
|
|
<CardFooter className="pt-2">
|
|
<div className="flex justify-between w-full">
|
|
<Button variant="outline" size="sm">View Recipe</Button>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="rounded-full"
|
|
onClick={shareRecipe}
|
|
>
|
|
<Share2 className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</CardFooter>
|
|
</Card>
|
|
|
|
<RecipeModal
|
|
recipe={recipe}
|
|
isOpen={isModalOpen}
|
|
onClose={() => setIsModalOpen(false)}
|
|
isFavorite={isFavorite}
|
|
onToggleFavorite={toggleFavorite}
|
|
onShare={shareRecipe}
|
|
/>
|
|
</>
|
|
)
|
|
}
|