// Utility helpers for the frontend /** * Format currency in INR */ export function formatCurrency(amount) { if (amount == null) return '₹0.00'; return new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', minimumFractionDigits: 2 }).format(amount); } /** * Format date/time */ export function formatDate(dateStr, options = {}) { if (!dateStr) return '-'; const date = new Date(dateStr); return new Intl.DateTimeFormat('en-IN', { dateStyle: 'medium', timeStyle: 'short', ...options }).format(date); } /** * Format time only */ export function formatTime(dateStr) { if (!dateStr) return '-'; return new Intl.DateTimeFormat('en-IN', { timeStyle: 'short' }).format(new Date(dateStr)); } /** * Time elapsed since a date (e.g., "5 min ago") */ export function timeAgo(dateStr) { if (!dateStr) return ''; const now = Date.now(); const then = new Date(dateStr).getTime(); const diff = Math.floor((now - then) / 1000); if (diff < 60) return `${diff}s`; if (diff < 3600) return `${Math.floor(diff / 60)}m`; if (diff < 86400) return `${Math.floor(diff / 3600)}h`; return `${Math.floor(diff / 86400)}d`; } /** * Timer display (mm:ss) from a start date */ export function elapsedTimer(dateStr) { if (!dateStr) return '00:00'; const diff = Math.floor((Date.now() - new Date(dateStr).getTime()) / 1000); const mins = Math.floor(diff / 60); const secs = diff % 60; return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`; } /** * Debounce function */ export function debounce(fn, delay = 300) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), delay); }; } /** * Generate a short ID for local use */ export function shortId() { return Math.random().toString(36).substring(2, 9); } /** * Capitalize first letter */ export function capitalize(str) { if (!str) return ''; return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); } /** * Truncate string */ export function truncate(str, len = 30) { if (!str || str.length <= len) return str || ''; return str.substring(0, len) + '...'; } /** * Get order source display label */ export function orderSourceLabel(source) { const labels = { dine_in: 'Dine In', take_away: 'Takeaway', takeaway: 'Takeaway', delivery: 'Delivery', website: 'Website', whatsapp: 'WhatsApp', swiggy: 'Swiggy', zomato: 'Zomato', qr_table: 'QR Order', qr: 'QR Order' }; return labels[source] || capitalize(source); } /** * Get status color class */ export function statusColor(status) { const colors = { pending: 'badge-warning', preparing: 'badge-info', ready: 'badge-success', served: 'badge-success', completed: 'badge-success', cancelled: 'badge-danger', voided: 'badge-danger', available: 'badge-success', occupied: 'badge-danger', reserved: 'badge-warning', cleaning: 'badge-info' }; return colors[status] || 'badge-info'; } /** * Kitchen station label */ export function stationLabel(station) { const labels = { south_indian: 'South Indian', chinese: 'Chinese', tandoor: 'Tandoor', juice: 'Juice Bar', bakery: 'Bakery', main: 'Main Kitchen', bar: 'Bar' }; return labels[station] || capitalize(station); } /** * Play notification sound */ export function playSound(type = 'notify') { try { const ctx = new (window.AudioContext || window.webkitAudioContext)(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.connect(gain); gain.connect(ctx.destination); if (type === 'order') { osc.frequency.value = 880; gain.gain.value = 0.3; osc.start(); osc.stop(ctx.currentTime + 0.15); setTimeout(() => { const osc2 = ctx.createOscillator(); osc2.connect(gain); osc2.frequency.value = 1100; osc2.start(); osc2.stop(ctx.currentTime + 0.15); }, 180); } else { osc.frequency.value = 660; gain.gain.value = 0.2; osc.start(); osc.stop(ctx.currentTime + 0.1); } } catch { // Audio not available } } /** * Check if user has a specific role */ export function hasRole(user, ...roles) { if (!user?.role?.name) return false; return roles.includes(user.role.name.toLowerCase()); } /** * Calculate GST breakdown */ export function calculateGST(amount, gstRate = 5) { const gstAmount = (amount * gstRate) / 100; return { base: amount, cgst: gstAmount / 2, sgst: gstAmount / 2, total: amount + gstAmount, rate: gstRate }; }