Files

508 lines
27 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import React, { useState, useEffect, useRef } from 'react';
import { motion } from 'framer-motion';
import {
Clock, Users, Bike, Package, UtensilsCrossed, CheckCircle,
AlertCircle, Timer, ArrowRight
} from 'lucide-react';
import { useLanguage } from '@/lib/language-context';
import { getTranslation } from '@/lib/translations';
import type {
KitchenOrder as Order,
KitchenOrderItem as OrderItem,
OrderStatus,
} from '@/domain/kitchen-order/entities';
import { ORDER_STATUS_PIPELINE } from '@/domain/kitchen-order/entities';
export type { Order, OrderItem };
const STATUS_ORDER = ORDER_STATUS_PIPELINE;
function getStatusMeta(status: OrderStatus, t: any) {
const statuses = t.screen?.statuses || {
received: 'Order Received',
review: 'In Review',
preparing: 'Preparing',
packing: 'Packing / Plating',
ready: 'Ready',
};
const colors: Record<OrderStatus, string> = {
received: 'bg-blue-100 text-blue-800 border-blue-200',
review: 'bg-amber-100 text-amber-800 border-amber-200',
preparing: 'bg-orange-100 text-orange-800 border-orange-200',
packing: 'bg-purple-100 text-purple-800 border-purple-200',
ready: 'bg-emerald-100 text-emerald-800 border-emerald-200',
};
const icons: Record<OrderStatus, React.ReactNode> = {
received: <AlertCircle className="w-4 h-4" />,
review: <Clock className="w-4 h-4" />,
preparing: <UtensilsCrossed className="w-4 h-4" />,
packing: <Package className="w-4 h-4" />,
ready: <CheckCircle className="w-4 h-4" />,
};
return {
label: statuses[status] || status,
color: colors[status],
icon: icons[status],
progress: STATUS_ORDER.indexOf(status) / (STATUS_ORDER.length - 1),
};
}
function getSourceMeta(source: Order['source']) {
if (source === 'table') return { icon: <Users className="w-4 h-4" />, label: 'Restaurant', color: '#B38B4D' };
if (source === 'foodora') return { icon: <Bike className="w-4 h-4" />, label: 'Foodora', color: '#E30613' };
if (source === 'uber') return { icon: <Bike className="w-4 h-4" />, label: 'Uber Eats', color: '#000000' };
if (source === 'wolt') return { icon: <Bike className="w-4 h-4" />, label: 'Wolt', color: '#00C2E0' };
if (source === 'pickup') return { icon: <Package className="w-4 h-4" />, label: 'Pickup', color: '#B38B4D' };
return { icon: <Bike className="w-4 h-4" />, label: 'Delivery', color: '#B38B4D' };
}
// Beautiful subtle particles (adapted from ScreenDisplay for order theme - gold "steam" specks)
function OrderParticles() {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d', { alpha: true });
if (!ctx) return;
let width = window.innerWidth;
let height = window.innerHeight;
canvas.width = width;
canvas.height = height;
const particles = Array.from({ length: 28 }, () => ({
x: Math.random() * width,
y: Math.random() * height * 0.85,
vx: (Math.random() - 0.5) * 0.12,
vy: -0.08 - Math.random() * 0.12,
size: 1.0 + Math.random() * 1.6,
alpha: 0.08 + Math.random() * 0.16,
phase: Math.random() * Math.PI * 2,
speed: 0.012 + Math.random() * 0.009,
}));
const onResize = () => {
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width;
canvas.height = height;
};
window.addEventListener('resize', onResize);
let rafId: number;
const draw = () => {
ctx.clearRect(0, 0, width, height);
for (let i = 0; i < particles.length; i++) {
const p = particles[i];
p.x += p.vx + Math.sin(p.phase) * 0.04;
p.y += p.vy;
p.phase += p.speed;
if (p.y < -8) {
p.y = height * 0.88 + Math.random() * 30;
p.x = Math.random() * width;
}
if (p.x < 0) p.x = width;
if (p.x > width) p.x = 0;
ctx.fillStyle = `hsla(38, 68%, 52%, ${p.alpha})`;
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
ctx.fill();
}
rafId = requestAnimationFrame(draw);
};
draw();
return () => {
cancelAnimationFrame(rafId);
window.removeEventListener('resize', onResize);
};
}, []);
return (
<canvas
ref={canvasRef}
className="fixed inset-0 pointer-events-none z-[1] opacity-60 mix-blend-multiply"
/>
);
}
export default function OrderDisplay() {
const { language } = useLanguage();
const t = getTranslation(language);
const [orders, setOrders] = useState<Order[]>(() => {
const now = new Date();
return [
// Restaurant orders (tables) - 8 orders
{ id: 'T-05', source: 'table', label: 'Table 5', customer: 'Table 5', items: [{name: 'Butter Chicken', qty: 1}, {name: 'Garlic Naan', qty: 2}], status: 'preparing', receivedAt: new Date(now.getTime() - 1000*60*14), etaMinutes: 6 },
{ id: 'T-12', source: 'table', label: 'Table 12', customer: 'Table 12', items: [{name: 'Lamb Rogan Josh', qty: 2}, {name: 'Biryani', qty: 1}], status: 'ready', receivedAt: new Date(now.getTime() - 1000*60*22), etaMinutes: 0 },
{ id: 'T-03', source: 'table', label: 'Table 3', customer: 'Table 3', items: [{name: 'Samosa Chat', qty: 2}, {name: 'Chana Chat', qty: 1}], status: 'packing', receivedAt: new Date(now.getTime() - 1000*60*11), etaMinutes: 4 },
{ id: 'T-08', source: 'table', label: 'Table 8', customer: 'Table 8', items: [{name: 'Daal Makhani', qty: 1}, {name: 'Rice', qty: 2}], status: 'ready', receivedAt: new Date(now.getTime() - 1000*60*18), etaMinutes: 0 },
{ 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: '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 },
{ id: 'W-884', source: 'wolt', label: 'Wolt #W-884', customer: 'Erik S.', items: [{name: 'Paneer Roll', qty: 3}], status: 'review', receivedAt: new Date(now.getTime() - 1000*60*4), etaMinutes: 11 },
{ id: 'FD-3928', source: 'foodora', label: 'Foodora #FD-3928', customer: 'Maria L.', items: [{name: 'Shahi Burger', qty: 2}, {name: 'Coca-Cola', qty: 2}], status: 'preparing', receivedAt: new Date(now.getTime() - 1000*60*7), etaMinutes: 8 },
{ id: 'UB-551', source: 'uber', label: 'Uber Eats #UB-551', customer: 'Johan P.', items: [{name: 'Chicken Tikka', qty: 1}, {name: 'Keema Naan', qty: 1}], status: 'received', receivedAt: new Date(now.getTime() - 1000*60*2), etaMinutes: 14 },
{ id: 'FD-3935', source: 'foodora', label: 'Foodora #FD-3935', customer: 'Omar B.', items: [{name: 'Butter Chicken', qty: 1}, {name: 'Naan', qty: 2}], status: 'preparing', receivedAt: new Date(now.getTime() - 1000*60*10), etaMinutes: 4 },
{ id: 'W-892', source: 'wolt', label: 'Wolt #W-892', customer: 'Lina T.', items: [{name: 'Veg Pizza', qty: 1}, {name: 'Lassi', qty: 1}], status: 'packing', receivedAt: new Date(now.getTime() - 1000*60*6), etaMinutes: 6 },
{ id: 'UB-562', source: 'uber', label: 'Uber Eats #UB-562', customer: 'Peter H.', items: [{name: 'Lamb Rogan Josh', qty: 1}, {name: 'Rice', qty: 2}], status: 'review', receivedAt: new Date(now.getTime() - 1000*60*12), etaMinutes: 9 },
{ id: 'FD-3940', source: 'foodora', label: 'Foodora #FD-3940', customer: 'Sara N.', items: [{name: 'Tikka Boti Roll', qty: 2}], status: 'packing', receivedAt: new Date(now.getTime() - 1000*60*15), etaMinutes: 2 },
// 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: '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 },
{ id: 'PH-802', source: 'pickup', label: 'Pickup PH-802', customer: 'Bilal M.', items: [{name: 'Lamm Vindaloo', qty: 1}, {name: 'Naan', qty: 2}], status: 'preparing', receivedAt: new Date(now.getTime() - 1000*60*9), etaMinutes: 6 },
{ id: 'WA-4550', source: 'pickup', label: 'Pickup WA-4550', customer: 'Zainab P.', items: [{name: 'Jalebi', qty: 2}, {name: 'Kulfi', qty: 1}], status: 'received', receivedAt: new Date(now.getTime() - 1000*60*1), etaMinutes: 13 },
];
});
const [lastUpdate, setLastUpdate] = useState(new Date());
const [liveClock, setLiveClock] = useState(new Date());
// Live clock
useEffect(() => {
const id = setInterval(() => setLiveClock(new Date()), 1000);
return () => clearInterval(id);
}, []);
// Simulate live backend updates (replace with real fetch / WebSocket / polling when ready)
useEffect(() => {
const interval = setInterval(() => {
setOrders(prev => {
let updated = [...prev];
const now = new Date();
// Occasionally advance a random non-ready order
if (Math.random() < 0.65) {
const candidates = updated
.map((o, i) => ({o, i}))
.filter(({o}) => o.status !== 'ready');
if (candidates.length > 0) {
const pick = candidates[Math.floor(Math.random() * candidates.length)];
const currIdx = STATUS_ORDER.indexOf(pick.o.status);
if (currIdx < STATUS_ORDER.length - 1) {
updated[pick.i] = {
...pick.o,
status: STATUS_ORDER[currIdx + 1],
};
}
}
}
// Occasionally add a new incoming order (allow up to ~30 total so each category can have 6-10+ for reels)
if (Math.random() < 0.28 && updated.length < 30) {
const sources: Order['source'][] = ['table', 'foodora', 'wolt', 'uber', 'pickup'];
const src = sources[Math.floor(Math.random() * sources.length)];
const isTable = src === 'table';
const isPickup = src === 'pickup';
const num = Math.floor(1000 + Math.random() * 9000);
const newOrder: Order = {
id: isTable ? `T-${Math.floor(1+Math.random()*14)}` : isPickup ? `WA-${num}` : `${src.toUpperCase().slice(0,2)}-${num}`,
source: src,
label: isTable ? `Table ${Math.floor(1+Math.random()*14)}` : isPickup ? `Pickup WA-${num}` : `${src.charAt(0).toUpperCase() + src.slice(1)} #${src.slice(0,2).toUpperCase()}-${num}`,
customer: isTable ? `Table ${Math.floor(1+Math.random()*14)}` : isPickup ? ['Ahmed R.', 'Sara M.', 'Omar K.', 'Fatima L.'][Math.floor(Math.random()*4)] : ['A. Khan', 'S. Patel', 'L. Berg', 'M. Lind'][Math.floor(Math.random()*4)],
items: [
{ name: ['Butter Chicken','Lahore Pizza','Lamb Rogan Josh','Shahi Paneer','Tikka Boti Roll'][Math.floor(Math.random()*5)], qty: 1 + Math.floor(Math.random()*2) },
{ name: ['Naan','Rice','Lassi','Samosa','Salad'][Math.floor(Math.random()*5)], qty: 1 },
],
status: 'received',
receivedAt: now,
etaMinutes: 10 + Math.floor(Math.random() * 8),
};
updated = [newOrder, ...updated].slice(0, 30);
}
// Occasionally remove a very old ready order (simulates pickup / serve)
if (Math.random() < 0.22) {
const readyIdx = updated.findIndex(o => o.status === 'ready' && (now.getTime() - o.receivedAt.getTime()) > 1000*60*3);
if (readyIdx !== -1) updated.splice(readyIdx, 1);
}
return updated;
});
setLastUpdate(new Date());
}, 6200); // ~every 6s for mesmerizing live feel
return () => clearInterval(interval);
}, []);
// Group into the three required sections
const restaurantOrders = orders.filter(o => o.source === 'table').sort((a,b) => b.receivedAt.getTime() - a.receivedAt.getTime());
const deliveryOrders = orders.filter(o => ['foodora', 'uber', 'wolt', 'other'].includes(o.source)).sort((a,b) => b.receivedAt.getTime() - a.receivedAt.getTime());
const pickupOrders = orders.filter(o => o.source === 'pickup').sort((a,b) => b.receivedAt.getTime() - a.receivedAt.getTime());
const readyOrders = orders.filter(o => o.status === 'ready');
const formatTime = (date: Date) => date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const getElapsed = (date: Date) => {
const mins = Math.floor((Date.now() - date.getTime()) / 60000);
return `${mins} ${t.screen?.elapsed || 'min'}`;
};
const screenLabel = t.screen?.display3 || 'DISPLAY 3';
// Helper to render a vertical looping reel for a list of orders.
// Viewport h-full (fills remaining screen height after headers).
// Cards fixed px height => browser zoom changes # visible (fewer on zoom-in, more on zoom-out), like screen2.
// Duplicates list for seamless upward CSS loop when count > visible.
// Always fills screen top-to-bottom with no whitespace.
const renderOrderReel = (ordersList: Order[], sectionLabel: string, sectionIcon: React.ReactNode) => {
const count = ordersList.length;
const shouldLoop = count > 3;
const displayList = shouldLoop ? [...ordersList, ...ordersList] : ordersList;
const duration = shouldLoop ? `${count * REEL_TIME_PER_ITEM}s` : undefined;
return (
<div className="flex flex-col h-full">
<div className="flex items-center gap-3 mb-3 px-1 flex-none">
{sectionIcon}
<div className="font-medium tracking-[2px] text-sm text-[#B38B4D]">{sectionLabel}</div>
<div className="flex-1 h-px bg-[#EDE6D9]" />
<div className="text-xs text-[#6B665F] tabular-nums">{count} ACTIVE</div>
</div>
<div
className="reel-viewport h-full overflow-hidden"
>
<div
className="order-reel-track"
style={{
gap: '8px',
animationDuration: duration,
// If not looping, no animation
animation: shouldLoop ? undefined : 'none'
}}
>
{displayList.map((order, idx) => {
const meta = getStatusMeta(order.status, t);
const srcMeta = getSourceMeta(order.source);
const elapsed = getElapsed(order.receivedAt);
const isReady = order.status === 'ready';
// Card with FIXED height in px. + h-full viewport (fills screen) means zoom in: fewer visible/column, zoom out: more visible. No whitespace, max top-bottom.
return (
<div
key={`${order.id}-${idx}`}
className={`group relative bg-white rounded-2xl border shadow-md overflow-hidden flex flex-col ${isReady ? 'border-emerald-300 ring-1 ring-emerald-200' : 'border-[#EDE6D9]'}`}
style={{ height: `${REEL_CARD_HEIGHT}px` }}
>
<div className="px-3 pt-2 pb-1 flex items-start justify-between gap-2 flex-none">
<div className="min-w-0">
<div className="font-mono text-lg tracking-[-0.5px] font-semibold text-[#2C2A26] leading-none truncate">
{order.label}
</div>
<div className="text-[10px] text-[#6B665F] mt-0.5 tracking-[0.3px] truncate">{order.customer} {elapsed}</div>
</div>
<div className={`px-2 py-0.5 rounded-full text-[10px] font-medium tracking-wider border flex items-center gap-1 whitespace-nowrap flex-none ${meta.color}`}>
{meta.icon} {meta.label.toUpperCase().slice(0,6)}
</div>
</div>
{/* Compact items */}
<div className="px-3 pb-1 text-xs text-[#2C2A26]/90 flex-1 overflow-hidden">
{order.items.slice(0,2).map((it, i) => (
<div key={i} className="flex justify-between leading-tight py-px">
<span className="truncate">{it.qty}× {it.name}</span>
</div>
))}
{order.items.length > 2 && <div className="text-[10px] text-[#6B665F]">+{order.items.length-2} more</div>}
</div>
{/* Compact progress */}
<div className="px-3 pb-2 pt-0.5 border-t border-[#EDE6D9]/60 bg-[#F8F5F0]/50 flex items-center gap-2 flex-none">
<div className="flex-1 h-1 bg-[#EDE6D9] rounded overflow-hidden">
<div
className="h-full transition-all"
style={{
width: `${meta.progress * 100}%`,
background: srcMeta.color
}}
/>
</div>
<div className="text-[10px] font-medium whitespace-nowrap tabular-nums" style={{ color: srcMeta.color }}>
{isReady ? 'READY' : `${order.etaMinutes}m`}
</div>
</div>
{isReady && (
<div className="absolute top-1 right-1 px-2 py-0.5 bg-emerald-600 text-white text-[9px] tracking-widest rounded font-semibold">READY</div>
)}
</div>
);
})}
</div>
</div>
</div>
);
};
// Reel settings for screen3 vertical marquees - dynamic with zoom like screen2
// Fixed card height in px so that browser zoom in/out changes how many cards fit vertically in the column (less when zoom in, more when zoom out).
// The reel viewport uses 100% of available column height (after section header) to fill the screen with no whitespace.
const REEL_CARD_HEIGHT = 120; // px per order card - tune for ~3-5 at 100% on 43" TV. Zoom affects visible count.
const REEL_TIME_PER_ITEM = 6; // seconds per order in the animation - slow upward movement
return (
<div className="h-screen bg-[#F8F5F0] text-[#2C2A26] overflow-hidden select-none flex flex-col screen-root">
<OrderParticles />
{/* Mesmerizing top bar - luxurious, welcoming, eye-catching for customers & riders. Taller, pulsing LIVE, centered tagline, elegant depth for 43" kiosk appeal. */}
<div className="relative z-20 h-20 border-b border-[#EDE6D9]/50 bg-gradient-to-b from-[#F8F5F0] via-[#F8F5F0]/98 to-[#F8F5F0]/95 backdrop-blur-xl flex items-center px-10 text-sm flex-none shadow-[0_2px_8px_rgba(0,0,0,0.03)]">
<div className="flex items-center gap-5">
{/* Brand with depth and elegance */}
<div className="flex items-baseline gap-1.5">
<div className="font-serif text-[28px] tracking-[-2.2px] text-[#2C2A26] drop-shadow-sm">SHAHI KITCHEN</div>
<div className="text-[9px] text-[#B38B4D] tracking-[2px] font-medium -mb-1">EST. 2016</div>
</div>
{/* Elegant status badges */}
<div className="flex items-center gap-2">
<div className="text-[11px] px-3.5 py-1 rounded-full border border-[#B38B4D]/60 text-[#B38B4D] tracking-[3px] font-medium bg-white/60 backdrop-blur-sm">
{screenLabel}
</div>
<motion.div
animate={{ scale: [1, 1.08, 1], opacity: [0.9, 1, 0.9] }}
transition={{ duration: 2.2, repeat: Infinity, ease: "easeInOut" }}
className="flex items-center gap-1.5 px-3 py-1 rounded-full bg-[#B38B4D] text-white text-[10px] tracking-[2.5px] font-semibold shadow-sm"
>
<div className="w-1.5 h-1.5 rounded-full bg-white animate-pulse" />
LIVE
</motion.div>
</div>
</div>
<div className="flex-1" />
{/* Centered mesmerizing tagline */}
<div className="hidden md:block text-center">
<div className="text-[11px] tracking-[4.5px] text-[#B38B4D]/70 font-medium">YOUR JOURNEY TO FLAVOR REAL-TIME MAGIC</div>
</div>
<div className="flex-1" />
{/* Right info - elegant and clear */}
<div className="flex items-center gap-7 text-[#6B665F] tracking-[1.5px] text-xs">
<div className="flex items-center gap-2.5">
<div>ASKIM</div>
<div className="w-px h-2.5 bg-[#EDE6D9]" />
<div>BACKAPLAN</div>
</div>
<div className="h-3 w-px bg-[#EDE6D9]/70" />
<div className="font-mono text-[#B38B4D] text-sm tracking-widest tabular-nums">
{liveClock.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'})}
</div>
<div className="text-[10px] px-2.5 py-0.5 rounded bg-[#B38B4D]/10 text-[#B38B4D] tracking-[1.5px]">
{t.screen?.prepared?.toUpperCase() || 'FRESHLY PREPARED'}
</div>
</div>
</div>
{/* Hero header with beautiful typography and live feel */}
<div className="relative z-10 bg-[#101724] text-white flex-none py-5 px-9 border-b border-white/10">
<div className="max-w-[1680px] mx-auto flex items-end justify-between">
<div>
<div className="inline-flex items-center gap-2 rounded-full bg-white/10 px-4 py-1 text-xs tracking-[3.5px] mb-2 border border-white/20">
{t.screen?.orderBoard || 'LIVE ORDER BOARD'}
</div>
<h1 className="font-serif text-[42px] md:text-[52px] leading-[0.9] tracking-[-2.2px] text-white">
{t.screen?.orderSubtitle || 'Delivery • Pickup • Restaurant — live for riders & guests'}
</h1>
<p className="mt-1.5 text-white/60 tracking-[0.5px] text-sm">
Delivery Partners Pickup (WhatsApp/Phone) Restaurant Tables Real-time kitchen progress
</p>
</div>
<div className="text-right text-sm">
<div className="text-[#B38B4D] tracking-[2px] text-xs mb-0.5">LAST SYNC</div>
<div className="font-mono text-lg text-white/90">{formatTime(lastUpdate)}</div>
<div className="text-[10px] text-white/50 mt-0.5">{t.screen?.liveUpdates || 'Live updates • Backend integration coming soon'}</div>
</div>
</div>
</div>
{/* Stats bar - beautiful metrics with motion - three sections */}
<div className="relative z-10 bg-[#F8F5F0] border-b border-[#EDE6D9]/60 py-3 px-9 flex-none">
<div className="max-w-[1680px] mx-auto grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
<div className="flex items-center gap-3">
<div className="text-[#B38B4D]"><Users className="w-5 h-5" /></div>
<div>
<div className="font-medium text-lg leading-none">{restaurantOrders.length}</div>
<div className="text-[#6B665F] text-xs tracking-[1px]">RESTAURANT ORDERS</div>
</div>
</div>
<div className="flex items-center gap-3">
<div className="text-[#B38B4D]"><Bike className="w-5 h-5" /></div>
<div>
<div className="font-medium text-lg leading-none">{deliveryOrders.length}</div>
<div className="text-[#6B665F] text-xs tracking-[1px]">DELIVERY PARTNERS</div>
</div>
</div>
<div className="flex items-center gap-3">
<div className="text-[#B38B4D]"><Package className="w-5 h-5" /></div>
<div>
<div className="font-medium text-lg leading-none">{pickupOrders.length}</div>
<div className="text-[#6B665F] text-xs tracking-[1px]">PICKUP ORDERS (WA/PHONE)</div>
</div>
</div>
<div className="flex items-center gap-3 text-[#6B665F]">
<Timer className="w-5 h-5 text-[#B38B4D]" />
<div className="text-xs tracking-[1.5px] leading-tight">
AVERAGE PREP TIME<br />
<span className="text-[#2C2A26] font-medium">12-16 MIN</span>
</div>
</div>
</div>
</div>
{/* Main beautiful content area - THREE COLUMNS with vertical reels filling entire remaining screen height */}
{/* Reels use h-full after fixed headers; cards fixed px height => zoom in: fewer visible per column, zoom out: more visible. No white space, max top to bottom like screen2 max left to right. */}
<div className="flex-1 min-h-0 overflow-hidden px-4 py-2 md:px-6 md:py-3 bg-[#F8F5F0]">
<div className="max-w-[1680px] mx-auto h-full grid grid-cols-1 lg:grid-cols-3 gap-4" style={{ minHeight: 0 }}>
{/* 1. DELIVERY PARTNERS - reel column */}
<div className="flex flex-col h-full">
{renderOrderReel(deliveryOrders, 'DELIVERY PARTNERS', <Bike className="w-5 h-5 text-[#B38B4D]" />)}
</div>
{/* 2. PICKUP ORDERS (WHATSAPP/PHONE) - reel column */}
<div className="flex flex-col h-full">
{renderOrderReel(pickupOrders, 'PICKUP ORDERS (WHATSAPP/PHONE)', <Package className="w-5 h-5 text-[#B38B4D]" />)}
</div>
{/* 3. RESTAURANT ORDERS - reel column */}
<div className="flex flex-col h-full">
{renderOrderReel(restaurantOrders, 'RESTAURANT ORDERS', <Users className="w-5 h-5 text-[#B38B4D]" />)}
</div>
</div>
</div>
{/* Bottom elegant bar / marquee for future rider messages */}
<div className="relative z-10 py-2.5 text-center text-[11px] tracking-[3px] text-[#8A8478] border-t border-[#EDE6D9]/60 bg-[#F8F5F0] flex-none flex items-center justify-center gap-4">
<div>SHAHI KITCHEN GOTHENBURG FRESH EVERY DAY</div>
<div className="h-px w-6 bg-[#EDE6D9]" />
<div className="text-[#B38B4D] font-medium">INTEGRATING WITH FOODORA WOLT UBER EATS</div>
<div className="h-px w-6 bg-[#EDE6D9]" />
<div>BACKEND API READY SOON LIVE DATA FEED</div>
</div>
</div>
);
}