98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
"use client"
|
|
|
|
import Link from "next/link"
|
|
import { motion } from "framer-motion"
|
|
import { Restaurant, Visit } from "@/app/types"
|
|
|
|
function priceLabel(range: number) {
|
|
return "€".repeat(range)
|
|
}
|
|
|
|
function formatDate(iso: string) {
|
|
return new Date(iso).toLocaleDateString("en-GB", {
|
|
day: "numeric",
|
|
month: "short",
|
|
year: "numeric",
|
|
})
|
|
}
|
|
|
|
interface Props {
|
|
restaurant: Restaurant
|
|
latestVisit: Visit
|
|
index: number
|
|
}
|
|
|
|
export default function RestaurantCard({ restaurant, latestVisit, index }: Props) {
|
|
return (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 24 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.4, delay: index * 0.08, ease: [0.25, 0.1, 0.25, 1] }}
|
|
>
|
|
<Link href={`/restaurant/${restaurant.id}`}>
|
|
<div className="group relative rounded-2xl border border-white/[0.06] bg-white/[0.03] hover:bg-white/[0.06] hover:border-white/[0.12] transition-all duration-300 p-5 cursor-pointer overflow-hidden">
|
|
{/* Amber glow on hover */}
|
|
<div className="absolute inset-0 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 pointer-events-none"
|
|
style={{ background: "radial-gradient(circle at 50% 0%, rgba(245,158,11,0.06) 0%, transparent 70%)" }}
|
|
/>
|
|
|
|
<div className="flex items-start justify-between gap-4">
|
|
<div className="flex-1 min-w-0">
|
|
<h3 className="text-lg font-bold text-[#f5f5f5] group-hover:text-[#f59e0b] transition-colors truncate">
|
|
{restaurant.name}
|
|
</h3>
|
|
<p className="text-sm text-white/40 mt-0.5">
|
|
{restaurant.city}, {restaurant.country}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex flex-col items-end gap-1 shrink-0">
|
|
<div className="flex items-center gap-1.5">
|
|
<span className="text-[#f59e0b] font-black text-lg leading-none">
|
|
{latestVisit.rating}
|
|
</span>
|
|
<span className="text-white/30 text-xs">/10</span>
|
|
</div>
|
|
<span className="text-white/30 text-xs font-medium tracking-wide">
|
|
{priceLabel(restaurant.price_range)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-4">
|
|
{latestVisit.dishes[0] && (
|
|
<p className="text-sm text-white/60 italic truncate">
|
|
“{latestVisit.dishes[0]}”
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-4 flex items-center justify-between">
|
|
<div className="flex flex-wrap gap-1.5">
|
|
{restaurant.cuisine.slice(0, 3).map((tag) => (
|
|
<span
|
|
key={tag}
|
|
className="text-[10px] font-semibold uppercase tracking-wider text-[#f59e0b]/70 bg-[#f59e0b]/10 rounded-full px-2.5 py-0.5"
|
|
>
|
|
{tag}
|
|
</span>
|
|
))}
|
|
</div>
|
|
<span className="text-xs text-white/25 shrink-0">
|
|
{formatDate(latestVisit.date)}
|
|
</span>
|
|
</div>
|
|
|
|
{restaurant.visits.length > 1 && (
|
|
<div className="mt-3 pt-3 border-t border-white/[0.05]">
|
|
<p className="text-xs text-white/30">
|
|
{restaurant.visits.length} visits
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Link>
|
|
</motion.div>
|
|
)
|
|
}
|