// TableModal.jsx — Masa sipariş yönetimi const { useState, useEffect, useRef } = React; function TableModal({ tableId, tables, onClose, onUpdate, lang, user }) { const T = window.TRANS[lang]; const table = tables.find(t => t.id === tableId); if (!table) return null; const isWaiter = user && user.role === 'waiter'; // Empty tables now ALWAYS start with an explicit "Masayı Aç" confirm step, // regardless of role. From there: // waiter user → 'opening' (auto open) // admin user → 'waiter' (pick a name) const initialStep = table.occupied ? 'order' : 'confirm'; const [step, setStep] = useState(initialStep); const [activeCat, setActiveCat] = useState(null); const [showPayment, setShowPayment] = useState(false); const [showReceipt, setShowReceipt] = useState(null); // Waiter pick is only shown to admin; waiters auto-open with their own name. const waiters = Store.getUsers().filter(u => u.role === 'waiter' && u.active); const menu = Store.getMenu().filter(m => m.active); const categories = Store.getCategories().filter(c => menu.some(m => m.cat === c)); useEffect(() => { if (!activeCat && categories.length) setActiveCat(categories[0]); }, []); // When we enter the 'opening' step (waiter clicked "Masayı Aç"), // open the table on the server with their own name. useEffect(() => { if (step !== 'opening') return; let cancelled = false; (async () => { try { const updated = await Store.openTable(table.id, user.name); if (cancelled) return; onUpdate(updated); setStep('order'); } catch (e) { if (!cancelled) onClose(); } })(); return () => { cancelled = true; }; }, [step]); const orders = table.orders || []; const total = orders.reduce((s, o) => s + o.price * o.qty, 0); const catItems = menu.filter(m => m.cat === activeCat); const handleWaiterSelect = async (name) => { const updated = await Store.openTable(table.id, name); onUpdate(updated); setStep('order'); }; const handleAddItem = async (item) => { const updated = await Store.addOrderItem(table.id, { id: item.id, name: item.name, price: item.price }); onUpdate(updated); }; const handleRemove = async (itemId) => { const updated = await Store.removeOrderItem(table.id, itemId); onUpdate(updated); }; const handlePayment = async (method) => { const t = tables.find(x => x.id === tableId); const receipt = { tableName: t.name, waiter: t.waiter, items: [...t.orders], total, method, closedAt: new Date(), }; const updated = await Store.closeTable(table.id, method); onUpdate(updated); setShowPayment(false); setShowReceipt(receipt); }; const handleCancel = async () => { const updated = await Store.cancelTable(table.id); onUpdate(updated); onClose(); }; // React to live updates that change the table state remotely. useEffect(() => { if (showReceipt || showPayment) return; if (step === 'order' && !table.occupied) { onClose(); } else if ((step === 'waiter' || step === 'opening' || step === 'confirm') && table.occupied) { setStep('order'); } }, [table.occupied]); // "Masayı Aç" pressed on the confirm screen. const handleOpenPress = () => { if (isWaiter) { setStep('opening'); } else { setStep('waiter'); } }; // Empty table — explicit "Masayı Aç" confirm. if (step === 'confirm') { return (
e.stopPropagation()}>
{table.name}
BOŞ
{isWaiter ? <>Masa {user.name} adına açılacak. : <>Masayı aç ve garson seç.}
); } if (step === 'opening') { return (
{table.name} açılıyor…
); } if (showReceipt) { return (
e.stopPropagation()}>
🧾
{showReceipt.tableName}
{showReceipt.waiter} • {showReceipt.method === 'cash' ? T.cash : T.card}
{showReceipt.items.map(item => (
{item.qty}x {item.name} {fmt(item.price * item.qty)}
))}
{T.total} {fmt(showReceipt.total)}
); } if (showPayment) { return (
setShowPayment(false)}>
e.stopPropagation()}>
{T.confirmPayment}
{T.total}: {fmt(total)}
); } if (step === 'waiter') { return (
e.stopPropagation()}>
{table.name}
Masayı kim açıyor?
{waiters.length === 0 ? (
Aktif garson yok. Yönetim → Kullanıcılar'dan ekle.
) : waiters.map(w => ( ))}
); } return (
e.stopPropagation()}>
{table.name}
{T.waiter}: {table.waiter} {table.openedAt && ⏱ {elapsed(table.openedAt)}}
{/* ✕ alone — destructive actions live in the order panel footer so an accidental tap on close doesn't free the table. */}
{categories.map(cat => ( ))}
{catItems.map(item => { const inOrder = orders.find(o => o.id === item.id); const qty = inOrder ? inOrder.qty : 0; return (
handleAddItem(item)} style={{ padding: '12px 10px', borderRadius: 10, border: '1.5px solid', borderColor: qty > 0 ? 'var(--accent)' : 'var(--border)', background: qty > 0 ? 'var(--accent-light)' : 'var(--surface)', cursor: 'pointer', fontFamily: 'inherit', transition: 'all 0.15s', display: 'flex', flexDirection: 'column', userSelect: 'none', WebkitTapHighlightColor: 'transparent', }}>
{item.name}
{fmt(item.price)}
{qty > 0 && (
e.stopPropagation()} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 10, paddingTop: 10, borderTop: '1px solid rgba(232,89,12,0.25)', gap: 8, }}>
{qty}
)}
); })}
Sipariş ({orders.length} ürün)
{orders.length === 0 ? (
{T.noOrders}
) : orders.map(o => (
{o.name}
{fmt(o.price)} × {o.qty}
{fmt(o.price * o.qty)}
))}
{T.total} {fmt(total)}
{orders.length > 0 ? ( ) : ( )}
); } Object.assign(window, { TableModal });