DIGIY PAY RESTOS

DIGIY RESTO PRO V2 – Système Complet
`); printWindow.document.close(); setTimeout(() => { setTables(tables.map(t => t.id === selectedTable.id ? { ...t, status: 'libre', guests: 0, orders: [] } : t)); setSelectedTable(null); setCurrentOrder([]); setView('tables'); alert('✅ Paiement effectué ! Table libérée.'); }, 500); };const markTableReady = (order) => { setAllOrders(allOrders.map(o => o.id === order.id ? { ...o, items: o.items.map(i => ({ ...i, status: 'pret' })) } : o)); alert(`✅ TABLE ${order.tableNumber} PRÊTE !`); };const addProduct = () => { if (!newProduct.name || !newProduct.price || !newProduct.sku) return alert('Remplis tous les champs !'); const product = { id: Date.now().toString(), name: newProduct.name, price: parseFloat(newProduct.price), tax: parseFloat(newProduct.tax), sku: newProduct.sku, poste: newProduct.poste, isPlat: newProduct.isPlat, isEntree: newProduct.isEntree, isDessert: newProduct.isDessert }; setProducts([...products, product]); setNewProduct({ name: '', price: '', tax: '0.10', poste: 'BAR', sku: '', isPlat: false, isEntree: false, isDessert: false }); alert('✅ Produit ajouté !'); };const addMenu = () => { if (!newMenu.name || !newMenu.price) return alert('Remplis le nom et le prix !'); if (newMenu.entrees.length === 0 && newMenu.plats.length === 0 && newMenu.desserts.length === 0) { return alert('Sélectionne au moins une option !'); } const menu = { id: `menu_${Date.now()}`, name: newMenu.name, price: parseFloat(newMenu.price), tax: parseFloat(newMenu.tax), entrees: newMenu.entrees.length > 0 ? newMenu.entrees : undefined, plats: newMenu.plats.length > 0 ? newMenu.plats : undefined, desserts: newMenu.desserts.length > 0 ? newMenu.desserts : undefined }; setMenus([...menus, menu]); setNewMenu({ name: '', price: '', tax: '0.10', entrees: [], plats: [], desserts: [] }); setShowMenuBuilder(false); alert('✅ Menu créé !'); };const toggleMenuSelection = (category, productId) => { setNewMenu(prev => { const current = prev[category]; if (current.includes(productId)) { return { ...prev, [category]: current.filter(id => id !== productId) }; } else { return { ...prev, [category]: [...current, productId] }; } }); };const addMenuToOrder = (menu, selections) => { const menuItem = { id: `menu_${Date.now()}`, name: menu.name, price: menu.price, tax: menu.tax, qty: 1, isMenu: true, selections: selections, poste: 'MENU' }; setCurrentOrder([...currentOrder, menuItem]); setShowMenuModal(false); setSelectedMenu(null); setMenuSelections({}); };const addNewZone = () => { if (!newZone.name || !newZone.tables || !newZone.startNumber) return alert('Remplis tous les champs !'); const tables = parseInt(newZone.tables); const startNum = parseInt(newZone.startNumber); if (tables < 1) return alert('Au moins 1 table !'); if (startNum < 1) return alert('Numéro de départ invalide !'); const zoneKey = `ZONE_${Date.now()}`; const newZones = { ...zones, [zoneKey]: { name: newZone.name, tables: tables, color: newZone.color, startNumber: startNum } }; setZones(newZones); setTables(generateTables(newZones)); setNewZone({ name: '', tables: '', color: 'from-blue-500 to-purple-500', startNumber: '' }); setEditingZone(null); alert('✅ Zone ajoutée !'); };const updateZoneTables = (zoneKey, newTableCount) => { const count = parseInt(newTableCount); if (!count || count < 0) return; setZones({...zones, [zoneKey]: {...zones[zoneKey], tables: count}}); const newZones = {...zones, [zoneKey]: {...zones[zoneKey], tables: count}}; setTables(generateTables(newZones)); setEditingZone(null); alert('✅ Tables mises à jour !'); };const updateZoneStartNumber = (zoneKey, newStartNumber) => { const startNum = parseInt(newStartNumber); if (!startNum || startNum < 1) return alert('Numéro invalide !'); setZones({...zones, [zoneKey]: {...zones[zoneKey], startNumber: startNum}}); const newZones = {...zones, [zoneKey]: {...zones[zoneKey], startNumber: startNum}}; setTables(generateTables(newZones)); setEditingZone(null); alert('✅ Numérotation mise à jour !'); };const deleteZone = (zoneKey) => { if (!confirm('Supprimer cette zone ?')) return; const newZones = {...zones}; delete newZones[zoneKey]; setZones(newZones); setTables(generateTables(newZones)); alert('✅ Zone supprimée !'); };// ✅ NOUVEAU : Ajouter une réservation const addReservation = () => { if (!newReservation.customerName || !newReservation.phone || !newReservation.date || !newReservation.time || !newReservation.guests) { return alert('Remplis tous les champs obligatoires !'); } const reservation = { id: Date.now().toString(), ...newReservation, guests: parseInt(newReservation.guests), status: 'confirmed', createdAt: new Date().toISOString() }; setReservations([...reservations, reservation]); setNewReservation({ customerName: '', phone: '', date: '', time: '', guests: '', notes: '' }); setShowReservationModal(false); alert('✅ Réservation confirmée !'); };// ✅ NOUVEAU : Attribuer une table à une réservation const assignTableToReservation = (reservationId, tableId) => { const table = tables.find(t => t.id === tableId); if (table.status === 'occupee') return alert('Table déjà occupée !'); const reservation = reservations.find(r => r.id === reservationId); setTables(tables.map(t => t.id === tableId ? { ...t, status: 'occupee', guests: reservation.guests, notes: `Résa: ${reservation.customerName}` } : t )); setReservations(reservations.map(r => r.id === reservationId ? { ...r, status: 'arrived', assignedTableId: tableId } : r )); alert(`✅ Table ${table.number} attribuée à ${reservation.customerName} !`); };const zoneTables = tables.filter(t => t.zone === selectedZone); const posteProducts = products.filter(p => p.poste === selectedPoste); const total = currentOrder.reduce((s, i) => s + (i.price * (1 + i.tax) * i.qty), 0);// ✅ NOUVEAU : Vue Réservations if (view === 'reservations') { const today = new Date().toISOString().split('T')[0]; const todayReservations = reservations.filter(r => r.date === today && r.status !== 'cancelled'); return (

📅 RÉSERVATIONS

📆 Réservations du jour

{todayReservations.length === 0 ? (

Aucune réservation aujourd'hui

) : (
{todayReservations.map(resa => (

{resa.customerName}

📞 {resa.phone}

🕐 {resa.time} • 👥 {resa.guests} pers.

{resa.notes &&

📝 {resa.notes}

}
{resa.status === 'arrived' ? ( ✅ Arrivé ) : ( 🕐 Confirmé )}
{resa.status !== 'arrived' && (

Attribuer une table :

{tables.filter(t => t.status === 'libre').slice(0, 8).map(t => ( ))}
)}
))}
)}

📋 Toutes les réservations

{reservations.filter(r => r.status !== 'cancelled').sort((a, b) => new Date(b.date) - new Date(a.date)).slice(0, 20).map(resa => (

{resa.customerName}

📅 {new Date(resa.date).toLocaleDateString('fr-FR')} • 🕐 {resa.time}

))}
{showReservationModal && (

📅 Nouvelle Réservation

setNewReservation({...newReservation, customerName: e.target.value})} placeholder="Nom du client *" className="w-full px-4 py-3 border-2 rounded-xl" /> setNewReservation({...newReservation, phone: e.target.value})} placeholder="Téléphone *" className="w-full px-4 py-3 border-2 rounded-xl" />
setNewReservation({...newReservation, date: e.target.value})} className="w-full px-4 py-3 border-2 rounded-xl" /> setNewReservation({...newReservation, time: e.target.value})} className="w-full px-4 py-3 border-2 rounded-xl" />
setNewReservation({...newReservation, guests: e.target.value})} placeholder="Nombre de personnes *" className="w-full px-4 py-3 border-2 rounded-xl" />