Add /products (list + detail) and /blog (list + detail) routes backed by the real Meshkee API, a real category-hierarchy mega menu (level 2/3 only), debounced instant search proxied through a same-origin API route, and tel:-link fallbacks on product cards when no price is set. Also fixes Product price normalization to read the real API shape instead of a guessed one, and hardens product linking against catalog sources that don't expose a slug. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
38 lines
942 B
TypeScript
38 lines
942 B
TypeScript
type PlaceholderProps = {
|
|
src: string;
|
|
alt?: string;
|
|
width: string;
|
|
height?: string;
|
|
label?: string;
|
|
className?: string;
|
|
fit?: "cover" | "contain";
|
|
};
|
|
|
|
export function Placeholder({
|
|
src,
|
|
alt = "",
|
|
width,
|
|
height,
|
|
label,
|
|
className = "",
|
|
fit = "cover",
|
|
}: PlaceholderProps) {
|
|
return (
|
|
<div
|
|
className={`relative flex shrink-0 items-center justify-center overflow-hidden border border-dashed border-red-muted/60 bg-red-light/40 ${className}`}
|
|
style={{ width, ...(height ? { height } : {}) }}
|
|
>
|
|
<img
|
|
src={src}
|
|
alt={alt}
|
|
className={`absolute inset-0 h-full w-full ${fit === "contain" ? "object-contain" : "object-cover"}`}
|
|
/>
|
|
{label && (
|
|
<span className="font-display pointer-events-none relative z-10 rounded bg-white/70 px-1.5 py-0.5 text-xs tracking-wider text-red-dark/50 uppercase">
|
|
{label}
|
|
</span>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|