Spaces:
Sleeping
Sleeping
{% extends "base.html" %} | |
{% block title %}Menu - Table {{ table_number }} - Tabble-v3{% endblock %} | |
{% block extra_css %} | |
<style> | |
.menu-header { | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
color: white; | |
padding: 2rem 0; | |
} | |
.dish-card { | |
transition: transform 0.2s; | |
height: 100%; | |
} | |
.dish-card:hover { | |
transform: translateY(-2px); | |
} | |
.dish-image { | |
height: 200px; | |
object-fit: cover; | |
} | |
.category-tab { | |
border-radius: 25px; | |
margin: 0 5px; | |
} | |
.cart-fab { | |
position: fixed; | |
bottom: 20px; | |
right: 20px; | |
width: 60px; | |
height: 60px; | |
border-radius: 50%; | |
z-index: 1000; | |
} | |
.cart-count { | |
position: absolute; | |
top: -5px; | |
right: -5px; | |
background: #dc3545; | |
color: white; | |
border-radius: 50%; | |
width: 25px; | |
height: 25px; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
font-size: 12px; | |
font-weight: bold; | |
} | |
</style> | |
{% endblock %} | |
{% block content %} | |
<!-- Menu Header --> | |
<div class="menu-header"> | |
<div class="container text-center"> | |
<h2> | |
<i class="fas fa-utensils me-2"></i> | |
Restaurant Menu | |
</h2> | |
<p class="mb-0">Table {{ table_number }} | Order ID: {{ unique_id }}</p> | |
</div> | |
</div> | |
<div class="container mt-4"> | |
<!-- Table Info & Quick Actions --> | |
<div class="row mb-4"> | |
<div class="col-md-8"> | |
<div class="card"> | |
<div class="card-body py-2"> | |
<div class="row align-items-center"> | |
<div class="col-sm-6"> | |
<small class="text-muted">Dining at:</small> | |
<strong class="d-block">Demo Restaurant</strong> | |
</div> | |
<div class="col-sm-6 text-sm-end"> | |
<small class="text-muted">Table {{ table_number }}</small> | |
<div class="badge bg-success ms-2"> | |
<i class="fas fa-wifi me-1"></i>Connected | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="col-md-4"> | |
<div class="d-flex gap-2"> | |
<button class="btn btn-outline-primary flex-fill" onclick="viewOrders()"> | |
<i class="fas fa-history me-1"></i>Orders | |
</button> | |
<button class="btn btn-outline-success flex-fill" onclick="callWaiter()"> | |
<i class="fas fa-bell me-1"></i>Call Waiter | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Category Tabs --> | |
<div class="row mb-4"> | |
<div class="col-12"> | |
<div class="d-flex flex-wrap justify-content-center"> | |
<button class="btn btn-primary category-tab active" onclick="filterCategory('all')"> | |
All Items | |
</button> | |
<button class="btn btn-outline-primary category-tab" onclick="filterCategory('starters')"> | |
Starters | |
</button> | |
<button class="btn btn-outline-primary category-tab" onclick="filterCategory('main-course')"> | |
Main Course | |
</button> | |
<button class="btn btn-outline-primary category-tab" onclick="filterCategory('beverages')"> | |
Beverages | |
</button> | |
<button class="btn btn-outline-primary category-tab" onclick="filterCategory('desserts')"> | |
Desserts | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Menu Items --> | |
<div class="row" id="menu-items"> | |
<!-- Sample Dish 1 --> | |
<div class="col-md-4 col-sm-6 mb-4 menu-item" data-category="main-course"> | |
<div class="card dish-card"> | |
<img src="https://images.unsplash.com/photo-1563379091339-03246963d96c?w=400&h=200&fit=crop" | |
class="card-img-top dish-image" alt="Chicken Biryani"> | |
<div class="card-body"> | |
<div class="d-flex justify-content-between align-items-start mb-2"> | |
<h6 class="card-title mb-0">Chicken Biryani</h6> | |
<span class="badge bg-warning"> | |
<i class="fas fa-pepper-hot"></i> | |
</span> | |
</div> | |
<p class="card-text text-muted small"> | |
Aromatic basmati rice cooked with tender chicken and traditional spices | |
</p> | |
<div class="d-flex justify-content-between align-items-center"> | |
<strong class="text-success">₹250</strong> | |
<div class="btn-group btn-group-sm"> | |
<button class="btn btn-outline-secondary" onclick="updateQuantity('biryani', -1)">-</button> | |
<span class="btn btn-outline-secondary" id="qty-biryani">0</span> | |
<button class="btn btn-outline-secondary" onclick="updateQuantity('biryani', 1)">+</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Sample Dish 2 --> | |
<div class="col-md-4 col-sm-6 mb-4 menu-item" data-category="starters"> | |
<div class="card dish-card"> | |
<img src="https://images.unsplash.com/photo-1599487488170-d11ec9c172f0?w=400&h=200&fit=crop" | |
class="card-img-top dish-image" alt="Paneer Tikka"> | |
<div class="card-body"> | |
<div class="d-flex justify-content-between align-items-start mb-2"> | |
<h6 class="card-title mb-0">Paneer Tikka</h6> | |
<span class="badge bg-success"> | |
<i class="fas fa-leaf"></i> | |
</span> | |
</div> | |
<p class="card-text text-muted small"> | |
Marinated cottage cheese cubes grilled to perfection | |
</p> | |
<div class="d-flex justify-content-between align-items-center"> | |
<strong class="text-success">₹180</strong> | |
<div class="btn-group btn-group-sm"> | |
<button class="btn btn-outline-secondary" onclick="updateQuantity('paneer', -1)">-</button> | |
<span class="btn btn-outline-secondary" id="qty-paneer">0</span> | |
<button class="btn btn-outline-secondary" onclick="updateQuantity('paneer', 1)">+</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Sample Dish 3 --> | |
<div class="col-md-4 col-sm-6 mb-4 menu-item" data-category="beverages"> | |
<div class="card dish-card"> | |
<img src="https://images.unsplash.com/photo-1571091718767-18b5b1457add?w=400&h=200&fit=crop" | |
class="card-img-top dish-image" alt="Mango Lassi"> | |
<div class="card-body"> | |
<div class="d-flex justify-content-between align-items-start mb-2"> | |
<h6 class="card-title mb-0">Mango Lassi</h6> | |
<span class="badge bg-info"> | |
<i class="fas fa-snowflake"></i> | |
</span> | |
</div> | |
<p class="card-text text-muted small"> | |
Refreshing yogurt-based drink with fresh mango pulp | |
</p> | |
<div class="d-flex justify-content-between align-items-center"> | |
<strong class="text-success">₹80</strong> | |
<div class="btn-group btn-group-sm"> | |
<button class="btn btn-outline-secondary" onclick="updateQuantity('lassi', -1)">-</button> | |
<span class="btn btn-outline-secondary" id="qty-lassi">0</span> | |
<button class="btn btn-outline-secondary" onclick="updateQuantity('lassi', 1)">+</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Empty Menu State --> | |
<div id="no-items" class="text-center py-5" style="display: none;"> | |
<i class="fas fa-search fa-3x text-muted mb-3"></i> | |
<p class="text-muted">No items found in this category</p> | |
</div> | |
</div> | |
<!-- Floating Cart Button --> | |
<button class="btn btn-success cart-fab" onclick="openCart()" id="cart-btn" style="display: none;"> | |
<i class="fas fa-shopping-cart"></i> | |
<span class="cart-count" id="cart-count">0</span> | |
</button> | |
<!-- Cart Modal --> | |
<div class="modal fade" id="cartModal" tabindex="-1"> | |
<div class="modal-dialog modal-lg"> | |
<div class="modal-content"> | |
<div class="modal-header"> | |
<h5 class="modal-title"> | |
<i class="fas fa-shopping-cart me-2"></i>Your Order | |
</h5> | |
<button type="button" class="btn-close" data-bs-dismiss="modal"></button> | |
</div> | |
<div class="modal-body"> | |
<div id="cart-items"> | |
<!-- Cart items will be populated here --> | |
</div> | |
<hr> | |
<div class="d-flex justify-content-between"> | |
<strong>Total: ₹<span id="cart-total">0</span></strong> | |
</div> | |
</div> | |
<div class="modal-footer"> | |
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> | |
Continue Shopping | |
</button> | |
<button type="button" class="btn btn-success" onclick="placeOrder()"> | |
<i class="fas fa-check me-2"></i>Place Order | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endblock %} | |
{% block extra_js %} | |
<script> | |
let cart = {}; | |
let dishes = { | |
'biryani': { name: 'Chicken Biryani', price: 250 }, | |
'paneer': { name: 'Paneer Tikka', price: 180 }, | |
'lassi': { name: 'Mango Lassi', price: 80 } | |
}; | |
function filterCategory(category) { | |
// Update active tab | |
document.querySelectorAll('.category-tab').forEach(tab => { | |
tab.classList.remove('active', 'btn-primary'); | |
tab.classList.add('btn-outline-primary'); | |
}); | |
event.target.classList.remove('btn-outline-primary'); | |
event.target.classList.add('active', 'btn-primary'); | |
// Filter items | |
const items = document.querySelectorAll('.menu-item'); | |
let visibleCount = 0; | |
items.forEach(item => { | |
const itemCategory = item.dataset.category; | |
const show = category === 'all' || itemCategory === category; | |
item.style.display = show ? 'block' : 'none'; | |
if (show) visibleCount++; | |
}); | |
document.getElementById('no-items').style.display = visibleCount === 0 ? 'block' : 'none'; | |
} | |
function updateQuantity(dishId, change) { | |
if (!cart[dishId]) cart[dishId] = 0; | |
cart[dishId] += change; | |
if (cart[dishId] < 0) cart[dishId] = 0; | |
if (cart[dishId] === 0) delete cart[dishId]; | |
document.getElementById(`qty-${dishId}`).textContent = cart[dishId] || 0; | |
updateCartDisplay(); | |
} | |
function updateCartDisplay() { | |
const totalItems = Object.values(cart).reduce((sum, qty) => sum + qty, 0); | |
const cartBtn = document.getElementById('cart-btn'); | |
const cartCount = document.getElementById('cart-count'); | |
if (totalItems > 0) { | |
cartBtn.style.display = 'block'; | |
cartCount.textContent = totalItems; | |
} else { | |
cartBtn.style.display = 'none'; | |
} | |
} | |
function openCart() { | |
const cartItems = document.getElementById('cart-items'); | |
const cartTotal = document.getElementById('cart-total'); | |
let html = ''; | |
let total = 0; | |
for (let dishId in cart) { | |
const dish = dishes[dishId]; | |
const qty = cart[dishId]; | |
const subtotal = dish.price * qty; | |
total += subtotal; | |
html += ` | |
<div class="d-flex justify-content-between align-items-center mb-2"> | |
<div> | |
<strong>${dish.name}</strong> | |
<small class="text-muted d-block">₹${dish.price} each</small> | |
</div> | |
<div class="d-flex align-items-center"> | |
<span class="me-3">Qty: ${qty}</span> | |
<strong>₹${subtotal}</strong> | |
</div> | |
</div> | |
`; | |
} | |
if (html === '') { | |
html = '<p class="text-muted text-center">Your cart is empty</p>'; | |
} | |
cartItems.innerHTML = html; | |
cartTotal.textContent = total; | |
new bootstrap.Modal(document.getElementById('cartModal')).show(); | |
} | |
function placeOrder() { | |
if (Object.keys(cart).length === 0) { | |
alert('Your cart is empty!'); | |
return; | |
} | |
const total = Object.keys(cart).reduce((sum, dishId) => { | |
return sum + (dishes[dishId].price * cart[dishId]); | |
}, 0); | |
const orderSummary = Object.keys(cart).map(dishId => { | |
return `${cart[dishId]}x ${dishes[dishId].name}`; | |
}).join(', '); | |
if (confirm(`Place order for ₹${total}?\n\nItems: ${orderSummary}`)) { | |
alert('Order placed successfully! You will receive updates on the status.'); | |
cart = {}; | |
updateCartDisplay(); | |
// Reset all quantities | |
Object.keys(dishes).forEach(dishId => { | |
document.getElementById(`qty-${dishId}`).textContent = '0'; | |
}); | |
bootstrap.Modal.getInstance(document.getElementById('cartModal')).hide(); | |
} | |
} | |
function viewOrders() { | |
alert('Order history feature will show your past orders'); | |
} | |
function callWaiter() { | |
if (confirm('Call waiter to your table?')) { | |
alert('Waiter has been notified and will be at your table shortly!'); | |
} | |
} | |
</script> | |
{% endblock %} |