73 lines
2.8 KiB
TypeScript
73 lines
2.8 KiB
TypeScript
"use client";
|
||
|
||
import { PublicRestaurant } from "@/app/types/Types";
|
||
import { glassSurfaceCard } from "@/lib/styles/glassSurface";
|
||
import { ArrowLeft2, Location } from "iconsax-react";
|
||
import Image from "next/image";
|
||
import Link from "next/link";
|
||
import { useState } from "react";
|
||
|
||
const FALLBACK_LOGO = "/assets/images/avatar.svg";
|
||
|
||
function isValidLogoUrl(url: string | null | undefined): url is string {
|
||
if (!url?.trim()) return false;
|
||
const lower = url.toLowerCase();
|
||
if (lower.endsWith(".pdf")) return false;
|
||
return lower.startsWith("http") || lower.startsWith("/");
|
||
}
|
||
|
||
function getInitials(name: string): string {
|
||
const trimmed = name.trim();
|
||
if (!trimmed) return "?";
|
||
return trimmed.charAt(0);
|
||
}
|
||
|
||
type Props = {
|
||
restaurant: PublicRestaurant;
|
||
};
|
||
|
||
export default function RestaurantCard({ restaurant }: Props) {
|
||
const validLogo = isValidLogoUrl(restaurant.logo);
|
||
const [logoSrc, setLogoSrc] = useState<string>(validLogo && restaurant.logo ? restaurant.logo : FALLBACK_LOGO);
|
||
const showInitials = !validLogo || logoSrc === FALLBACK_LOGO;
|
||
|
||
return (
|
||
<Link
|
||
href={`/${restaurant.slug}`}
|
||
className={glassSurfaceCard(
|
||
"group flex items-center gap-4 p-4 transition-all duration-200 ease-out",
|
||
"hover:shadow-md active:scale-[0.98] outline-none [-webkit-tap-highlight-color:transparent]",
|
||
)}
|
||
>
|
||
<div className="relative shrink-0">
|
||
{showInitials ? (
|
||
<div className="flex size-16 items-center justify-center rounded-2xl bg-(--danak-orange-light) text-xl font-medium text-(--danak-orange)">{getInitials(restaurant.name)}</div>
|
||
) : (
|
||
<Image src={logoSrc} alt={restaurant.name} width={64} height={64} className="size-16 rounded-2xl bg-[#F2F2F9] object-cover ring-1 ring-black/5" onError={() => setLogoSrc(FALLBACK_LOGO)} />
|
||
)}
|
||
</div>
|
||
|
||
<div className="min-w-0 flex-1">
|
||
<div className="flex items-start justify-between gap-2">
|
||
<h2 className="truncate text-sm font-medium text-foreground">{restaurant.name}</h2>
|
||
</div>
|
||
|
||
{restaurant.address && (
|
||
<div className="mt-1.5 flex items-start gap-1.5 text-[#8C90A3]">
|
||
<Location stroke="currentColor" size={14} className="mt-0.5 shrink-0 text-(--danak-orange)" variant="Bold" />
|
||
<p className="line-clamp-2 text-xs leading-5">{restaurant.address?.trim()}</p>
|
||
</div>
|
||
)}
|
||
|
||
{restaurant.establishedYear != null && (
|
||
<p className="mt-1.5 text-[11px] text-[#8C90A3]">
|
||
سال تاسیس <span className="font-medium text-(--danak-orange)">{restaurant.establishedYear}</span>
|
||
</p>
|
||
)}
|
||
</div>
|
||
|
||
<ArrowLeft2 size={18} className="shrink-0 text-[#C4C7D4] transition-transform duration-200 group-hover:-translate-x-0.5 group-hover:text-(--danak-orange)" />
|
||
</Link>
|
||
);
|
||
}
|