Replace entire repo content with updated code from /root/shahikitchen-website/
This commit is contained in:
@@ -18,6 +18,8 @@ import { container } from '@/infrastructure/di/container';
|
||||
import { useCart } from '@/presentation/providers/cart-provider';
|
||||
import { useLanguage } from '@/presentation/providers/language-provider';
|
||||
import { getTranslation } from '@/presentation/i18n/translations';
|
||||
import { getMenuItemName } from '@/application/i18n/menu-localization';
|
||||
import { getMenuItemById } from '@/lib/menu-data';
|
||||
import CartInquiryModal from '@/components/CartInquiryModal';
|
||||
|
||||
export default function CartDrawer() {
|
||||
@@ -31,7 +33,7 @@ export default function CartDrawer() {
|
||||
clearCart,
|
||||
} = useCart();
|
||||
|
||||
const { language } = useLanguage();
|
||||
const { language, isRtl } = useLanguage();
|
||||
const t = getTranslation(language);
|
||||
const [inquiryMode, setInquiryMode] = useState<FulfillmentMode | null>(null);
|
||||
|
||||
@@ -53,11 +55,11 @@ export default function CartDrawer() {
|
||||
};
|
||||
|
||||
const handlePickupSubmit = (details: PickupInquiryDetails) => {
|
||||
openWhatsApp(buildPickupInquiryMessage(items, details, inquiryCopy));
|
||||
openWhatsApp(buildPickupInquiryMessage(items, details, inquiryCopy, language));
|
||||
};
|
||||
|
||||
const handleDeliverySubmit = (details: DeliveryInquiryDetails) => {
|
||||
openWhatsApp(buildDeliveryInquiryMessage(items, details, inquiryCopy));
|
||||
openWhatsApp(buildDeliveryInquiryMessage(items, details, inquiryCopy, language));
|
||||
};
|
||||
|
||||
if (!isOpen) return null;
|
||||
@@ -69,7 +71,11 @@ export default function CartDrawer() {
|
||||
onClick={closeCart}
|
||||
/>
|
||||
|
||||
<div className="fixed top-0 right-0 h-full w-full max-w-md bg-[#F8F5F0] z-[990] shadow-2xl flex flex-col">
|
||||
<div
|
||||
className={`fixed top-0 h-full w-full max-w-md bg-[#F8F5F0] z-[990] shadow-2xl flex flex-col ${
|
||||
isRtl ? 'left-0 border-r border-[#EDE6D9]' : 'right-0 border-l border-[#EDE6D9]'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between p-6 border-b border-[#EDE6D9]">
|
||||
<div className="flex items-center gap-3">
|
||||
<h2 className="text-2xl tracking-[-0.5px]">{t.cartDrawer.title}</h2>
|
||||
@@ -117,7 +123,12 @@ export default function CartDrawer() {
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between">
|
||||
<div>
|
||||
<h4 className="font-medium tracking-[-0.3px]">{item.name}</h4>
|
||||
<h4 className="font-medium tracking-[-0.3px]">
|
||||
{getMenuItemName(language, {
|
||||
id: item.id,
|
||||
name: getMenuItemById(item.id)?.name ?? item.name,
|
||||
})}
|
||||
</h4>
|
||||
<p className="text-sm text-[#6B665F]">
|
||||
{item.pricingMode === 'weight'
|
||||
? `${item.pricePerHalfKg ?? item.price} kr / ½ kg`
|
||||
@@ -132,7 +143,7 @@ export default function CartDrawer() {
|
||||
<div className="flex items-center gap-3 mt-3">
|
||||
<button
|
||||
onClick={() => updateQuantity(item.id, item.quantity - 1)}
|
||||
className="w-8 h-8 flex items-center justify-center border border-[#EDE6D9] rounded hover:bg-white transition"
|
||||
className="w-11 h-11 flex items-center justify-center border border-[#EDE6D9] rounded hover:bg-white transition touch-manipulation"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
@@ -141,7 +152,7 @@ export default function CartDrawer() {
|
||||
</span>
|
||||
<button
|
||||
onClick={() => updateQuantity(item.id, item.quantity + 1)}
|
||||
className="w-8 h-8 flex items-center justify-center border border-[#EDE6D9] rounded hover:bg-white transition"
|
||||
className="w-11 h-11 flex items-center justify-center border border-[#EDE6D9] rounded hover:bg-white transition touch-manipulation"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
@@ -161,7 +172,7 @@ export default function CartDrawer() {
|
||||
</div>
|
||||
|
||||
{items.length > 0 && (
|
||||
<div className="p-6 border-t border-[#EDE6D9] bg-white">
|
||||
<div className="p-6 pb-[max(1.5rem,env(safe-area-inset-bottom))] border-t border-[#EDE6D9] bg-white">
|
||||
<button
|
||||
onClick={clearCart}
|
||||
className="text-xs text-[#8A8478] hover:text-[#B38B4D] mb-3 underline"
|
||||
|
||||
@@ -6,9 +6,11 @@ import {
|
||||
CATERING_CATEGORY_ORDER,
|
||||
groupDishesByCategory,
|
||||
} from '@/lib/catering-data';
|
||||
import { buildCateringPackagePricingMessage } from '@/application/messaging/whatsapp-message-builder';
|
||||
import { container } from '@/infrastructure/di/container';
|
||||
import { useLanguage } from '@/lib/language-context';
|
||||
import { getTranslation } from '@/lib/translations';
|
||||
import { Users, UtensilsCrossed } from 'lucide-react';
|
||||
import { MessageCircle, Users, UtensilsCrossed } from 'lucide-react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
interface CateringPackageCardProps {
|
||||
@@ -26,6 +28,13 @@ export default function CateringPackageCard({ pkg, index = 0 }: CateringPackageC
|
||||
const packageDescription =
|
||||
(t.catering.packageDescriptions as Record<string, string>)?.[pkg.id] ?? pkg.description;
|
||||
|
||||
const handlePricingInquiry = () => {
|
||||
const template = (t.catering as { packagePricingInquiry?: string }).packagePricingInquiry;
|
||||
if (!template) return;
|
||||
const message = buildCateringPackagePricingMessage(packageName, template);
|
||||
container.messagingGateway.openWhatsApp(message);
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.article
|
||||
initial={{ opacity: 0, y: 28 }}
|
||||
@@ -67,16 +76,14 @@ export default function CateringPackageCard({ pkg, index = 0 }: CateringPackageC
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-5 rounded-2xl border border-[#c99a2e]/25 bg-[#fffdf8] px-4 py-3.5">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<span className="text-2xl font-medium tabular-nums tracking-[-0.5px] text-[#B38B4D]">
|
||||
{pkg.pricePerHead}
|
||||
</span>
|
||||
<span className="text-sm font-semibold text-[#8a6a25]">
|
||||
{t.catering.perHead} · {pkg.currency}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handlePricingInquiry}
|
||||
className="mb-5 flex w-full items-center justify-center gap-2 rounded-2xl border border-[#c99a2e]/35 bg-[#fffdf8] px-4 py-3.5 text-base font-semibold tracking-[-0.2px] text-[#B38B4D] transition-all hover:border-[#c99a2e] hover:bg-[#fff6dc] hover:text-[#8C6B3A] active:scale-[0.98]"
|
||||
>
|
||||
<MessageCircle className="h-4 w-4 shrink-0" aria-hidden />
|
||||
{t.catering.contactForPricing}
|
||||
</button>
|
||||
|
||||
<div className="mb-2 flex items-center gap-2 text-xs font-bold uppercase tracking-[0.18em] text-[#8a6a25]">
|
||||
<UtensilsCrossed className="h-3.5 w-3.5 text-[#c99a2e]" />
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
|
||||
interface DishDetailsModalProps {
|
||||
item: MenuItem;
|
||||
displayName: string;
|
||||
description: string;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
@@ -24,6 +25,7 @@ interface DishDetailsModalProps {
|
||||
|
||||
export default function DishDetailsModal({
|
||||
item,
|
||||
displayName,
|
||||
description,
|
||||
isOpen,
|
||||
onClose,
|
||||
@@ -83,7 +85,7 @@ export default function DishDetailsModal({
|
||||
) : imageSrc ? (
|
||||
<img
|
||||
src={imageSrc}
|
||||
alt={item.name}
|
||||
alt={displayName}
|
||||
className="w-full h-[240px] sm:h-[280px] object-cover bg-[#F2EDE4]"
|
||||
onError={(e) => {
|
||||
applyNextImageFallback(
|
||||
@@ -114,7 +116,7 @@ export default function DishDetailsModal({
|
||||
id="dish-detail-title"
|
||||
className="font-serif text-2xl sm:text-[26px] tracking-[-0.4px] text-[#2C2A26]"
|
||||
>
|
||||
{item.name}
|
||||
{displayName}
|
||||
</h2>
|
||||
|
||||
{description && (
|
||||
|
||||
+16
-12
@@ -28,7 +28,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const { totalItems, openCart } = useCart();
|
||||
const { totalItems: wishlistCount, openWishlist } = useWishlist();
|
||||
const { language } = useLanguage();
|
||||
const { language, isRtl } = useLanguage();
|
||||
const t = getTranslation(language);
|
||||
const pathname = usePathname();
|
||||
|
||||
@@ -91,7 +91,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
</Link>
|
||||
|
||||
{/* Desktop Navigation - Premium Mesmerizing Design */}
|
||||
<div className="hidden md:block flex-shrink-0">
|
||||
<div className="hidden lg:block flex-shrink-0 min-w-0">
|
||||
<div className="flex items-center rounded-full border border-[#c99a2e]/20 bg-white/60 px-2 py-1.5 backdrop-blur-3xl shadow-sm">
|
||||
<div className="relative flex items-center gap-1 text-sm font-medium text-[#101724]">
|
||||
{navLinks.map((link, index) => {
|
||||
@@ -127,7 +127,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
</div>
|
||||
|
||||
{/* Desktop Actions — Stunning Mesmerizing Buttons */}
|
||||
<div className="hidden md:flex items-center gap-3">
|
||||
<div className="hidden lg:flex items-center gap-3 shrink-0">
|
||||
{/* Wishlist Button */}
|
||||
<button
|
||||
onClick={openWishlist}
|
||||
@@ -168,11 +168,11 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
</div>
|
||||
|
||||
{/* Mobile Hamburger + Wishlist + Cart (compact, high touch target) */}
|
||||
<div className="md:hidden flex items-center gap-2">
|
||||
<div className="lg:hidden flex items-center gap-1.5 shrink-0">
|
||||
{/* MOBILE WISHLIST ICON */}
|
||||
<button
|
||||
onClick={openWishlist}
|
||||
className="relative flex items-center justify-center w-10 h-10 rounded-full hover:bg-[#F5F1E9] active:bg-[#EDE6D9] transition-colors"
|
||||
className="relative flex items-center justify-center w-11 h-11 rounded-full hover:bg-[#F5F1E9] active:bg-[#EDE6D9] transition-colors"
|
||||
aria-label={t.wishlist}
|
||||
>
|
||||
<Heart className={`h-5 w-5 ${wishlistCount > 0 ? 'text-[#c99a2e] fill-[#c99a2e]/30' : 'text-[#101724]'}`} />
|
||||
@@ -186,7 +186,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
{/* MOBILE CART ICON (always visible) */}
|
||||
<button
|
||||
onClick={openCart}
|
||||
className="relative flex items-center justify-center w-10 h-10 rounded-full hover:bg-[#F5F1E9] active:bg-[#EDE6D9] transition-colors"
|
||||
className="relative flex items-center justify-center w-11 h-11 rounded-full hover:bg-[#F5F1E9] active:bg-[#EDE6D9] transition-colors"
|
||||
aria-label="Open cart"
|
||||
>
|
||||
<ShoppingBag className="h-5 w-5 text-[#101724]" />
|
||||
@@ -199,7 +199,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="text-[#B38B4D] p-2 -mr-1 active:text-[#8C6B3A] transition-colors"
|
||||
className="flex items-center justify-center w-11 h-11 text-[#B38B4D] -me-1 active:text-[#8C6B3A] transition-colors"
|
||||
aria-label="Toggle menu"
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
@@ -219,7 +219,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
{/* Modern Mobile Menu Drawer (slide-in, animated, high-contrast, touch-friendly) - high z to always appear in front of hero banner video etc. */}
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<div className="md:hidden fixed inset-0 z-[9999]">
|
||||
<div className="lg:hidden fixed inset-0 z-[9999]">
|
||||
{/* Backdrop */}
|
||||
<motion.div
|
||||
className="absolute inset-0 bg-[#101724]/70 backdrop-blur-md"
|
||||
@@ -232,10 +232,14 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
|
||||
{/* Sliding Panel - modern, full-bleed on small phones, elegant on larger */}
|
||||
<motion.div
|
||||
className="absolute right-0 top-0 bottom-0 w-[82%] max-w-[340px] bg-[#fbf7ef] shadow-2xl border-l border-[#c99a2e]/10 flex flex-col overflow-y-auto z-[10000]"
|
||||
initial={{ x: '100%' }}
|
||||
className={`absolute top-0 bottom-0 w-[82%] max-w-[340px] bg-[#fbf7ef] shadow-2xl flex flex-col overflow-y-auto z-[10000] ${
|
||||
isRtl
|
||||
? 'left-0 border-r border-[#c99a2e]/10'
|
||||
: 'right-0 border-l border-[#c99a2e]/10'
|
||||
}`}
|
||||
initial={{ x: isRtl ? '-100%' : '100%' }}
|
||||
animate={{ x: 0 }}
|
||||
exit={{ x: '100%' }}
|
||||
exit={{ x: isRtl ? '-100%' : '100%' }}
|
||||
transition={{ type: 'spring', stiffness: 320, damping: 32 }}
|
||||
>
|
||||
{/* Header */}
|
||||
@@ -294,7 +298,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
</div>
|
||||
|
||||
{/* Secondary actions */}
|
||||
<div className="mt-auto px-5 pb-8 pt-4 border-t border-[#EDE6D9] bg-white/40 space-y-3">
|
||||
<div className="mt-auto px-5 pt-4 pb-[max(2rem,env(safe-area-inset-bottom))] border-t border-[#EDE6D9] bg-white/40 space-y-3">
|
||||
<Link
|
||||
href="/reserve"
|
||||
onClick={closeMenu}
|
||||
|
||||
@@ -151,7 +151,7 @@ export default function OrderDisplay() {
|
||||
{ id: 'T-01', source: 'table', label: 'Table 1', customer: 'Table 1', items: [{name: 'Shahi Paneer', qty: 1}, {name: 'Naan', qty: 3}], status: 'preparing', receivedAt: new Date(now.getTime() - 1000*60*8), etaMinutes: 7 },
|
||||
{ id: 'T-04', source: 'table', label: 'Table 4', customer: 'Table 4', items: [{name: 'Chicken Tikka', qty: 2}, {name: 'Rice', qty: 1}], status: 'review', receivedAt: new Date(now.getTime() - 1000*60*5), etaMinutes: 10 },
|
||||
{ id: 'T-06', source: 'table', label: 'Table 6', customer: 'Table 6', items: [{name: 'Lahore Sizzler', qty: 1}, {name: 'Naan', qty: 2}], status: 'packing', receivedAt: new Date(now.getTime() - 1000*60*3), etaMinutes: 5 },
|
||||
{ id: 'T-07', source: 'table', label: 'Table 7', customer: 'Table 7', items: [{name: 'Tikka Boti', qty: 1}, {name: 'Salad', qty: 1}], status: 'received', receivedAt: new Date(now.getTime() - 1000*60*1), etaMinutes: 12 },
|
||||
{ id: 'T-07', source: 'table', label: 'Table 7', customer: 'Table 7', items: [{name: 'Chicken Tikka', qty: 1}, {name: 'Salad', qty: 1}], status: 'received', receivedAt: new Date(now.getTime() - 1000*60*1), etaMinutes: 12 },
|
||||
|
||||
// Delivery Partners (online) - 8 orders (mix of platforms)
|
||||
{ id: 'FD-3921', source: 'foodora', label: 'Foodora #FD-3921', customer: 'Aisha K.', items: [{name: 'Lahore Pizza', qty: 1}, {name: 'Mango Lassi', qty: 2}], status: 'packing', receivedAt: new Date(now.getTime() - 1000*60*9), etaMinutes: 3 },
|
||||
@@ -166,7 +166,7 @@ export default function OrderDisplay() {
|
||||
// Pickup orders (whatsapp/phone) - 8 orders
|
||||
{ id: 'WA-4521', source: 'pickup', label: 'Pickup WA-4521', customer: 'Ahmed R.', items: [{name: 'Chicken Biryani', qty: 2}, {name: 'Raita', qty: 1}], status: 'preparing', receivedAt: new Date(now.getTime() - 1000*60*13), etaMinutes: 5 },
|
||||
{ id: 'PH-783', source: 'pickup', label: 'Pickup PH-783', customer: 'Sara M.', items: [{name: 'Veg Pizza', qty: 1}, {name: 'Garlic Naan', qty: 2}], status: 'packing', receivedAt: new Date(now.getTime() - 1000*60*6), etaMinutes: 2 },
|
||||
{ id: 'WA-4530', source: 'pickup', label: 'Pickup WA-4530', customer: 'Omar K.', items: [{name: 'Tikka Boti', qty: 1}], status: 'ready', receivedAt: new Date(now.getTime() - 1000*60*20), etaMinutes: 0 },
|
||||
{ id: 'WA-4530', source: 'pickup', label: 'Pickup WA-4530', customer: 'Omar K.', items: [{name: 'Chicken Tikka', qty: 1}], status: 'ready', receivedAt: new Date(now.getTime() - 1000*60*20), etaMinutes: 0 },
|
||||
{ id: 'WA-4535', source: 'pickup', label: 'Pickup WA-4535', customer: 'Fatima L.', items: [{name: 'Shahi Paneer', qty: 1}, {name: 'Naan', qty: 1}], status: 'preparing', receivedAt: new Date(now.getTime() - 1000*60*8), etaMinutes: 7 },
|
||||
{ id: 'PH-791', source: 'pickup', label: 'Pickup PH-791', customer: 'Hassan Q.', items: [{name: 'Daal Makhani', qty: 1}, {name: 'Rice', qty: 2}], status: 'review', receivedAt: new Date(now.getTime() - 1000*60*11), etaMinutes: 8 },
|
||||
{ id: 'WA-4542', source: 'pickup', label: 'Pickup WA-4542', customer: 'Ayesha S.', items: [{name: 'Samosa Keema', qty: 3}], status: 'packing', receivedAt: new Date(now.getTime() - 1000*60*4), etaMinutes: 3 },
|
||||
|
||||
@@ -12,6 +12,11 @@ import {
|
||||
import { menuCategories, allMenuItems, type MenuItem, type MenuCategory } from '@/lib/menu-data';
|
||||
import { useLanguage } from '@/lib/language-context';
|
||||
import { getTranslation } from '@/lib/translations';
|
||||
import {
|
||||
getMenuItemDescription,
|
||||
getMenuItemName,
|
||||
} from '@/application/i18n/menu-localization';
|
||||
import type { Language } from '@/domain/language/entities';
|
||||
|
||||
interface ScreenDisplayProps {
|
||||
screen: 1 | 2;
|
||||
@@ -102,9 +107,20 @@ function SpiceParticles() {
|
||||
);
|
||||
}
|
||||
|
||||
function MenuCard({ item, isHighlighted, t }: { item: MenuItem; isHighlighted?: boolean; t: any }) {
|
||||
function MenuCard({
|
||||
item,
|
||||
isHighlighted,
|
||||
language,
|
||||
t,
|
||||
}: {
|
||||
item: MenuItem;
|
||||
isHighlighted?: boolean;
|
||||
language: Language;
|
||||
t: ReturnType<typeof getTranslation>;
|
||||
}) {
|
||||
const poster = getMenuPosterSrc(item, 'optimized');
|
||||
const desc = (t as any).menuDescriptions?.[item.id] || item.description || '';
|
||||
const displayName = getMenuItemName(language, item);
|
||||
const desc = getMenuItemDescription(language, t, item);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
@@ -119,7 +135,7 @@ function MenuCard({ item, isHighlighted, t }: { item: MenuItem; isHighlighted?:
|
||||
<div className="relative h-36 bg-[#F2EDE4] overflow-hidden">
|
||||
<motion.img
|
||||
src={poster}
|
||||
alt={item.name}
|
||||
alt={displayName}
|
||||
className="absolute inset-0 w-full h-full object-cover"
|
||||
animate={{ scale: [1, 1.018, 1] }}
|
||||
transition={{ duration: 8.5, repeat: Infinity, ease: 'easeInOut' }}
|
||||
@@ -147,7 +163,7 @@ function MenuCard({ item, isHighlighted, t }: { item: MenuItem; isHighlighted?:
|
||||
|
||||
<div className="p-3.5 flex-1 flex flex-col">
|
||||
<div className="font-medium tracking-[-0.3px] text-[15px] leading-tight text-[#2C2A26] mb-1 line-clamp-1 group-hover:text-[#B38B4D] transition-colors">
|
||||
{item.name}
|
||||
{displayName}
|
||||
</div>
|
||||
<p className="text-[#6B665F] text-[12px] leading-snug line-clamp-2 flex-1">
|
||||
{desc}
|
||||
@@ -257,7 +273,8 @@ export default function ScreenDisplay({ screen }: ScreenDisplayProps) {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const translatedDesc = current ? ((t as any).menuDescriptions?.[current.id] || current.description) : '';
|
||||
const currentDisplayName = current ? getMenuItemName(language, current) : '';
|
||||
const translatedDesc = current ? getMenuItemDescription(language, t, current) : '';
|
||||
|
||||
// =====================================================
|
||||
// CONTINUOUS MENU REEL (one line, loop like a film reel) - items move LEFT
|
||||
@@ -282,6 +299,7 @@ export default function ScreenDisplay({ screen }: ScreenDisplayProps) {
|
||||
// ReelCard: large poster + number+name on left, price on right (opposite side, same line) so price is always clearly visible as cards move left in the reel. Sized big for 43" TV distance viewing.
|
||||
function ReelCard({ item, number }: { item: MenuItem; number: number }) {
|
||||
const numStr = String(number).padStart(2, '0');
|
||||
const reelName = getMenuItemName(language, item);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -291,7 +309,7 @@ export default function ScreenDisplay({ screen }: ScreenDisplayProps) {
|
||||
<div className="relative bg-[#F2EDE4]" style={{ height: '320px' }}>
|
||||
<motion.img
|
||||
src={getMenuPosterSrc(item, 'optimized')}
|
||||
alt={item.name}
|
||||
alt={reelName}
|
||||
className="w-full h-full object-cover"
|
||||
animate={{ scale: [1, 1.015, 1] }}
|
||||
transition={{ duration: 6, repeat: Infinity, ease: 'easeInOut' }}
|
||||
@@ -304,7 +322,7 @@ export default function ScreenDisplay({ screen }: ScreenDisplayProps) {
|
||||
</div>
|
||||
<div className="px-4 py-5 flex items-baseline justify-between gap-4">
|
||||
<div className="font-serif text-3xl tracking-[-0.5px] leading-none text-[#2C2A26]">
|
||||
{numStr}. {item.name}
|
||||
{numStr}. {reelName}
|
||||
</div>
|
||||
<div className="text-[#B38B4D] text-2xl font-semibold tracking-tight whitespace-nowrap">
|
||||
{item.price} kr
|
||||
@@ -381,7 +399,7 @@ export default function ScreenDisplay({ screen }: ScreenDisplayProps) {
|
||||
<motion.img
|
||||
key={`${current.id}-poster`}
|
||||
src={getMenuPosterSrc(current, 'optimized')}
|
||||
alt={current.name}
|
||||
alt={currentDisplayName}
|
||||
className="absolute inset-0 w-full h-full object-cover"
|
||||
initial={{ opacity: 0, scale: 1 }}
|
||||
animate={{ opacity: 1, scale: [1, 1.06, 1] }}
|
||||
@@ -420,7 +438,7 @@ export default function ScreenDisplay({ screen }: ScreenDisplayProps) {
|
||||
</div>
|
||||
|
||||
<h1 className="font-serif text-[56px] md:text-[64px] leading-[0.88] tracking-[-3.2px] mb-2 text-[#B38B4D] drop-shadow-[0_0_10px_rgba(179,139,77,0.85)]">
|
||||
{current.name}
|
||||
{currentDisplayName}
|
||||
</h1>
|
||||
|
||||
<div className="flex items-baseline gap-2 mb-4">
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useLanguage } from '@/presentation/providers/language-provider';
|
||||
import { getTranslation } from '@/presentation/i18n/translations';
|
||||
import { getMenuPosterSrc, applyNextImageFallback, getMenuPosterCandidates } from '@/lib/assets';
|
||||
import { getMenuItemById } from '@/lib/menu-data';
|
||||
import { getMenuItemName } from '@/application/i18n/menu-localization';
|
||||
import { buildCartLineFromMenuItem } from '@/application/cart/cart-line-builder';
|
||||
|
||||
export default function WishlistDrawer() {
|
||||
@@ -20,7 +21,7 @@ export default function WishlistDrawer() {
|
||||
} = useWishlist();
|
||||
|
||||
const { addToCart } = useCart();
|
||||
const { language } = useLanguage();
|
||||
const { language, isRtl } = useLanguage();
|
||||
const t = getTranslation(language);
|
||||
|
||||
if (!isOpen) return null;
|
||||
@@ -43,7 +44,11 @@ export default function WishlistDrawer() {
|
||||
onClick={closeWishlist}
|
||||
/>
|
||||
|
||||
<div className="fixed top-0 right-0 h-full w-full max-w-md bg-[#F8F5F0] z-[985] shadow-2xl flex flex-col">
|
||||
<div
|
||||
className={`fixed top-0 h-full w-full max-w-md bg-[#F8F5F0] z-[985] shadow-2xl flex flex-col ${
|
||||
isRtl ? 'left-0 border-r border-[#EDE6D9]' : 'right-0 border-l border-[#EDE6D9]'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between p-6 border-b border-[#EDE6D9]">
|
||||
<div className="flex items-center gap-3">
|
||||
<Heart className="h-5 w-5 text-[#c99a2e] fill-[#c99a2e]/20" />
|
||||
@@ -88,7 +93,14 @@ export default function WishlistDrawer() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-5">
|
||||
{items.map((item) => (
|
||||
{items.map((item) => {
|
||||
const menuItem = getMenuItemById(item.id);
|
||||
const displayName = getMenuItemName(language, {
|
||||
id: item.id,
|
||||
name: menuItem?.name ?? item.name,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex gap-4 rounded-2xl border border-[#EDE6D9] bg-white p-4"
|
||||
@@ -96,7 +108,7 @@ export default function WishlistDrawer() {
|
||||
<div className="h-20 w-20 shrink-0 overflow-hidden rounded-xl bg-[#F2EDE4]">
|
||||
<img
|
||||
src={getMenuPosterSrc(item)}
|
||||
alt={item.name}
|
||||
alt={displayName}
|
||||
className="h-full w-full object-cover"
|
||||
loading="lazy"
|
||||
onError={(e) => {
|
||||
@@ -112,7 +124,7 @@ export default function WishlistDrawer() {
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex justify-between gap-2">
|
||||
<h4 className="font-medium tracking-[-0.3px] text-[#101724] truncate">
|
||||
{item.name}
|
||||
{displayName}
|
||||
</h4>
|
||||
<span className="shrink-0 text-right font-medium text-[#B38B4D] tabular-nums text-sm leading-tight">
|
||||
{(() => {
|
||||
@@ -147,13 +159,14 @@ export default function WishlistDrawer() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{items.length > 0 && (
|
||||
<div className="p-6 border-t border-[#EDE6D9] bg-white">
|
||||
<div className="p-6 pb-[max(1.5rem,env(safe-area-inset-bottom))] border-t border-[#EDE6D9] bg-white">
|
||||
<p className="text-xs text-center text-[#6B665F] mb-4">
|
||||
{t.wishlistDrawer.hint}
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user