Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
{
const button = document.createElement('button');
button.className = 'menu-btn';
button.onclick = () => addToOrder(item);
button.innerHTML = `
${item.name}
${item.price.toFixed(2)}
`;
container.appendChild(button);
});
}
function addToOrder(item) {
const existing = currentOrder.find(orderItem => orderItem.id === item.id);
if (existing) {
existing.quantity++;
} else {
currentOrder.push({ ...item, quantity: 1 });
}
displayCurrentOrder();
// Haptic feedback on mobile
if (navigator.vibrate) {
navigator.vibrate(50);
}
}
function displayCurrentOrder() {
const container = document.getElementById('orderItems');
const totalDiv = document.getElementById('orderTotal');
container.innerHTML = '';
let total = 0;
currentOrder.forEach((item, index) => {
const itemDiv = document.createElement('div');
itemDiv.className = 'order-item';
const itemTotal = item.price * item.quantity;
total += itemTotal;
itemDiv.innerHTML = `
${item.name}
${item.price.toFixed(2)} each
${item.quantity}
${itemTotal.toFixed(2)}
`;
container.appendChild(itemDiv);
});
totalDiv.textContent = `Total: ${total.toFixed(2)}`;
}
function increaseQuantity(index) {
currentOrder[index].quantity++;
displayCurrentOrder();
}
function decreaseQuantity(index) {
if (currentOrder[index].quantity > 1) {
currentOrder[index].quantity--;
} else {
currentOrder.splice(index, 1);
}
displayCurrentOrder();
}
function clearOrder() {
currentOrder = [];
displayCurrentOrder();
}
function completeOrder() {
if (currentOrder.length === 0) {
alert('❌ No items in order');
return;
}
const customerName = document.getElementById('customerName').value.trim() || 'Walk-in';
const customerPhone = document.getElementById('customerPhone').value.trim();
const total = currentOrder.reduce((sum, item) => sum + (item.price * item.quantity), 0);
const orderData = {
customer_name: customerName,
customer_phone: customerPhone,
total: total,
order_items: JSON.stringify(currentOrder),
user_id: currentUser.id
};
if (DB_CONFIG.useSQLite) {
db.run(
"INSERT INTO orders (customer_name, customer_phone, total, order_items, user_id) VALUES (?, ?, ?, ?, ?)",
[orderData.customer_name, orderData.customer_phone, orderData.total, orderData.order_items, orderData.user_id]
);
saveDatabase();
}
// Success feedback
alert(`✅ Order completed!\n\nCustomer: ${customerName}\nTotal: ${total.toFixed(2)}\nItems: ${currentOrder.length}`);
// Clear form
currentOrder = [];
document.getElementById('customerName').value = '';
document.getElementById('customerPhone').value = '';
displayCurrentOrder();
updateDashboard();
loadRecentOrders();
// Haptic feedback
if (navigator.vibrate) {
navigator.vibrate([100, 50, 100]);
}
}
function loadRecentOrders() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders ORDER BY created_at DESC LIMIT 10");
const orders = stmt.all();
stmt.free();
const container = document.getElementById('recentOrders');
container.innerHTML = '';
orders.forEach(order => {
const orderDiv = document.createElement('div');
orderDiv.className = 'order-card';
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name} (${item.quantity})`).join(', ');
orderDiv.innerHTML = `
👤 ${order.customer_name}
${order.customer_phone ? `📞 ${order.customer_phone}` : ''}
${itemsList}
🕒 ${new Date(order.created_at).toLocaleString()}
`;
container.appendChild(orderDiv);
});
}
// Menu Management
function loadMenuManagement() {
displayMenuList();
}
function displayMenuList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items ORDER BY category, name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('menuList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'menu-card';
itemDiv.innerHTML = `
${item.description || 'No description'}
`;
container.appendChild(itemDiv);
});
}
function saveMenuItem() {
const name = document.getElementById('itemName').value.trim();
const price = parseFloat(document.getElementById('itemPrice').value);
const category = document.getElementById('itemCategory').value;
const description = document.getElementById('itemDescription').value.trim();
const available = parseInt(document.getElementById('itemAvailable').value);
const editingId = document.getElementById('editingItemId').value;
if (!name || isNaN(price)) {
alert('❌ Please enter item name and price');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE menu_items SET name = ?, price = ?, category = ?, description = ?, available = ? WHERE id = ?",
[name, price, category, description, available, editingId]
);
} else {
db.run(
"INSERT INTO menu_items (name, price, category, description, available) VALUES (?, ?, ?, ?, ?)",
[name, price, category, description, available]
);
}
saveDatabase();
}
clearMenuForm();
displayMenuList();
loadMenuButtons();
alert('✅ Menu item saved successfully!');
}
function editMenuItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('itemName').value = item.name;
document.getElementById('itemPrice').value = item.price;
document.getElementById('itemCategory').value = item.category;
document.getElementById('itemDescription').value = item.description || '';
document.getElementById('itemAvailable').value = item.available;
document.getElementById('editingItemId').value = item.id;
}
}
function deleteMenuItem(id) {
if (confirm('🗑️ Are you sure you want to delete this menu item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM menu_items WHERE id = ?", [id]);
saveDatabase();
}
displayMenuList();
loadMenuButtons();
alert('✅ Menu item deleted successfully!');
}
}
function clearMenuForm() {
document.getElementById('itemName').value = '';
document.getElementById('itemPrice').value = '';
document.getElementById('itemDescription').value = '';
document.getElementById('itemAvailable').value = '1';
document.getElementById('editingItemId').value = '';
}
// Analytics
function loadAnalytics() {
updateAnalytics();
}
function updateAnalytics() {
if (!DB_CONFIG.useSQLite) return;
const timeframe = document.getElementById('analyticsTimeframe').value;
const { startDate, endDate } = getDateRange(timeframe);
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at <= ?"
);
const stats = stmt.get([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const avgOrder = stats.orders > 0 ? stats.sales / stats.orders : 0;
document.getElementById('totalSales').textContent = '
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
= ? AND created_at <= ?
`);
const orders = topItemStmt.all([startDate.toISOString(), endDate.toISOString()]);
topItemStmt.free();
const itemCounts = {};
orders.forEach(order => {
const items = JSON.parse(order.order_items);
items.forEach(item => {
itemCounts[item.name] = (itemCounts[item.name] || 0) + item.quantity;
});
});
const topItem = Object.keys(itemCounts).reduce((a, b) =>
itemCounts[a] > itemCounts[b] ? a : b, '-'
);
document.getElementById('topItem').textContent = topItem;
displayOrderHistory(startDate, endDate);
}
function getDateRange(timeframe) {
const now = new Date();
let startDate, endDate = new Date(now);
switch(timeframe) {
case 'daily':
startDate = new Date(now);
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'weekly':
startDate = new Date(now);
startDate.setDate(now.getDate() - now.getDay());
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'monthly':
startDate = new Date(now.getFullYear(), now.getMonth(), 1);
endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
break;
case 'yearly':
startDate = new Date(now.getFullYear(), 0, 1);
endDate = new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999);
break;
}
return { startDate, endDate };
}
function displayOrderHistory(startDate, endDate) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare(
"SELECT * FROM orders WHERE created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT 50"
);
const orders = stmt.all([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const tbody = document.getElementById('orderHistoryBody');
tbody.innerHTML = '';
orders.forEach(order => {
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name}(${item.quantity})`).join(', ');
const row = document.createElement('tr');
row.innerHTML = `
#${order.id} |
${order.customer_name} |
${itemsList} |
${order.total.toFixed(2)} |
${new Date(order.created_at).toLocaleString()} |
|
`;
tbody.appendChild(row);
});
}
// Inventory Management
function loadInventoryManagement() {
displayInventoryList();
}
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
if (item.stock <= 0) {
stockClass = 'stock-out';
stockText = '❌ Out of Stock';
} else if (item.stock <= item.reorder_level) {
stockClass = 'stock-low';
stockText = '⚠️ Low Stock';
}
itemDiv.innerHTML = `
💰 Cost: ${item.cost.toFixed(2)} per ${item.unit}
📊 Reorder at: ${item.reorder_level} ${item.unit}
`;
container.appendChild(itemDiv);
});
}
function saveInventoryItem() {
const name = document.getElementById('inventoryName').value.trim();
const stock = parseFloat(document.getElementById('inventoryStock').value);
const cost = parseFloat(document.getElementById('inventoryCost').value);
const unit = document.getElementById('inventoryUnit').value.trim();
const reorderLevel = parseFloat(document.getElementById('inventoryReorderLevel').value);
const editingId = document.getElementById('editingInventoryId').value;
if (!name || isNaN(stock) || isNaN(cost) || !unit || isNaN(reorderLevel)) {
alert('❌ Please fill all fields correctly');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE inventory SET name = ?, stock = ?, cost = ?, unit = ?, reorder_level = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
[name, stock, cost, unit, reorderLevel, editingId]
);
} else {
db.run(
"INSERT INTO inventory (name, stock, cost, unit, reorder_level) VALUES (?, ?, ?, ?, ?)",
[name, stock, cost, unit, reorderLevel]
);
}
saveDatabase();
}
clearInventoryForm();
displayInventoryList();
alert('✅ Inventory item saved successfully!');
}
function editInventoryItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('inventoryName').value = item.name;
document.getElementById('inventoryStock').value = item.stock;
document.getElementById('inventoryCost').value = item.cost;
document.getElementById('inventoryUnit').value = item.unit;
document.getElementById('inventoryReorderLevel').value = item.reorder_level;
document.getElementById('editingInventoryId').value = item.id;
}
}
function deleteInventoryItem(id) {
if (confirm('🗑️ Are you sure you want to delete this inventory item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM inventory WHERE id = ?", [id]);
saveDatabase();
}
displayInventoryList();
alert('✅ Inventory item deleted successfully!');
}
}
function clearInventoryForm() {
document.getElementById('inventoryName').value = '';
document.getElementById('inventoryStock').value = '';
document.getElementById('inventoryCost').value = '';
document.getElementById('inventoryUnit').value = '';
document.getElementById('inventoryReorderLevel').value = '';
document.getElementById('editingInventoryId').value = '';
}
// User Management
function loadUserManagement() {
if (currentUser?.role !== 'admin') {
alert('❌ Access denied. Admin privileges required.');
showTab('orders');
return;
}
displayUsersList();
}
function displayUsersList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE active = 1 ORDER BY role, username");
const users = stmt.all();
stmt.free();
const container = document.getElementById('usersList');
container.innerHTML = '';
users.forEach(user => {
const userDiv = document.createElement('div');
userDiv.className = 'user-card';
userDiv.innerHTML = `
📧 ${user.email || 'No email'}
📅 Created: ${new Date(user.created_at).toLocaleDateString()}
`;
container.appendChild(userDiv);
});
}
function saveUser() {
const username = document.getElementById('newUsername').value.trim();
const password = document.getElementById('newPassword').value;
const fullName = document.getElementById('newUserFullName').value.trim();
const role = document.getElementById('newUserRole').value;
const email = document.getElementById('newUserEmail').value.trim();
const editingId = document.getElementById('editingUserId').value;
if (!username || !password || !fullName) {
alert('❌ Please fill in username, password, and full name');
return;
}
if (DB_CONFIG.useSQLite) {
try {
if (editingId) {
db.run(
"UPDATE users SET username = ?, password = ?, role = ?, full_name = ?, email = ? WHERE id = ?",
[username, password, role, fullName, email, editingId]
);
} else {
db.run(
"INSERT INTO users (username, password, role, full_name, email) VALUES (?, ?, ?, ?, ?)",
[username, password, role, fullName, email]
);
}
saveDatabase();
clearUserForm();
displayUsersList();
alert('✅ User saved successfully!');
} catch (error) {
if (error.message.includes('UNIQUE constraint failed')) {
alert('❌ Username already exists. Please choose a different username.');
} else {
alert('❌ Error saving user: ' + error.message);
}
}
}
}
function editUser(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE id = ?");
const user = stmt.get([id]);
stmt.free();
if (user) {
document.getElementById('newUsername').value = user.username;
document.getElementById('newPassword').value = user.password;
document.getElementById('newUserFullName').value = user.full_name || '';
document.getElementById('newUserRole').value = user.role;
document.getElementById('newUserEmail').value = user.email || '';
document.getElementById('editingUserId').value = user.id;
}
}
function deleteUser(id) {
if (confirm('🗑️ Are you sure you want to delete this user? This action cannot be undone.')) {
if (DB_CONFIG.useSQLite) {
db.run("UPDATE users SET active = 0 WHERE id = ?", [id]);
saveDatabase();
}
displayUsersList();
alert('✅ User deleted successfully!');
}
}
function clearUserForm() {
document.getElementById('newUsername').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('newUserFullName').value = '';
document.getElementById('newUserRole').value = 'employee';
document.getElementById('newUserEmail').value = '';
document.getElementById('editingUserId').value = '';
}
// Print Receipt
function printReceipt(orderId) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders WHERE id = ?");
const order = stmt.get([orderId]);
stmt.free();
if (!order) return;
const orderItems = JSON.parse(order.order_items);
let receiptContent = `
CY FRYING
CY YOU NEED US TO FRY
📞 (937) 527-3203
Order #: ${order.id}
Customer: ${order.customer_name}
${order.customer_phone ? `
Phone: ${order.customer_phone}
` : ''}
Date: ${new Date(order.created_at).toLocaleString()}
`;
orderItems.forEach(item => {
const itemTotal = item.price * item.quantity;
receiptContent += `
${item.name} x${item.quantity}
${itemTotal.toFixed(2)}
`;
});
receiptContent += `
TOTAL:
${order.total.toFixed(2)}
Thank you for your business!
🍟 Come back soon! 🍟
`;
const printWindow = window.open('', '_blank');
printWindow.document.write(`
Receipt - Order #${order.id}
${receiptContent}
`);
printWindow.document.close();
printWindow.print();
printWindow.close();
}
// Keyboard Shortcuts
document.addEventListener('keydown', function(e) {
// Only when not typing in inputs
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
switch(e.key) {
case '1':
if (currentUser) showTab('orders');
break;
case '2':
if (currentUser) showTab('menu');
break;
case '3':
if (currentUser) showTab('analytics');
break;
case '4':
if (currentUser) showTab('inventory');
break;
case 'Enter':
if (!currentUser && !document.getElementById('loginScreen').classList.contains('hidden')) {
e.preventDefault();
attemptLogin();
} else if (currentOrder.length > 0) {
e.preventDefault();
completeOrder();
}
break;
case 'Escape':
if (currentOrder.length > 0) {
clearOrder();
}
break;
}
});
// Touch optimizations
let touchStartY = 0;
document.addEventListener('touchstart', function(e) {
touchStartY = e.touches[0].clientY;
});
document.addEventListener('touchmove', function(e) {
const touchY = e.touches[0].clientY;
const touchDiff = touchStartY - touchY;
// Prevent bounce scrolling
if (touchDiff > 0 && window.pageYOffset === 0) {
e.preventDefault();
}
}, { passive: false });
// Auto-save and backup
setInterval(() => {
if (db && DB_CONFIG.useSQLite) {
saveDatabase();
}
}, 30000); // Save every 30 seconds
// Orientation change handler
window.addEventListener('orientationchange', function() {
setTimeout(() => {
window.scrollTo(0, 0);
}, 100);
});
// Network status
window.addEventListener('online', function() {
updateStatus('Online');
});
window.addEventListener('offline', function() {
updateStatus('Offline');
});
// Initialize app when page loads
document.addEventListener('DOMContentLoaded', function() {
initDatabase().then(() => {
console.log('✅ Cy Frying Food Truck System loaded successfully!');
}).catch(error => {
console.error('❌ Failed to initialize:', error);
alert('Failed to initialize database. Please refresh the page.');
});
});
// Prevent zoom on double tap
let lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
const now = (new Date()).getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);
// Service worker for offline support (optional)
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').catch(function(error) {
console.log('ServiceWorker registration failed:', error);
});
});
}
console.log('🚚 Cy Frying Food Truck Management System Ready!');
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
errorDiv.classList.add('hidden'), 3000);
}
function clearLoginForm() {
document.getElementById('username').value = '';
document.getElementById('password').value = '';
document.getElementById('loginError').classList.add('hidden');
}
function logout() {
currentUser = null;
currentOrder = [];
document.getElementById('loginScreen').classList.remove('hidden');
document.getElementById('mainApp').classList.add('hidden');
clearLoginForm();
}
// Tab Management
function showTab(tabName) {
document.querySelectorAll('.tab-content').forEach(tab => tab.classList.add('hidden'));
document.querySelectorAll('.nav-tab').forEach(tab => tab.classList.remove('active'));
document.getElementById(tabName + 'Tab').classList.remove('hidden');
event.target.classList.add('active');
switch(tabName) {
case 'orders':
loadOrderManagement();
break;
case 'menu':
loadMenuManagement();
break;
case 'analytics':
loadAnalytics();
break;
case 'inventory':
loadInventoryManagement();
break;
case 'users':
loadUserManagement();
break;
}
}
// Load Initial Data
function loadInitialData() {
updateDashboard();
loadOrderManagement();
updateOrderTime();
setInterval(updateOrderTime, 1000);
}
function updateOrderTime() {
const now = new Date();
document.getElementById('orderTime').textContent = now.toLocaleTimeString();
}
function updateDashboard() {
const today = new Date();
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
if (DB_CONFIG.useSQLite) {
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at < ?"
);
const stats = stmt.get([today.toISOString(), tomorrow.toISOString()]);
stmt.free();
document.getElementById('todayOrders').textContent = stats.orders;
document.getElementById('todaySales').textContent = '
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
{
const button = document.createElement('button');
button.className = 'menu-btn';
button.onclick = () => addToOrder(item);
button.innerHTML = `
${item.name}
${item.price.toFixed(2)}
`;
container.appendChild(button);
});
}
function addToOrder(item) {
const existing = currentOrder.find(orderItem => orderItem.id === item.id);
if (existing) {
existing.quantity++;
} else {
currentOrder.push({ ...item, quantity: 1 });
}
displayCurrentOrder();
// Haptic feedback on mobile
if (navigator.vibrate) {
navigator.vibrate(50);
}
}
function displayCurrentOrder() {
const container = document.getElementById('orderItems');
const totalDiv = document.getElementById('orderTotal');
container.innerHTML = '';
let total = 0;
currentOrder.forEach((item, index) => {
const itemDiv = document.createElement('div');
itemDiv.className = 'order-item';
const itemTotal = item.price * item.quantity;
total += itemTotal;
itemDiv.innerHTML = `
${item.name}
${item.price.toFixed(2)} each
${item.quantity}
${itemTotal.toFixed(2)}
`;
container.appendChild(itemDiv);
});
totalDiv.textContent = `Total: ${total.toFixed(2)}`;
}
function increaseQuantity(index) {
currentOrder[index].quantity++;
displayCurrentOrder();
}
function decreaseQuantity(index) {
if (currentOrder[index].quantity > 1) {
currentOrder[index].quantity--;
} else {
currentOrder.splice(index, 1);
}
displayCurrentOrder();
}
function clearOrder() {
currentOrder = [];
displayCurrentOrder();
}
function completeOrder() {
if (currentOrder.length === 0) {
alert('❌ No items in order');
return;
}
const customerName = document.getElementById('customerName').value.trim() || 'Walk-in';
const customerPhone = document.getElementById('customerPhone').value.trim();
const total = currentOrder.reduce((sum, item) => sum + (item.price * item.quantity), 0);
const orderData = {
customer_name: customerName,
customer_phone: customerPhone,
total: total,
order_items: JSON.stringify(currentOrder),
user_id: currentUser.id
};
if (DB_CONFIG.useSQLite) {
db.run(
"INSERT INTO orders (customer_name, customer_phone, total, order_items, user_id) VALUES (?, ?, ?, ?, ?)",
[orderData.customer_name, orderData.customer_phone, orderData.total, orderData.order_items, orderData.user_id]
);
saveDatabase();
}
// Success feedback
alert(`✅ Order completed!\n\nCustomer: ${customerName}\nTotal: ${total.toFixed(2)}\nItems: ${currentOrder.length}`);
// Clear form
currentOrder = [];
document.getElementById('customerName').value = '';
document.getElementById('customerPhone').value = '';
displayCurrentOrder();
updateDashboard();
loadRecentOrders();
// Haptic feedback
if (navigator.vibrate) {
navigator.vibrate([100, 50, 100]);
}
}
function loadRecentOrders() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders ORDER BY created_at DESC LIMIT 10");
const orders = stmt.all();
stmt.free();
const container = document.getElementById('recentOrders');
container.innerHTML = '';
orders.forEach(order => {
const orderDiv = document.createElement('div');
orderDiv.className = 'order-card';
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name} (${item.quantity})`).join(', ');
orderDiv.innerHTML = `
👤 ${order.customer_name}
${order.customer_phone ? `📞 ${order.customer_phone}` : ''}
${itemsList}
🕒 ${new Date(order.created_at).toLocaleString()}
`;
container.appendChild(orderDiv);
});
}
// Menu Management
function loadMenuManagement() {
displayMenuList();
}
function displayMenuList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items ORDER BY category, name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('menuList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'menu-card';
itemDiv.innerHTML = `
${item.description || 'No description'}
`;
container.appendChild(itemDiv);
});
}
function saveMenuItem() {
const name = document.getElementById('itemName').value.trim();
const price = parseFloat(document.getElementById('itemPrice').value);
const category = document.getElementById('itemCategory').value;
const description = document.getElementById('itemDescription').value.trim();
const available = parseInt(document.getElementById('itemAvailable').value);
const editingId = document.getElementById('editingItemId').value;
if (!name || isNaN(price)) {
alert('❌ Please enter item name and price');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE menu_items SET name = ?, price = ?, category = ?, description = ?, available = ? WHERE id = ?",
[name, price, category, description, available, editingId]
);
} else {
db.run(
"INSERT INTO menu_items (name, price, category, description, available) VALUES (?, ?, ?, ?, ?)",
[name, price, category, description, available]
);
}
saveDatabase();
}
clearMenuForm();
displayMenuList();
loadMenuButtons();
alert('✅ Menu item saved successfully!');
}
function editMenuItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('itemName').value = item.name;
document.getElementById('itemPrice').value = item.price;
document.getElementById('itemCategory').value = item.category;
document.getElementById('itemDescription').value = item.description || '';
document.getElementById('itemAvailable').value = item.available;
document.getElementById('editingItemId').value = item.id;
}
}
function deleteMenuItem(id) {
if (confirm('🗑️ Are you sure you want to delete this menu item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM menu_items WHERE id = ?", [id]);
saveDatabase();
}
displayMenuList();
loadMenuButtons();
alert('✅ Menu item deleted successfully!');
}
}
function clearMenuForm() {
document.getElementById('itemName').value = '';
document.getElementById('itemPrice').value = '';
document.getElementById('itemDescription').value = '';
document.getElementById('itemAvailable').value = '1';
document.getElementById('editingItemId').value = '';
}
// Analytics
function loadAnalytics() {
updateAnalytics();
}
function updateAnalytics() {
if (!DB_CONFIG.useSQLite) return;
const timeframe = document.getElementById('analyticsTimeframe').value;
const { startDate, endDate } = getDateRange(timeframe);
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at <= ?"
);
const stats = stmt.get([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const avgOrder = stats.orders > 0 ? stats.sales / stats.orders : 0;
document.getElementById('totalSales').textContent = '
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
= ? AND created_at <= ?
`);
const orders = topItemStmt.all([startDate.toISOString(), endDate.toISOString()]);
topItemStmt.free();
const itemCounts = {};
orders.forEach(order => {
const items = JSON.parse(order.order_items);
items.forEach(item => {
itemCounts[item.name] = (itemCounts[item.name] || 0) + item.quantity;
});
});
const topItem = Object.keys(itemCounts).reduce((a, b) =>
itemCounts[a] > itemCounts[b] ? a : b, '-'
);
document.getElementById('topItem').textContent = topItem;
displayOrderHistory(startDate, endDate);
}
function getDateRange(timeframe) {
const now = new Date();
let startDate, endDate = new Date(now);
switch(timeframe) {
case 'daily':
startDate = new Date(now);
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'weekly':
startDate = new Date(now);
startDate.setDate(now.getDate() - now.getDay());
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'monthly':
startDate = new Date(now.getFullYear(), now.getMonth(), 1);
endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
break;
case 'yearly':
startDate = new Date(now.getFullYear(), 0, 1);
endDate = new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999);
break;
}
return { startDate, endDate };
}
function displayOrderHistory(startDate, endDate) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare(
"SELECT * FROM orders WHERE created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT 50"
);
const orders = stmt.all([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const tbody = document.getElementById('orderHistoryBody');
tbody.innerHTML = '';
orders.forEach(order => {
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name}(${item.quantity})`).join(', ');
const row = document.createElement('tr');
row.innerHTML = `
#${order.id} |
${order.customer_name} |
${itemsList} |
${order.total.toFixed(2)} |
${new Date(order.created_at).toLocaleString()} |
|
`;
tbody.appendChild(row);
});
}
// Inventory Management
function loadInventoryManagement() {
displayInventoryList();
}
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
if (item.stock <= 0) {
stockClass = 'stock-out';
stockText = '❌ Out of Stock';
} else if (item.stock <= item.reorder_level) {
stockClass = 'stock-low';
stockText = '⚠️ Low Stock';
}
itemDiv.innerHTML = `
💰 Cost: ${item.cost.toFixed(2)} per ${item.unit}
📊 Reorder at: ${item.reorder_level} ${item.unit}
`;
container.appendChild(itemDiv);
});
}
function saveInventoryItem() {
const name = document.getElementById('inventoryName').value.trim();
const stock = parseFloat(document.getElementById('inventoryStock').value);
const cost = parseFloat(document.getElementById('inventoryCost').value);
const unit = document.getElementById('inventoryUnit').value.trim();
const reorderLevel = parseFloat(document.getElementById('inventoryReorderLevel').value);
const editingId = document.getElementById('editingInventoryId').value;
if (!name || isNaN(stock) || isNaN(cost) || !unit || isNaN(reorderLevel)) {
alert('❌ Please fill all fields correctly');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE inventory SET name = ?, stock = ?, cost = ?, unit = ?, reorder_level = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
[name, stock, cost, unit, reorderLevel, editingId]
);
} else {
db.run(
"INSERT INTO inventory (name, stock, cost, unit, reorder_level) VALUES (?, ?, ?, ?, ?)",
[name, stock, cost, unit, reorderLevel]
);
}
saveDatabase();
}
clearInventoryForm();
displayInventoryList();
alert('✅ Inventory item saved successfully!');
}
function editInventoryItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('inventoryName').value = item.name;
document.getElementById('inventoryStock').value = item.stock;
document.getElementById('inventoryCost').value = item.cost;
document.getElementById('inventoryUnit').value = item.unit;
document.getElementById('inventoryReorderLevel').value = item.reorder_level;
document.getElementById('editingInventoryId').value = item.id;
}
}
function deleteInventoryItem(id) {
if (confirm('🗑️ Are you sure you want to delete this inventory item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM inventory WHERE id = ?", [id]);
saveDatabase();
}
displayInventoryList();
alert('✅ Inventory item deleted successfully!');
}
}
function clearInventoryForm() {
document.getElementById('inventoryName').value = '';
document.getElementById('inventoryStock').value = '';
document.getElementById('inventoryCost').value = '';
document.getElementById('inventoryUnit').value = '';
document.getElementById('inventoryReorderLevel').value = '';
document.getElementById('editingInventoryId').value = '';
}
// User Management
function loadUserManagement() {
if (currentUser?.role !== 'admin') {
alert('❌ Access denied. Admin privileges required.');
showTab('orders');
return;
}
displayUsersList();
}
function displayUsersList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE active = 1 ORDER BY role, username");
const users = stmt.all();
stmt.free();
const container = document.getElementById('usersList');
container.innerHTML = '';
users.forEach(user => {
const userDiv = document.createElement('div');
userDiv.className = 'user-card';
userDiv.innerHTML = `
📧 ${user.email || 'No email'}
📅 Created: ${new Date(user.created_at).toLocaleDateString()}
`;
container.appendChild(userDiv);
});
}
function saveUser() {
const username = document.getElementById('newUsername').value.trim();
const password = document.getElementById('newPassword').value;
const fullName = document.getElementById('newUserFullName').value.trim();
const role = document.getElementById('newUserRole').value;
const email = document.getElementById('newUserEmail').value.trim();
const editingId = document.getElementById('editingUserId').value;
if (!username || !password || !fullName) {
alert('❌ Please fill in username, password, and full name');
return;
}
if (DB_CONFIG.useSQLite) {
try {
if (editingId) {
db.run(
"UPDATE users SET username = ?, password = ?, role = ?, full_name = ?, email = ? WHERE id = ?",
[username, password, role, fullName, email, editingId]
);
} else {
db.run(
"INSERT INTO users (username, password, role, full_name, email) VALUES (?, ?, ?, ?, ?)",
[username, password, role, fullName, email]
);
}
saveDatabase();
clearUserForm();
displayUsersList();
alert('✅ User saved successfully!');
} catch (error) {
if (error.message.includes('UNIQUE constraint failed')) {
alert('❌ Username already exists. Please choose a different username.');
} else {
alert('❌ Error saving user: ' + error.message);
}
}
}
}
function editUser(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE id = ?");
const user = stmt.get([id]);
stmt.free();
if (user) {
document.getElementById('newUsername').value = user.username;
document.getElementById('newPassword').value = user.password;
document.getElementById('newUserFullName').value = user.full_name || '';
document.getElementById('newUserRole').value = user.role;
document.getElementById('newUserEmail').value = user.email || '';
document.getElementById('editingUserId').value = user.id;
}
}
function deleteUser(id) {
if (confirm('🗑️ Are you sure you want to delete this user? This action cannot be undone.')) {
if (DB_CONFIG.useSQLite) {
db.run("UPDATE users SET active = 0 WHERE id = ?", [id]);
saveDatabase();
}
displayUsersList();
alert('✅ User deleted successfully!');
}
}
function clearUserForm() {
document.getElementById('newUsername').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('newUserFullName').value = '';
document.getElementById('newUserRole').value = 'employee';
document.getElementById('newUserEmail').value = '';
document.getElementById('editingUserId').value = '';
}
// Print Receipt
function printReceipt(orderId) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders WHERE id = ?");
const order = stmt.get([orderId]);
stmt.free();
if (!order) return;
const orderItems = JSON.parse(order.order_items);
let receiptContent = `
CY FRYING
CY YOU NEED US TO FRY
📞 (937) 527-3203
Order #: ${order.id}
Customer: ${order.customer_name}
${order.customer_phone ? `
Phone: ${order.customer_phone}
` : ''}
Date: ${new Date(order.created_at).toLocaleString()}
`;
orderItems.forEach(item => {
const itemTotal = item.price * item.quantity;
receiptContent += `
${item.name} x${item.quantity}
${itemTotal.toFixed(2)}
`;
});
receiptContent += `
TOTAL:
${order.total.toFixed(2)}
Thank you for your business!
🍟 Come back soon! 🍟
`;
const printWindow = window.open('', '_blank');
printWindow.document.write(`
Receipt - Order #${order.id}
${receiptContent}
`);
printWindow.document.close();
printWindow.print();
printWindow.close();
}
// Keyboard Shortcuts
document.addEventListener('keydown', function(e) {
// Only when not typing in inputs
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
switch(e.key) {
case '1':
if (currentUser) showTab('orders');
break;
case '2':
if (currentUser) showTab('menu');
break;
case '3':
if (currentUser) showTab('analytics');
break;
case '4':
if (currentUser) showTab('inventory');
break;
case 'Enter':
if (!currentUser && !document.getElementById('loginScreen').classList.contains('hidden')) {
e.preventDefault();
attemptLogin();
} else if (currentOrder.length > 0) {
e.preventDefault();
completeOrder();
}
break;
case 'Escape':
if (currentOrder.length > 0) {
clearOrder();
}
break;
}
});
// Touch optimizations
let touchStartY = 0;
document.addEventListener('touchstart', function(e) {
touchStartY = e.touches[0].clientY;
});
document.addEventListener('touchmove', function(e) {
const touchY = e.touches[0].clientY;
const touchDiff = touchStartY - touchY;
// Prevent bounce scrolling
if (touchDiff > 0 && window.pageYOffset === 0) {
e.preventDefault();
}
}, { passive: false });
// Auto-save and backup
setInterval(() => {
if (db && DB_CONFIG.useSQLite) {
saveDatabase();
}
}, 30000); // Save every 30 seconds
// Orientation change handler
window.addEventListener('orientationchange', function() {
setTimeout(() => {
window.scrollTo(0, 0);
}, 100);
});
// Network status
window.addEventListener('online', function() {
updateStatus('Online');
});
window.addEventListener('offline', function() {
updateStatus('Offline');
});
// Initialize app when page loads
document.addEventListener('DOMContentLoaded', function() {
initDatabase().then(() => {
console.log('✅ Cy Frying Food Truck System loaded successfully!');
}).catch(error => {
console.error('❌ Failed to initialize:', error);
alert('Failed to initialize database. Please refresh the page.');
});
});
// Prevent zoom on double tap
let lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
const now = (new Date()).getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);
// Service worker for offline support (optional)
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').catch(function(error) {
console.log('ServiceWorker registration failed:', error);
});
});
}
console.log('🚚 Cy Frying Food Truck Management System Ready!');
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
{
const items = typeof order.order_items === 'string' ? JSON.parse(order.order_items) : order.order_items;
items.forEach(item => {
itemCounts[item.name] = (itemCounts[item.name] || 0) + item.quantity;
});
});
const topItem = Object.keys(itemCounts).reduce((a, b) =>
itemCounts[a] > itemCounts[b] ? a : b, '-'
);
document.getElementById('topItem').textContent = topItem;
displayOrderHistory(orders);
} catch (error) {
console.error('Error updating analytics:', error);
}
}
// Update Dashboard with API
async function updateDashboard() {
try {
const today = new Date();
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
let todayStats = { orders: 0, sales: 0 };
if (DB_CONFIG.useSQLite) {
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at < ?"
);
todayStats = stmt.get([today.toISOString(), tomorrow.toISOString()]);
stmt.free();
} else if (db?.connected) {
todayStats = await apiCall('/analytics/daily');
} else if (window.offlineData) {
const todayOrders = window.offlineData.orders.filter(order => {
const orderDate = new Date(order.created_at);
return orderDate >= today && orderDate < tomorrow;
});
todayStats = {
orders: todayOrders.length,
sales: todayOrders.reduce((sum, order) => sum + order.total, 0)
};
}
document.getElementById('todayOrders').textContent = todayStats.orders;
document.getElementById('todaySales').textContent = '
function loginSuccess(user) {
currentUser = user;
document.getElementById('loginScreen').classList.add('hidden');
document.getElementById('mainApp').classList.remove('hidden');
document.getElementById('currentUser').textContent = user.full_name || user.username;
// Hide user management for non-admins
if (user.role !== 'admin') {
document.getElementById('usersTabBtn').style.display = 'none';
}
clearLoginForm();
loadInitialData();
}
function showLoginError(message) {
const errorDiv = document.getElementById('loginError');
errorDiv.textContent = message;
errorDiv.classList.remove('hidden');
setTimeout(() => errorDiv.classList.add('hidden'), 3000);
}
function clearLoginForm() {
document.getElementById('username').value = '';
document.getElementById('password').value = '';
document.getElementById('loginError').classList.add('hidden');
}
function logout() {
currentUser = null;
currentOrder = [];
document.getElementById('loginScreen').classList.remove('hidden');
document.getElementById('mainApp').classList.add('hidden');
clearLoginForm();
}
// Tab Management
function showTab(tabName) {
document.querySelectorAll('.tab-content').forEach(tab => tab.classList.add('hidden'));
document.querySelectorAll('.nav-tab').forEach(tab => tab.classList.remove('active'));
document.getElementById(tabName + 'Tab').classList.remove('hidden');
event.target.classList.add('active');
switch(tabName) {
case 'orders':
loadOrderManagement();
break;
case 'menu':
loadMenuManagement();
break;
case 'analytics':
loadAnalytics();
break;
case 'inventory':
loadInventoryManagement();
break;
case 'users':
loadUserManagement();
break;
}
}
// Load Initial Data
function loadInitialData() {
updateDashboard();
loadOrderManagement();
updateOrderTime();
setInterval(updateOrderTime, 1000);
}
function updateOrderTime() {
const now = new Date();
document.getElementById('orderTime').textContent = now.toLocaleTimeString();
}
function updateDashboard() {
const today = new Date();
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
if (DB_CONFIG.useSQLite) {
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at < ?"
);
const stats = stmt.get([today.toISOString(), tomorrow.toISOString()]);
stmt.free();
document.getElementById('todayOrders').textContent = stats.orders;
document.getElementById('todaySales').textContent = '
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
{
const button = document.createElement('button');
button.className = 'menu-btn';
button.onclick = () => addToOrder(item);
button.innerHTML = `
${item.name}
${item.price.toFixed(2)}
`;
container.appendChild(button);
});
}
function addToOrder(item) {
const existing = currentOrder.find(orderItem => orderItem.id === item.id);
if (existing) {
existing.quantity++;
} else {
currentOrder.push({ ...item, quantity: 1 });
}
displayCurrentOrder();
// Haptic feedback on mobile
if (navigator.vibrate) {
navigator.vibrate(50);
}
}
function displayCurrentOrder() {
const container = document.getElementById('orderItems');
const totalDiv = document.getElementById('orderTotal');
container.innerHTML = '';
let total = 0;
currentOrder.forEach((item, index) => {
const itemDiv = document.createElement('div');
itemDiv.className = 'order-item';
const itemTotal = item.price * item.quantity;
total += itemTotal;
itemDiv.innerHTML = `
${item.name}
${item.price.toFixed(2)} each
${item.quantity}
${itemTotal.toFixed(2)}
`;
container.appendChild(itemDiv);
});
totalDiv.textContent = `Total: ${total.toFixed(2)}`;
}
function increaseQuantity(index) {
currentOrder[index].quantity++;
displayCurrentOrder();
}
function decreaseQuantity(index) {
if (currentOrder[index].quantity > 1) {
currentOrder[index].quantity--;
} else {
currentOrder.splice(index, 1);
}
displayCurrentOrder();
}
function clearOrder() {
currentOrder = [];
displayCurrentOrder();
}
function completeOrder() {
if (currentOrder.length === 0) {
alert('❌ No items in order');
return;
}
const customerName = document.getElementById('customerName').value.trim() || 'Walk-in';
const customerPhone = document.getElementById('customerPhone').value.trim();
const total = currentOrder.reduce((sum, item) => sum + (item.price * item.quantity), 0);
const orderData = {
customer_name: customerName,
customer_phone: customerPhone,
total: total,
order_items: JSON.stringify(currentOrder),
user_id: currentUser.id
};
if (DB_CONFIG.useSQLite) {
db.run(
"INSERT INTO orders (customer_name, customer_phone, total, order_items, user_id) VALUES (?, ?, ?, ?, ?)",
[orderData.customer_name, orderData.customer_phone, orderData.total, orderData.order_items, orderData.user_id]
);
saveDatabase();
}
// Success feedback
alert(`✅ Order completed!\n\nCustomer: ${customerName}\nTotal: ${total.toFixed(2)}\nItems: ${currentOrder.length}`);
// Clear form
currentOrder = [];
document.getElementById('customerName').value = '';
document.getElementById('customerPhone').value = '';
displayCurrentOrder();
updateDashboard();
loadRecentOrders();
// Haptic feedback
if (navigator.vibrate) {
navigator.vibrate([100, 50, 100]);
}
}
function loadRecentOrders() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders ORDER BY created_at DESC LIMIT 10");
const orders = stmt.all();
stmt.free();
const container = document.getElementById('recentOrders');
container.innerHTML = '';
orders.forEach(order => {
const orderDiv = document.createElement('div');
orderDiv.className = 'order-card';
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name} (${item.quantity})`).join(', ');
orderDiv.innerHTML = `
👤 ${order.customer_name}
${order.customer_phone ? `📞 ${order.customer_phone}` : ''}
${itemsList}
🕒 ${new Date(order.created_at).toLocaleString()}
`;
container.appendChild(orderDiv);
});
}
// Menu Management
function loadMenuManagement() {
displayMenuList();
}
function displayMenuList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items ORDER BY category, name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('menuList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'menu-card';
itemDiv.innerHTML = `
${item.description || 'No description'}
`;
container.appendChild(itemDiv);
});
}
function saveMenuItem() {
const name = document.getElementById('itemName').value.trim();
const price = parseFloat(document.getElementById('itemPrice').value);
const category = document.getElementById('itemCategory').value;
const description = document.getElementById('itemDescription').value.trim();
const available = parseInt(document.getElementById('itemAvailable').value);
const editingId = document.getElementById('editingItemId').value;
if (!name || isNaN(price)) {
alert('❌ Please enter item name and price');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE menu_items SET name = ?, price = ?, category = ?, description = ?, available = ? WHERE id = ?",
[name, price, category, description, available, editingId]
);
} else {
db.run(
"INSERT INTO menu_items (name, price, category, description, available) VALUES (?, ?, ?, ?, ?)",
[name, price, category, description, available]
);
}
saveDatabase();
}
clearMenuForm();
displayMenuList();
loadMenuButtons();
alert('✅ Menu item saved successfully!');
}
function editMenuItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('itemName').value = item.name;
document.getElementById('itemPrice').value = item.price;
document.getElementById('itemCategory').value = item.category;
document.getElementById('itemDescription').value = item.description || '';
document.getElementById('itemAvailable').value = item.available;
document.getElementById('editingItemId').value = item.id;
}
}
function deleteMenuItem(id) {
if (confirm('🗑️ Are you sure you want to delete this menu item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM menu_items WHERE id = ?", [id]);
saveDatabase();
}
displayMenuList();
loadMenuButtons();
alert('✅ Menu item deleted successfully!');
}
}
function clearMenuForm() {
document.getElementById('itemName').value = '';
document.getElementById('itemPrice').value = '';
document.getElementById('itemDescription').value = '';
document.getElementById('itemAvailable').value = '1';
document.getElementById('editingItemId').value = '';
}
// Analytics
function loadAnalytics() {
updateAnalytics();
}
function updateAnalytics() {
if (!DB_CONFIG.useSQLite) return;
const timeframe = document.getElementById('analyticsTimeframe').value;
const { startDate, endDate } = getDateRange(timeframe);
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at <= ?"
);
const stats = stmt.get([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const avgOrder = stats.orders > 0 ? stats.sales / stats.orders : 0;
document.getElementById('totalSales').textContent = '
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
= ? AND created_at <= ?
`);
const orders = topItemStmt.all([startDate.toISOString(), endDate.toISOString()]);
topItemStmt.free();
const itemCounts = {};
orders.forEach(order => {
const items = JSON.parse(order.order_items);
items.forEach(item => {
itemCounts[item.name] = (itemCounts[item.name] || 0) + item.quantity;
});
});
const topItem = Object.keys(itemCounts).reduce((a, b) =>
itemCounts[a] > itemCounts[b] ? a : b, '-'
);
document.getElementById('topItem').textContent = topItem;
displayOrderHistory(startDate, endDate);
}
function getDateRange(timeframe) {
const now = new Date();
let startDate, endDate = new Date(now);
switch(timeframe) {
case 'daily':
startDate = new Date(now);
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'weekly':
startDate = new Date(now);
startDate.setDate(now.getDate() - now.getDay());
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'monthly':
startDate = new Date(now.getFullYear(), now.getMonth(), 1);
endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
break;
case 'yearly':
startDate = new Date(now.getFullYear(), 0, 1);
endDate = new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999);
break;
}
return { startDate, endDate };
}
function displayOrderHistory(startDate, endDate) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare(
"SELECT * FROM orders WHERE created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT 50"
);
const orders = stmt.all([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const tbody = document.getElementById('orderHistoryBody');
tbody.innerHTML = '';
orders.forEach(order => {
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name}(${item.quantity})`).join(', ');
const row = document.createElement('tr');
row.innerHTML = `
#${order.id} |
${order.customer_name} |
${itemsList} |
${order.total.toFixed(2)} |
${new Date(order.created_at).toLocaleString()} |
|
`;
tbody.appendChild(row);
});
}
// Inventory Management
function loadInventoryManagement() {
displayInventoryList();
}
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
if (item.stock <= 0) {
stockClass = 'stock-out';
stockText = '❌ Out of Stock';
} else if (item.stock <= item.reorder_level) {
stockClass = 'stock-low';
stockText = '⚠️ Low Stock';
}
itemDiv.innerHTML = `
💰 Cost: ${item.cost.toFixed(2)} per ${item.unit}
📊 Reorder at: ${item.reorder_level} ${item.unit}
`;
container.appendChild(itemDiv);
});
}
function saveInventoryItem() {
const name = document.getElementById('inventoryName').value.trim();
const stock = parseFloat(document.getElementById('inventoryStock').value);
const cost = parseFloat(document.getElementById('inventoryCost').value);
const unit = document.getElementById('inventoryUnit').value.trim();
const reorderLevel = parseFloat(document.getElementById('inventoryReorderLevel').value);
const editingId = document.getElementById('editingInventoryId').value;
if (!name || isNaN(stock) || isNaN(cost) || !unit || isNaN(reorderLevel)) {
alert('❌ Please fill all fields correctly');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE inventory SET name = ?, stock = ?, cost = ?, unit = ?, reorder_level = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
[name, stock, cost, unit, reorderLevel, editingId]
);
} else {
db.run(
"INSERT INTO inventory (name, stock, cost, unit, reorder_level) VALUES (?, ?, ?, ?, ?)",
[name, stock, cost, unit, reorderLevel]
);
}
saveDatabase();
}
clearInventoryForm();
displayInventoryList();
alert('✅ Inventory item saved successfully!');
}
function editInventoryItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('inventoryName').value = item.name;
document.getElementById('inventoryStock').value = item.stock;
document.getElementById('inventoryCost').value = item.cost;
document.getElementById('inventoryUnit').value = item.unit;
document.getElementById('inventoryReorderLevel').value = item.reorder_level;
document.getElementById('editingInventoryId').value = item.id;
}
}
function deleteInventoryItem(id) {
if (confirm('🗑️ Are you sure you want to delete this inventory item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM inventory WHERE id = ?", [id]);
saveDatabase();
}
displayInventoryList();
alert('✅ Inventory item deleted successfully!');
}
}
function clearInventoryForm() {
document.getElementById('inventoryName').value = '';
document.getElementById('inventoryStock').value = '';
document.getElementById('inventoryCost').value = '';
document.getElementById('inventoryUnit').value = '';
document.getElementById('inventoryReorderLevel').value = '';
document.getElementById('editingInventoryId').value = '';
}
// User Management
function loadUserManagement() {
if (currentUser?.role !== 'admin') {
alert('❌ Access denied. Admin privileges required.');
showTab('orders');
return;
}
displayUsersList();
}
function displayUsersList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE active = 1 ORDER BY role, username");
const users = stmt.all();
stmt.free();
const container = document.getElementById('usersList');
container.innerHTML = '';
users.forEach(user => {
const userDiv = document.createElement('div');
userDiv.className = 'user-card';
userDiv.innerHTML = `
📧 ${user.email || 'No email'}
📅 Created: ${new Date(user.created_at).toLocaleDateString()}
`;
container.appendChild(userDiv);
});
}
function saveUser() {
const username = document.getElementById('newUsername').value.trim();
const password = document.getElementById('newPassword').value;
const fullName = document.getElementById('newUserFullName').value.trim();
const role = document.getElementById('newUserRole').value;
const email = document.getElementById('newUserEmail').value.trim();
const editingId = document.getElementById('editingUserId').value;
if (!username || !password || !fullName) {
alert('❌ Please fill in username, password, and full name');
return;
}
if (DB_CONFIG.useSQLite) {
try {
if (editingId) {
db.run(
"UPDATE users SET username = ?, password = ?, role = ?, full_name = ?, email = ? WHERE id = ?",
[username, password, role, fullName, email, editingId]
);
} else {
db.run(
"INSERT INTO users (username, password, role, full_name, email) VALUES (?, ?, ?, ?, ?)",
[username, password, role, fullName, email]
);
}
saveDatabase();
clearUserForm();
displayUsersList();
alert('✅ User saved successfully!');
} catch (error) {
if (error.message.includes('UNIQUE constraint failed')) {
alert('❌ Username already exists. Please choose a different username.');
} else {
alert('❌ Error saving user: ' + error.message);
}
}
}
}
function editUser(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE id = ?");
const user = stmt.get([id]);
stmt.free();
if (user) {
document.getElementById('newUsername').value = user.username;
document.getElementById('newPassword').value = user.password;
document.getElementById('newUserFullName').value = user.full_name || '';
document.getElementById('newUserRole').value = user.role;
document.getElementById('newUserEmail').value = user.email || '';
document.getElementById('editingUserId').value = user.id;
}
}
function deleteUser(id) {
if (confirm('🗑️ Are you sure you want to delete this user? This action cannot be undone.')) {
if (DB_CONFIG.useSQLite) {
db.run("UPDATE users SET active = 0 WHERE id = ?", [id]);
saveDatabase();
}
displayUsersList();
alert('✅ User deleted successfully!');
}
}
function clearUserForm() {
document.getElementById('newUsername').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('newUserFullName').value = '';
document.getElementById('newUserRole').value = 'employee';
document.getElementById('newUserEmail').value = '';
document.getElementById('editingUserId').value = '';
}
// Print Receipt
function printReceipt(orderId) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders WHERE id = ?");
const order = stmt.get([orderId]);
stmt.free();
if (!order) return;
const orderItems = JSON.parse(order.order_items);
let receiptContent = `
CY FRYING
CY YOU NEED US TO FRY
📞 (937) 527-3203
Order #: ${order.id}
Customer: ${order.customer_name}
${order.customer_phone ? `
Phone: ${order.customer_phone}
` : ''}
Date: ${new Date(order.created_at).toLocaleString()}
`;
orderItems.forEach(item => {
const itemTotal = item.price * item.quantity;
receiptContent += `
${item.name} x${item.quantity}
${itemTotal.toFixed(2)}
`;
});
receiptContent += `
TOTAL:
${order.total.toFixed(2)}
Thank you for your business!
🍟 Come back soon! 🍟
`;
const printWindow = window.open('', '_blank');
printWindow.document.write(`
Receipt - Order #${order.id}
${receiptContent}
`);
printWindow.document.close();
printWindow.print();
printWindow.close();
}
// Keyboard Shortcuts
document.addEventListener('keydown', function(e) {
// Only when not typing in inputs
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
switch(e.key) {
case '1':
if (currentUser) showTab('orders');
break;
case '2':
if (currentUser) showTab('menu');
break;
case '3':
if (currentUser) showTab('analytics');
break;
case '4':
if (currentUser) showTab('inventory');
break;
case 'Enter':
if (!currentUser && !document.getElementById('loginScreen').classList.contains('hidden')) {
e.preventDefault();
attemptLogin();
} else if (currentOrder.length > 0) {
e.preventDefault();
completeOrder();
}
break;
case 'Escape':
if (currentOrder.length > 0) {
clearOrder();
}
break;
}
});
// Touch optimizations
let touchStartY = 0;
document.addEventListener('touchstart', function(e) {
touchStartY = e.touches[0].clientY;
});
document.addEventListener('touchmove', function(e) {
const touchY = e.touches[0].clientY;
const touchDiff = touchStartY - touchY;
// Prevent bounce scrolling
if (touchDiff > 0 && window.pageYOffset === 0) {
e.preventDefault();
}
}, { passive: false });
// Auto-save and backup
setInterval(() => {
if (db && DB_CONFIG.useSQLite) {
saveDatabase();
}
}, 30000); // Save every 30 seconds
// Orientation change handler
window.addEventListener('orientationchange', function() {
setTimeout(() => {
window.scrollTo(0, 0);
}, 100);
});
// Network status
window.addEventListener('online', function() {
updateStatus('Online');
});
window.addEventListener('offline', function() {
updateStatus('Offline');
});
// Initialize app when page loads
document.addEventListener('DOMContentLoaded', function() {
initDatabase().then(() => {
console.log('✅ Cy Frying Food Truck System loaded successfully!');
}).catch(error => {
console.error('❌ Failed to initialize:', error);
alert('Failed to initialize database. Please refresh the page.');
});
});
// Prevent zoom on double tap
let lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
const now = (new Date()).getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);
// Service worker for offline support (optional)
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').catch(function(error) {
console.log('ServiceWorker registration failed:', error);
});
});
}
console.log('🚚 Cy Frying Food Truck Management System Ready!');
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
0) {
localStorage.removeItem('cyFryingOfflineOrders');
console.log(`✅ Synced ${offlineOrders.length} offline orders`);
}
} catch (error) {
console.error('Error syncing offline data:', error);
}
}
// Network status monitoring
window.addEventListener('online', function() {
updateStatus('Online - Reconnected');
if (db && !db.connected) {
// Try to reconnect
setTimeout(() => {
initDatabase().then(() => {
syncOfflineData();
});
}, 1000);
}
});
window.addEventListener('offline', function() {
updateStatus('Offline Mode');
if (db) {
db.connected = false;
}
});
function loginSuccess(user) {
currentUser = user;
document.getElementById('loginScreen').classList.add('hidden');
document.getElementById('mainApp').classList.remove('hidden');
document.getElementById('currentUser').textContent = user.full_name || user.username;
// Hide user management for non-admins
if (user.role !== 'admin') {
document.getElementById('usersTabBtn').style.display = 'none';
}
clearLoginForm();
loadInitialData();
}
function showLoginError(message) {
const errorDiv = document.getElementById('loginError');
errorDiv.textContent = message;
errorDiv.classList.remove('hidden');
setTimeout(() => errorDiv.classList.add('hidden'), 3000);
}
function clearLoginForm() {
document.getElementById('username').value = '';
document.getElementById('password').value = '';
document.getElementById('loginError').classList.add('hidden');
}
function logout() {
currentUser = null;
currentOrder = [];
document.getElementById('loginScreen').classList.remove('hidden');
document.getElementById('mainApp').classList.add('hidden');
clearLoginForm();
}
// Tab Management
function showTab(tabName) {
document.querySelectorAll('.tab-content').forEach(tab => tab.classList.add('hidden'));
document.querySelectorAll('.nav-tab').forEach(tab => tab.classList.remove('active'));
document.getElementById(tabName + 'Tab').classList.remove('hidden');
event.target.classList.add('active');
switch(tabName) {
case 'orders':
loadOrderManagement();
break;
case 'menu':
loadMenuManagement();
break;
case 'analytics':
loadAnalytics();
break;
case 'inventory':
loadInventoryManagement();
break;
case 'users':
loadUserManagement();
break;
}
}
// Load Initial Data
function loadInitialData() {
updateDashboard();
loadOrderManagement();
updateOrderTime();
setInterval(updateOrderTime, 1000);
}
function updateOrderTime() {
const now = new Date();
document.getElementById('orderTime').textContent = now.toLocaleTimeString();
}
function updateDashboard() {
const today = new Date();
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
if (DB_CONFIG.useSQLite) {
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at < ?"
);
const stats = stmt.get([today.toISOString(), tomorrow.toISOString()]);
stmt.free();
document.getElementById('todayOrders').textContent = stats.orders;
document.getElementById('todaySales').textContent = '
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
{
const button = document.createElement('button');
button.className = 'menu-btn';
button.onclick = () => addToOrder(item);
button.innerHTML = `
${item.name}
${item.price.toFixed(2)}
`;
container.appendChild(button);
});
}
function addToOrder(item) {
const existing = currentOrder.find(orderItem => orderItem.id === item.id);
if (existing) {
existing.quantity++;
} else {
currentOrder.push({ ...item, quantity: 1 });
}
displayCurrentOrder();
// Haptic feedback on mobile
if (navigator.vibrate) {
navigator.vibrate(50);
}
}
function displayCurrentOrder() {
const container = document.getElementById('orderItems');
const totalDiv = document.getElementById('orderTotal');
container.innerHTML = '';
let total = 0;
currentOrder.forEach((item, index) => {
const itemDiv = document.createElement('div');
itemDiv.className = 'order-item';
const itemTotal = item.price * item.quantity;
total += itemTotal;
itemDiv.innerHTML = `
${item.name}
${item.price.toFixed(2)} each
${item.quantity}
${itemTotal.toFixed(2)}
`;
container.appendChild(itemDiv);
});
totalDiv.textContent = `Total: ${total.toFixed(2)}`;
}
function increaseQuantity(index) {
currentOrder[index].quantity++;
displayCurrentOrder();
}
function decreaseQuantity(index) {
if (currentOrder[index].quantity > 1) {
currentOrder[index].quantity--;
} else {
currentOrder.splice(index, 1);
}
displayCurrentOrder();
}
function clearOrder() {
currentOrder = [];
displayCurrentOrder();
}
function completeOrder() {
if (currentOrder.length === 0) {
alert('❌ No items in order');
return;
}
const customerName = document.getElementById('customerName').value.trim() || 'Walk-in';
const customerPhone = document.getElementById('customerPhone').value.trim();
const total = currentOrder.reduce((sum, item) => sum + (item.price * item.quantity), 0);
const orderData = {
customer_name: customerName,
customer_phone: customerPhone,
total: total,
order_items: JSON.stringify(currentOrder),
user_id: currentUser.id
};
if (DB_CONFIG.useSQLite) {
db.run(
"INSERT INTO orders (customer_name, customer_phone, total, order_items, user_id) VALUES (?, ?, ?, ?, ?)",
[orderData.customer_name, orderData.customer_phone, orderData.total, orderData.order_items, orderData.user_id]
);
saveDatabase();
}
// Success feedback
alert(`✅ Order completed!\n\nCustomer: ${customerName}\nTotal: ${total.toFixed(2)}\nItems: ${currentOrder.length}`);
// Clear form
currentOrder = [];
document.getElementById('customerName').value = '';
document.getElementById('customerPhone').value = '';
displayCurrentOrder();
updateDashboard();
loadRecentOrders();
// Haptic feedback
if (navigator.vibrate) {
navigator.vibrate([100, 50, 100]);
}
}
function loadRecentOrders() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders ORDER BY created_at DESC LIMIT 10");
const orders = stmt.all();
stmt.free();
const container = document.getElementById('recentOrders');
container.innerHTML = '';
orders.forEach(order => {
const orderDiv = document.createElement('div');
orderDiv.className = 'order-card';
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name} (${item.quantity})`).join(', ');
orderDiv.innerHTML = `
👤 ${order.customer_name}
${order.customer_phone ? `📞 ${order.customer_phone}` : ''}
${itemsList}
🕒 ${new Date(order.created_at).toLocaleString()}
`;
container.appendChild(orderDiv);
});
}
// Menu Management
function loadMenuManagement() {
displayMenuList();
}
function displayMenuList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items ORDER BY category, name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('menuList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'menu-card';
itemDiv.innerHTML = `
${item.description || 'No description'}
`;
container.appendChild(itemDiv);
});
}
function saveMenuItem() {
const name = document.getElementById('itemName').value.trim();
const price = parseFloat(document.getElementById('itemPrice').value);
const category = document.getElementById('itemCategory').value;
const description = document.getElementById('itemDescription').value.trim();
const available = parseInt(document.getElementById('itemAvailable').value);
const editingId = document.getElementById('editingItemId').value;
if (!name || isNaN(price)) {
alert('❌ Please enter item name and price');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE menu_items SET name = ?, price = ?, category = ?, description = ?, available = ? WHERE id = ?",
[name, price, category, description, available, editingId]
);
} else {
db.run(
"INSERT INTO menu_items (name, price, category, description, available) VALUES (?, ?, ?, ?, ?)",
[name, price, category, description, available]
);
}
saveDatabase();
}
clearMenuForm();
displayMenuList();
loadMenuButtons();
alert('✅ Menu item saved successfully!');
}
function editMenuItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM menu_items WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('itemName').value = item.name;
document.getElementById('itemPrice').value = item.price;
document.getElementById('itemCategory').value = item.category;
document.getElementById('itemDescription').value = item.description || '';
document.getElementById('itemAvailable').value = item.available;
document.getElementById('editingItemId').value = item.id;
}
}
function deleteMenuItem(id) {
if (confirm('🗑️ Are you sure you want to delete this menu item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM menu_items WHERE id = ?", [id]);
saveDatabase();
}
displayMenuList();
loadMenuButtons();
alert('✅ Menu item deleted successfully!');
}
}
function clearMenuForm() {
document.getElementById('itemName').value = '';
document.getElementById('itemPrice').value = '';
document.getElementById('itemDescription').value = '';
document.getElementById('itemAvailable').value = '1';
document.getElementById('editingItemId').value = '';
}
// Analytics
function loadAnalytics() {
updateAnalytics();
}
function updateAnalytics() {
if (!DB_CONFIG.useSQLite) return;
const timeframe = document.getElementById('analyticsTimeframe').value;
const { startDate, endDate } = getDateRange(timeframe);
const stmt = db.prepare(
"SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as sales FROM orders WHERE created_at >= ? AND created_at <= ?"
);
const stats = stmt.get([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const avgOrder = stats.orders > 0 ? stats.sales / stats.orders : 0;
document.getElementById('totalSales').textContent = '
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory
👥 User Management
= ? AND created_at <= ?
`);
const orders = topItemStmt.all([startDate.toISOString(), endDate.toISOString()]);
topItemStmt.free();
const itemCounts = {};
orders.forEach(order => {
const items = JSON.parse(order.order_items);
items.forEach(item => {
itemCounts[item.name] = (itemCounts[item.name] || 0) + item.quantity;
});
});
const topItem = Object.keys(itemCounts).reduce((a, b) =>
itemCounts[a] > itemCounts[b] ? a : b, '-'
);
document.getElementById('topItem').textContent = topItem;
displayOrderHistory(startDate, endDate);
}
function getDateRange(timeframe) {
const now = new Date();
let startDate, endDate = new Date(now);
switch(timeframe) {
case 'daily':
startDate = new Date(now);
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'weekly':
startDate = new Date(now);
startDate.setDate(now.getDate() - now.getDay());
startDate.setHours(0, 0, 0, 0);
endDate.setHours(23, 59, 59, 999);
break;
case 'monthly':
startDate = new Date(now.getFullYear(), now.getMonth(), 1);
endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
break;
case 'yearly':
startDate = new Date(now.getFullYear(), 0, 1);
endDate = new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999);
break;
}
return { startDate, endDate };
}
function displayOrderHistory(startDate, endDate) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare(
"SELECT * FROM orders WHERE created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT 50"
);
const orders = stmt.all([startDate.toISOString(), endDate.toISOString()]);
stmt.free();
const tbody = document.getElementById('orderHistoryBody');
tbody.innerHTML = '';
orders.forEach(order => {
const items = JSON.parse(order.order_items);
const itemsList = items.map(item => `${item.name}(${item.quantity})`).join(', ');
const row = document.createElement('tr');
row.innerHTML = `
#${order.id} |
${order.customer_name} |
${itemsList} |
${order.total.toFixed(2)} |
${new Date(order.created_at).toLocaleString()} |
|
`;
tbody.appendChild(row);
});
}
// Inventory Management
function loadInventoryManagement() {
displayInventoryList();
}
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
function displayInventoryList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory ORDER BY name");
const items = stmt.all();
stmt.free();
const container = document.getElementById('inventoryList');
container.innerHTML = '';
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'inventory-card';
let stockClass = 'stock-good';
let stockText = '✅ Good Stock';
if (item.stock <= 0) {
stockClass = 'stock-out';
stockText = '❌ Out of Stock';
} else if (item.stock <= item.reorder_level) {
stockClass = 'stock-low';
stockText = '⚠️ Low Stock';
}
itemDiv.innerHTML = `
💰 Cost: ${item.cost.toFixed(2)} per ${item.unit}
📊 Reorder at: ${item.reorder_level} ${item.unit}
`;
container.appendChild(itemDiv);
});
}
function saveInventoryItem() {
const name = document.getElementById('inventoryName').value.trim();
const stock = parseFloat(document.getElementById('inventoryStock').value);
const cost = parseFloat(document.getElementById('inventoryCost').value);
const unit = document.getElementById('inventoryUnit').value.trim();
const reorderLevel = parseFloat(document.getElementById('inventoryReorderLevel').value);
const editingId = document.getElementById('editingInventoryId').value;
if (!name || isNaN(stock) || isNaN(cost) || !unit || isNaN(reorderLevel)) {
alert('❌ Please fill all fields correctly');
return;
}
if (DB_CONFIG.useSQLite) {
if (editingId) {
db.run(
"UPDATE inventory SET name = ?, stock = ?, cost = ?, unit = ?, reorder_level = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
[name, stock, cost, unit, reorderLevel, editingId]
);
} else {
db.run(
"INSERT INTO inventory (name, stock, cost, unit, reorder_level) VALUES (?, ?, ?, ?, ?)",
[name, stock, cost, unit, reorderLevel]
);
}
saveDatabase();
}
clearInventoryForm();
displayInventoryList();
alert('✅ Inventory item saved successfully!');
}
function editInventoryItem(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM inventory WHERE id = ?");
const item = stmt.get([id]);
stmt.free();
if (item) {
document.getElementById('inventoryName').value = item.name;
document.getElementById('inventoryStock').value = item.stock;
document.getElementById('inventoryCost').value = item.cost;
document.getElementById('inventoryUnit').value = item.unit;
document.getElementById('inventoryReorderLevel').value = item.reorder_level;
document.getElementById('editingInventoryId').value = item.id;
}
}
function deleteInventoryItem(id) {
if (confirm('🗑️ Are you sure you want to delete this inventory item?')) {
if (DB_CONFIG.useSQLite) {
db.run("DELETE FROM inventory WHERE id = ?", [id]);
saveDatabase();
}
displayInventoryList();
alert('✅ Inventory item deleted successfully!');
}
}
function clearInventoryForm() {
document.getElementById('inventoryName').value = '';
document.getElementById('inventoryStock').value = '';
document.getElementById('inventoryCost').value = '';
document.getElementById('inventoryUnit').value = '';
document.getElementById('inventoryReorderLevel').value = '';
document.getElementById('editingInventoryId').value = '';
}
// User Management
function loadUserManagement() {
if (currentUser?.role !== 'admin') {
alert('❌ Access denied. Admin privileges required.');
showTab('orders');
return;
}
displayUsersList();
}
function displayUsersList() {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE active = 1 ORDER BY role, username");
const users = stmt.all();
stmt.free();
const container = document.getElementById('usersList');
container.innerHTML = '';
users.forEach(user => {
const userDiv = document.createElement('div');
userDiv.className = 'user-card';
userDiv.innerHTML = `
📧 ${user.email || 'No email'}
📅 Created: ${new Date(user.created_at).toLocaleDateString()}
`;
container.appendChild(userDiv);
});
}
function saveUser() {
const username = document.getElementById('newUsername').value.trim();
const password = document.getElementById('newPassword').value;
const fullName = document.getElementById('newUserFullName').value.trim();
const role = document.getElementById('newUserRole').value;
const email = document.getElementById('newUserEmail').value.trim();
const editingId = document.getElementById('editingUserId').value;
if (!username || !password || !fullName) {
alert('❌ Please fill in username, password, and full name');
return;
}
if (DB_CONFIG.useSQLite) {
try {
if (editingId) {
db.run(
"UPDATE users SET username = ?, password = ?, role = ?, full_name = ?, email = ? WHERE id = ?",
[username, password, role, fullName, email, editingId]
);
} else {
db.run(
"INSERT INTO users (username, password, role, full_name, email) VALUES (?, ?, ?, ?, ?)",
[username, password, role, fullName, email]
);
}
saveDatabase();
clearUserForm();
displayUsersList();
alert('✅ User saved successfully!');
} catch (error) {
if (error.message.includes('UNIQUE constraint failed')) {
alert('❌ Username already exists. Please choose a different username.');
} else {
alert('❌ Error saving user: ' + error.message);
}
}
}
}
function editUser(id) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM users WHERE id = ?");
const user = stmt.get([id]);
stmt.free();
if (user) {
document.getElementById('newUsername').value = user.username;
document.getElementById('newPassword').value = user.password;
document.getElementById('newUserFullName').value = user.full_name || '';
document.getElementById('newUserRole').value = user.role;
document.getElementById('newUserEmail').value = user.email || '';
document.getElementById('editingUserId').value = user.id;
}
}
function deleteUser(id) {
if (confirm('🗑️ Are you sure you want to delete this user? This action cannot be undone.')) {
if (DB_CONFIG.useSQLite) {
db.run("UPDATE users SET active = 0 WHERE id = ?", [id]);
saveDatabase();
}
displayUsersList();
alert('✅ User deleted successfully!');
}
}
function clearUserForm() {
document.getElementById('newUsername').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('newUserFullName').value = '';
document.getElementById('newUserRole').value = 'employee';
document.getElementById('newUserEmail').value = '';
document.getElementById('editingUserId').value = '';
}
// Print Receipt
function printReceipt(orderId) {
if (!DB_CONFIG.useSQLite) return;
const stmt = db.prepare("SELECT * FROM orders WHERE id = ?");
const order = stmt.get([orderId]);
stmt.free();
if (!order) return;
const orderItems = JSON.parse(order.order_items);
let receiptContent = `
CY FRYING
CY YOU NEED US TO FRY
📞 (937) 527-3203
Order #: ${order.id}
Customer: ${order.customer_name}
${order.customer_phone ? `
Phone: ${order.customer_phone}
` : ''}
Date: ${new Date(order.created_at).toLocaleString()}
`;
orderItems.forEach(item => {
const itemTotal = item.price * item.quantity;
receiptContent += `
${item.name} x${item.quantity}
${itemTotal.toFixed(2)}
`;
});
receiptContent += `
TOTAL:
${order.total.toFixed(2)}
Thank you for your business!
🍟 Come back soon! 🍟
`;
const printWindow = window.open('', '_blank');
printWindow.document.write(`
Receipt - Order #${order.id}
${receiptContent}
`);
printWindow.document.close();
printWindow.print();
printWindow.close();
}
// Keyboard Shortcuts
document.addEventListener('keydown', function(e) {
// Only when not typing in inputs
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
switch(e.key) {
case '1':
if (currentUser) showTab('orders');
break;
case '2':
if (currentUser) showTab('menu');
break;
case '3':
if (currentUser) showTab('analytics');
break;
case '4':
if (currentUser) showTab('inventory');
break;
case 'Enter':
if (!currentUser && !document.getElementById('loginScreen').classList.contains('hidden')) {
e.preventDefault();
attemptLogin();
} else if (currentOrder.length > 0) {
e.preventDefault();
completeOrder();
}
break;
case 'Escape':
if (currentOrder.length > 0) {
clearOrder();
}
break;
}
});
// Touch optimizations
let touchStartY = 0;
document.addEventListener('touchstart', function(e) {
touchStartY = e.touches[0].clientY;
});
document.addEventListener('touchmove', function(e) {
const touchY = e.touches[0].clientY;
const touchDiff = touchStartY - touchY;
// Prevent bounce scrolling
if (touchDiff > 0 && window.pageYOffset === 0) {
e.preventDefault();
}
}, { passive: false });
// Auto-save and backup
setInterval(() => {
if (db && DB_CONFIG.useSQLite) {
saveDatabase();
}
}, 30000); // Save every 30 seconds
// Orientation change handler
window.addEventListener('orientationchange', function() {
setTimeout(() => {
window.scrollTo(0, 0);
}, 100);
});
// Network status
window.addEventListener('online', function() {
updateStatus('Online');
});
window.addEventListener('offline', function() {
updateStatus('Offline');
});
// Initialize app when page loads
document.addEventListener('DOMContentLoaded', function() {
initDatabase().then(() => {
console.log('✅ Cy Frying Food Truck System loaded successfully!');
}).catch(error => {
console.error('❌ Failed to initialize:', error);
alert('Failed to initialize database. Please refresh the page.');
});
});
// Prevent zoom on double tap
let lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
const now = (new Date()).getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);
// Service worker for offline support (optional)
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').catch(function(error) {
console.log('ServiceWorker registration failed:', error);
});
});
}
console.log('🚚 Cy Frying Food Truck Management System Ready!');
Cy Frying - Food Truck Management
Total: $0.00
📋 Recent Orders
📊 Sales Analytics
📋 Order History
Order # |
Customer |
Items |
Total |
Time |
Actions |
📦 Inventory Management
Add/Edit Inventory Item
Current Inventory