Replace entire repo content with correct code from /root/shahikitchen-website/
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { X } from 'lucide-react';
|
||||
import type { MenuItem } from '@/domain/menu/entities';
|
||||
import { getDishIngredients } from '@/domain/menu/dish-details';
|
||||
import {
|
||||
applyNextImageFallback,
|
||||
dishImageUrl,
|
||||
getMenuPosterCandidates,
|
||||
getMenuVideoSrc,
|
||||
} from '@/lib/assets';
|
||||
|
||||
interface DishDetailsModalProps {
|
||||
item: MenuItem;
|
||||
description: string;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
labels: {
|
||||
ingredients: string;
|
||||
close: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default function DishDetailsModal({
|
||||
item,
|
||||
description,
|
||||
isOpen,
|
||||
onClose,
|
||||
labels,
|
||||
}: DishDetailsModalProps) {
|
||||
const videoSrc = getMenuVideoSrc(item);
|
||||
const imageSrc = item.image ? dishImageUrl(item.image) : null;
|
||||
const ingredients = getDishIngredients(item.id);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') onClose();
|
||||
},
|
||||
[onClose],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) return;
|
||||
document.body.style.overflow = 'hidden';
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
document.body.style.overflow = '';
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [isOpen, handleKeyDown]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="fixed inset-0 z-[1000] bg-black/45 backdrop-blur-[2px]"
|
||||
onClick={onClose}
|
||||
aria-hidden
|
||||
/>
|
||||
|
||||
<div
|
||||
className="fixed inset-0 z-[1010] flex items-end sm:items-center justify-center p-0 sm:p-6 pointer-events-none"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="dish-detail-title"
|
||||
>
|
||||
<div
|
||||
className="pointer-events-auto w-full sm:max-w-lg max-h-[92dvh] sm:max-h-[88dvh] overflow-y-auto rounded-t-3xl sm:rounded-2xl bg-[#FFFCF7] border border-[#EDE6D9] shadow-2xl shadow-[#101724]/15"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="relative bg-[#F2EDE4]">
|
||||
{videoSrc ? (
|
||||
<video
|
||||
src={videoSrc}
|
||||
autoPlay
|
||||
loop
|
||||
muted
|
||||
playsInline
|
||||
className="w-full h-[240px] sm:h-[280px] object-cover bg-[#F2EDE4]"
|
||||
/>
|
||||
) : imageSrc ? (
|
||||
<img
|
||||
src={imageSrc}
|
||||
alt={item.name}
|
||||
className="w-full h-[240px] sm:h-[280px] object-cover bg-[#F2EDE4]"
|
||||
onError={(e) => {
|
||||
applyNextImageFallback(
|
||||
e.target as HTMLImageElement,
|
||||
getMenuPosterCandidates(item),
|
||||
(e.target as HTMLImageElement).src,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full aspect-[4/3] flex items-center justify-center text-sm text-[#8A8478]">
|
||||
No media available
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
aria-label={labels.close}
|
||||
className="absolute top-3 right-3 flex h-9 w-9 items-center justify-center rounded-full bg-white/90 text-[#2C2A26] shadow-md border border-[#EDE6D9] hover:bg-white hover:text-[#0f5a4a] transition-colors"
|
||||
>
|
||||
<X className="h-4 w-4" aria-hidden />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="p-6 sm:p-7 space-y-5">
|
||||
<h2
|
||||
id="dish-detail-title"
|
||||
className="font-serif text-2xl sm:text-[26px] tracking-[-0.4px] text-[#2C2A26]"
|
||||
>
|
||||
{item.name}
|
||||
</h2>
|
||||
|
||||
{description && (
|
||||
<p className="text-[#6B665F] text-[15px] leading-relaxed">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{ingredients.length > 0 && (
|
||||
<div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-[0.2em] text-[#c99a2e] mb-3">
|
||||
{labels.ingredients}
|
||||
</h3>
|
||||
<ul className="space-y-2">
|
||||
{ingredients.map((ingredient) => (
|
||||
<li
|
||||
key={ingredient}
|
||||
className="flex items-start gap-2.5 text-[15px] text-[#2C2A26] leading-snug"
|
||||
>
|
||||
<span
|
||||
className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-[#B38B4D]"
|
||||
aria-hidden
|
||||
/>
|
||||
{ingredient}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user