// Base de données en mémoire (démo). Tout est remis à zéro au redémarrage du serveur. // En production : remplacer par Supabase / Postgres. export type Size = 'L' | 'XL' export type Category = 'wok' | 'baguette' | 'boissons' | 'desserts' export type Status = 'new' | 'prep' | 'ready' | 'done' | 'refused' export type Payment = 'carte' | 'apple' | 'google' | 'especes' export interface Dish { id: string name: string desc: string cat: Category prices: Partial> // centimes ; null = prix à définir meats: string[] sauces?: string[] badge?: { label: string, tone: 'best' | 'spicy' | 'veggie' } img?: string available: boolean } export interface Extra { id: string, label: string, price: number } export interface OrderItem { dishId: string name: string size: Size meat: string sauce?: string extras: string[] note?: string qty: number unit: number } export interface Order { id: string num: string createdAt: number client: { name: string, phone: string } mode: 'livraison' | 'retrait' address?: string slot?: string items: OrderItem[] subtotal: number fee: number total: number payment: Payment paid: boolean status: Status prepMinutes?: number readyBy?: number refunded?: boolean history: { at: number, label: string }[] } export interface DayHours { day: string, open: boolean, midi: string, soir: string } export interface Settings { open: boolean wait: number deliveryFee: number freeFrom: number minOrder: number radiusKm: number hours: DayHours[] closures: { date: string, label: string }[] } interface DB { dishes: Dish[] extras: Extra[] orders: Order[] settings: Settings seq: number } const MEATS = ['Bœuf', 'Crevettes', 'Poulet'] function seedOrders(): Order[] { const now = Date.now() const m = (min: number) => now - min * 60000 const mk = (n: number, min: number, name: string, mode: Order['mode'], items: OrderItem[], status: Status, payment: Payment = 'carte', extra: Partial = {}): Order => { const subtotal = items.reduce((a, i) => a + i.unit * i.qty, 0) const fee = mode === 'livraison' ? 250 : 0 const createdAt = m(min) return { id: 'seed' + n, num: 'PZ-0' + n, createdAt, client: { name, phone: '06 12 34 56 78' }, mode, address: mode === 'livraison' ? '12 rue des Arts, 74200 Thonon-les-Bains' : undefined, slot: mode === 'retrait' ? 'Dès que possible' : undefined, items, subtotal, fee, total: subtotal + fee, payment, paid: payment !== 'especes', status, history: [ { at: createdAt, label: 'Commande reçue' }, ...(status !== 'new' ? [{ at: createdAt + 60000, label: 'Acceptée · en préparation au wok' }] : []), ...(status === 'ready' || status === 'done' ? [{ at: createdAt + 18 * 60000, label: 'Prête' }] : []), ...(status === 'done' ? [{ at: createdAt + 25 * 60000, label: mode === 'livraison' ? 'Remise au livreur' : 'Récupérée par le client' }] : []) ], ...extra } } const it = (dishId: string, name: string, size: Size, meat: string, unit: number, qty = 1, sauce?: string, note?: string): OrderItem => ({ dishId, name, size, meat, unit, qty, sauce, note, extras: [] }) return [ mk(412, 380, 'Emma T.', 'retrait', [it('pad', 'Le Pad Thaï', 'L', 'Poulet', 1350)], 'done'), mk(413, 350, 'Hugo L.', 'livraison', [it('crousty', 'Le Crousty', 'XL', 'Poulet', 1350, 2, 'BBQ')], 'done', 'google'), mk(414, 320, 'Nadia K.', 'livraison', [it('nouilles', 'Les Nouilles', 'XL', 'Bœuf', 1500), it('crousty', 'Le Crousty', 'L', 'Poulet', 1100, 1, 'Chili thaï')], 'done'), mk(415, 60, 'Karim D.', 'livraison', [it('crousty', 'Le Crousty', 'L', 'Poulet', 1100, 1, 'BBQ'), it('nouilles', 'Les Nouilles', 'XL', 'Bœuf', 1500)], 'done', 'apple'), mk(416, 22, 'Lina M.', 'retrait', [it('crousty', 'Le Crousty', 'XL', 'Bœuf', 1350, 1, 'Aigre-douce'), it('baguette', 'La Baguette', 'XL', 'Poulet', 1000)], 'ready', 'carte', { prepMinutes: 20 }), mk(417, 12, 'Sami B.', 'livraison', [it('pad', 'Le Pad Thaï', 'XL', 'Crevettes', 1590, 1, undefined, 'sans oignons frits'), it('nouilles', 'Les Nouilles', 'L', 'Poulet', 1250)], 'prep', 'apple', { prepMinutes: 20, readyBy: m(12) + 20 * 60000 }) ] } function seed(): DB { return { seq: 418, extras: [ { id: 'sauce', label: 'Sauce en plus', price: 50 }, { id: 'oignons', label: 'Oignons frits en plus', price: 50 }, { id: 'viande', label: 'Double viande', price: 300 } ], dishes: [ { id: 'crousty', name: 'Le Crousty', desc: 'Poulet crousty, riz, sauce wow, oignons frits.', cat: 'wok', prices: { L: 1100, XL: 1350 }, meats: MEATS, sauces: ['BBQ', 'Chili thaï', 'Aigre-douce'], badge: { label: 'Best-seller', tone: 'best' }, img: '/img/crousty.png', available: true }, { id: 'nouilles', name: 'Les Nouilles', desc: 'Nouilles, légumes, herbes thaï, oignons frits.', cat: 'wok', prices: { L: 1250, XL: 1500 }, meats: MEATS, img: '/img/nouilles.png', available: true }, { id: 'riz', name: 'Le Riz Thaï', desc: 'Riz sauté, légumes, sauce soja, herbes thaï, oignons frits.', cat: 'wok', prices: { L: 1150, XL: 1400 }, meats: MEATS, img: '/img/riz-thai.png', available: true }, { id: 'pad', name: 'Le Pad Thaï', desc: 'Nouilles de riz, herbes thaï, soja, oignons frits.', cat: 'wok', prices: { L: 1350, XL: 1590 }, meats: MEATS, badge: { label: 'Épicé 🌶️', tone: 'spicy' }, img: '/img/pad-thai.png', available: true }, { id: 'veggie', name: 'Le Veggie', desc: 'Riz, légumes (brocolis), herbes thaï, oignons frits.', cat: 'wok', prices: { L: null, XL: null }, meats: [], badge: { label: 'Veggie', tone: 'veggie' }, available: true }, { id: 'baguette', name: 'La Baguette', desc: 'Bœuf ou poulet, légumes, sauce, frites.', cat: 'baguette', prices: { XL: 1000 }, meats: ['Bœuf', 'Poulet'], available: true } ], orders: seedOrders(), settings: { open: true, wait: 20, deliveryFee: 250, freeFrom: 3500, minOrder: 1500, radiusKm: 5, hours: [ { day: 'Lundi', open: true, midi: '11h30 – 14h00', soir: '18h30 – 22h00' }, { day: 'Mardi', open: true, midi: '11h30 – 14h00', soir: '18h30 – 22h00' }, { day: 'Mercredi', open: true, midi: '11h30 – 14h00', soir: '18h30 – 22h00' }, { day: 'Jeudi', open: true, midi: '11h30 – 14h00', soir: '18h30 – 22h00' }, { day: 'Vendredi', open: true, midi: '11h30 – 14h00', soir: '18h30 – 23h00' }, { day: 'Samedi', open: true, midi: '11h30 – 14h30', soir: '18h30 – 23h00' }, { day: 'Dimanche', open: true, midi: 'Fermé', soir: '18h30 – 22h00' } ], closures: [ { date: '24–25 déc.', label: 'Fêtes de fin d\'année' }, { date: '1 janv.', label: 'Jour de l\'an' } ] } } } const g = globalThis as unknown as { __panzaiDb?: DB } if (!g.__panzaiDb) g.__panzaiDb = seed() export const db = g.__panzaiDb export function resetDb() { Object.assign(db, seed()) } export function findOrder(id: string) { const o = db.orders.find(x => x.id === id) if (!o) throw createError({ statusCode: 404, statusMessage: 'Commande introuvable' }) return o }