Update templates/menu.html
Browse files- templates/menu.html +172 -45
templates/menu.html
CHANGED
@@ -15,7 +15,6 @@
|
|
15 |
{% endfor %}
|
16 |
{% endfor %}
|
17 |
<style>
|
18 |
-
/* Existing styles remain unchanged */
|
19 |
body {
|
20 |
font-family: Arial, sans-serif;
|
21 |
background-color: #fdf4e3;
|
@@ -1001,7 +1000,9 @@
|
|
1001 |
<div>
|
1002 |
<h5 class="card-title">{{ item.Name | default('Unnamed Item') }}</h5>
|
1003 |
<p class="card-text price">${{ item.Price__c | default('0.00') }}</p>
|
1004 |
-
|
|
|
|
|
1005 |
</div>
|
1006 |
<div class="d-flex flex-column align-item-center justify-content-center">
|
1007 |
<div class="button-container"
|
@@ -1010,12 +1011,16 @@
|
|
1010 |
data-item-image="{{ item.Image2__c | default(item.Image1__c) | default('/static/placeholder.jpg') }}"
|
1011 |
data-item-section="{{ item.Section__c | default(section) }}"
|
1012 |
data-item-category="{{ selected_category }}">
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
|
|
|
|
|
|
|
|
1019 |
{% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' and item.Section__c != 'Soft Drinks' %}
|
1020 |
<span class="customisable-text">Customisable</span>
|
1021 |
{% endif %}
|
@@ -1023,16 +1028,18 @@
|
|
1023 |
</div>
|
1024 |
</div>
|
1025 |
</div>
|
1026 |
-
|
1027 |
-
<
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
|
|
|
|
1036 |
</div>
|
1037 |
</div>
|
1038 |
{% endfor %}
|
@@ -1110,6 +1117,35 @@
|
|
1110 |
</div>
|
1111 |
</div>
|
1112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1113 |
<!-- Mic Popup -->
|
1114 |
<div class="mic-popup" id="micPopup">
|
1115 |
<div class="mic-popup-icon">
|
@@ -1127,6 +1163,7 @@
|
|
1127 |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
1128 |
<script>
|
1129 |
let isProcessingRequest = false;
|
|
|
1130 |
|
1131 |
const menuItems = [
|
1132 |
{% for section, items in ordered_menu.items() %}
|
@@ -1204,6 +1241,79 @@
|
|
1204 |
};
|
1205 |
}
|
1206 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1207 |
function updateCartUI(cart) {
|
1208 |
if (!Array.isArray(cart)) {
|
1209 |
console.error('Invalid cart data:', cart);
|
@@ -1242,31 +1352,36 @@
|
|
1242 |
|
1243 |
const addButton = itemElement.querySelector('.btn-primary');
|
1244 |
const buttonContainer = addButton.closest('.button-container');
|
1245 |
-
const name = buttonContainer.getAttribute('data-item-name');
|
1246 |
-
const price = buttonContainer.getAttribute('data-item-price');
|
1247 |
-
const image = buttonContainer.getAttribute('data-item-image');
|
1248 |
-
const category = buttonContainer.getAttribute('data-item-category');
|
1249 |
const section = buttonContainer.getAttribute('data-item-section');
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
1256 |
-
|
1257 |
-
|
1258 |
-
|
1259 |
-
|
1260 |
-
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1270 |
}
|
1271 |
|
1272 |
sessionStorage.removeItem('highlightItem');
|
@@ -1657,6 +1772,18 @@
|
|
1657 |
quantityInput.value = qty + 1;
|
1658 |
});
|
1659 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1660 |
const micIcon = document.getElementById('micIcon');
|
1661 |
const micUnsupported = document.getElementById('micUnsupported');
|
1662 |
const micPopup = document.getElementById('micPopup');
|
@@ -1826,8 +1953,7 @@
|
|
1826 |
handleAddonClick(event.target);
|
1827 |
}
|
1828 |
});
|
1829 |
-
|
1830 |
-
function handleAddonClick(checkbox) {
|
1831 |
const groupName = checkbox.getAttribute('data-group');
|
1832 |
const isMultiSelectGroup = ["Extra Toppings", "Choose Raita/Sides", "Select Dip/Sauce", "Extra Add-ons", "Make it"].includes(groupName);
|
1833 |
const checkboxes = document.querySelectorAll(`.addon-option[data-group="${groupName}"]`);
|
@@ -1898,4 +2024,5 @@
|
|
1898 |
}
|
1899 |
</script>
|
1900 |
</body>
|
1901 |
-
</html>
|
|
|
|
15 |
{% endfor %}
|
16 |
{% endfor %}
|
17 |
<style>
|
|
|
18 |
body {
|
19 |
font-family: Arial, sans-serif;
|
20 |
background-color: #fdf4e3;
|
|
|
1000 |
<div>
|
1001 |
<h5 class="card-title">{{ item.Name | default('Unnamed Item') }}</h5>
|
1002 |
<p class="card-text price">${{ item.Price__c | default('0.00') }}</p>
|
1003 |
+
{% if item.Section__c != 'Soft Drinks' %}
|
1004 |
+
<div class="toggle-details" data-item-name="{{ item.Name | default('Unnamed Item') }}">Show Details</div>
|
1005 |
+
{% endif %}
|
1006 |
</div>
|
1007 |
<div class="d-flex flex-column align-item-center justify-content-center">
|
1008 |
<div class="button-container"
|
|
|
1011 |
data-item-image="{{ item.Image2__c | default(item.Image1__c) | default('/static/placeholder.jpg') }}"
|
1012 |
data-item-section="{{ item.Section__c | default(section) }}"
|
1013 |
data-item-category="{{ selected_category }}">
|
1014 |
+
{% if item.Section__c == 'Soft Drinks' %}
|
1015 |
+
<button class="btn btn-primary add-to-cart-btn" onclick="showSoftDrinkModal(this)">ADD</button>
|
1016 |
+
{% else %}
|
1017 |
+
<button class="btn btn-primary"
|
1018 |
+
data-bs-toggle="modal"
|
1019 |
+
data-bs-target="#itemModal"
|
1020 |
+
onclick="showItemDetails('{{ item.Name | default('Unnamed Item') | e }}', '{{ item.Price__c | default('0.00') }}', '{{ item.Image2__c | default(item.Image1__c) | default('/static/placeholder.jpg') }}', '{{ item.Description__c | default('No description') | e }}', '{{ item.IngredientsInfo__c | default('Not specified') | e }}', '{{ item.NutritionalInfo__c | default('Not available') | e }}', '{{ item.Allergens__c | default('None listed') | e }}', '{{ item.Section__c | default(section) | e }}', '{{ selected_category | e }}')">
|
1021 |
+
ADD
|
1022 |
+
</button>
|
1023 |
+
{% endif %}
|
1024 |
{% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' and item.Section__c != 'Soft Drinks' %}
|
1025 |
<span class="customisable-text">Customisable</span>
|
1026 |
{% endif %}
|
|
|
1028 |
</div>
|
1029 |
</div>
|
1030 |
</div>
|
1031 |
+
{% if item.Section__c != 'Soft Drinks' %}
|
1032 |
+
<div class="item-details" id="details-{{ item.Name | default('unnamed-item') | replace(' ', '-') }}">
|
1033 |
+
<h6>Description</h6>
|
1034 |
+
<p>{{ item.Description__c | default('No description available') }}</p>
|
1035 |
+
<h6>Ingredients Info</h6>
|
1036 |
+
<p>{{ item.IngredientsInfo__c | default('Not specified') }}</p>
|
1037 |
+
<h6>Nutritional Info</h6>
|
1038 |
+
север <p>{{ item.NutritionalInfo__c | default('Not available') }}</p>
|
1039 |
+
<h6>Allergens</h6>
|
1040 |
+
<p>{{ item.Allergens__c | default('None listed') }}</p>
|
1041 |
+
</div>
|
1042 |
+
{% endif %}
|
1043 |
</div>
|
1044 |
</div>
|
1045 |
{% endfor %}
|
|
|
1117 |
</div>
|
1118 |
</div>
|
1119 |
|
1120 |
+
<!-- Modal for Soft Drinks Quantity Selection -->
|
1121 |
+
<div class="modal fade" id="softDrinkModal" tabindex="-1" aria-labelledby="softDrinkModalLabel" aria-hidden="true">
|
1122 |
+
<div class="modal-dialog modal-dialog-centered">
|
1123 |
+
<div class="modal-content" style="border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
|
1124 |
+
<div class="modal-header" style="background: linear-gradient(45deg, #0FAA39, #0D9232); color: white; border-radius: 15px 15px 0 0;">
|
1125 |
+
<h5 class="modal-title" id="softDrinkModalLabel">Select Your Drink</h5>
|
1126 |
+
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
1127 |
+
</div>
|
1128 |
+
<div class="modal-body" style="padding: 20px;">
|
1129 |
+
<div class="text-center mb-4">
|
1130 |
+
<img id="soft-drink-image" class="img-fluid rounded mb-3" alt="Soft Drink Image" style="max-height: 150px; width: auto; object-fit: contain;">
|
1131 |
+
<h5 id="soft-drink-name" class="fw-bold" style="color: #333;"></h5>
|
1132 |
+
<p id="soft-drink-price" class="text-muted" style="font-size: 1.1rem;"></p>
|
1133 |
+
</div>
|
1134 |
+
<div class="d-flex justify-content-center align-items-center mb-4">
|
1135 |
+
<div class="quantity-selector" style="background-color: #f8f9fa; padding: 10px; border-radius: 10px;">
|
1136 |
+
<button type="button" class="btn btn-outline-secondary" id="soft-drink-decrease" style="width: 40px; height: 40px;">-</button>
|
1137 |
+
<input type="text" class="form-control text-center mx-2" id="soft-drink-quantity" value="1" readonly style="width: 60px; font-weight: bold; font-size: 1.1rem;">
|
1138 |
+
<button type="button" class="btn btn-outline-secondary" id="soft-drink-increase" style="width: 40px; height: 40px;">+</button>
|
1139 |
+
</div>
|
1140 |
+
</div>
|
1141 |
+
</div>
|
1142 |
+
<div class="modal-footer" style="border-top: none; padding: 0 20px 20px 20px; justify-content: center;">
|
1143 |
+
<button type="button" class="btn btn-primary" onclick="addSoftDrinkToCart()" style="width: 200px; padding: 12px; font-size: 1.1rem; background-color: #0FAA39; border-color: #0FAA39;">Add to Cart</button>
|
1144 |
+
</div>
|
1145 |
+
</div>
|
1146 |
+
</div>
|
1147 |
+
</div>
|
1148 |
+
|
1149 |
<!-- Mic Popup -->
|
1150 |
<div class="mic-popup" id="micPopup">
|
1151 |
<div class="mic-popup-icon">
|
|
|
1163 |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
1164 |
<script>
|
1165 |
let isProcessingRequest = false;
|
1166 |
+
let currentSoftDrinkButton = null;
|
1167 |
|
1168 |
const menuItems = [
|
1169 |
{% for section, items in ordered_menu.items() %}
|
|
|
1241 |
};
|
1242 |
}
|
1243 |
|
1244 |
+
function showSoftDrinkModal(button) {
|
1245 |
+
currentSoftDrinkButton = button;
|
1246 |
+
const buttonContainer = button.closest('.button-container');
|
1247 |
+
const itemName = sanitizeInput(buttonContainer.getAttribute('data-item-name'));
|
1248 |
+
const itemPrice = buttonContainer.getAttribute('data-item-price');
|
1249 |
+
const itemImage = buttonContainer.getAttribute('data-item-image');
|
1250 |
+
|
1251 |
+
document.getElementById('soft-drink-name').textContent = itemName;
|
1252 |
+
document.getElementById('soft-drink-price').textContent = `$${itemPrice}`;
|
1253 |
+
document.getElementById('soft-drink-quantity').value = '1';
|
1254 |
+
const softDrinkImage = document.getElementById('soft-drink-image');
|
1255 |
+
softDrinkImage.src = itemImage || '/static/placeholder.jpg';
|
1256 |
+
|
1257 |
+
const modal = new bootstrap.Modal(document.getElementById('softDrinkModal'));
|
1258 |
+
modal.show();
|
1259 |
+
}
|
1260 |
+
|
1261 |
+
function addSoftDrinkToCart() {
|
1262 |
+
if (!currentSoftDrinkButton) return;
|
1263 |
+
|
1264 |
+
const buttonContainer = currentSoftDrinkButton.closest('.button-container');
|
1265 |
+
const quantity = parseInt(document.getElementById('soft-drink-quantity').value) || 1;
|
1266 |
+
|
1267 |
+
const itemName = sanitizeInput(buttonContainer.getAttribute('data-item-name'));
|
1268 |
+
const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
|
1269 |
+
const itemImage = buttonContainer.getAttribute('data-item-image');
|
1270 |
+
const section = sanitizeInput(buttonContainer.getAttribute('data-item-section'));
|
1271 |
+
const selectedCategory = sanitizeInput(buttonContainer.getAttribute('data-item-category'));
|
1272 |
+
|
1273 |
+
const cartPayload = {
|
1274 |
+
itemName: itemName,
|
1275 |
+
itemPrice: itemPrice,
|
1276 |
+
itemImage: itemImage,
|
1277 |
+
section: section,
|
1278 |
+
category: selectedCategory,
|
1279 |
+
addons: [],
|
1280 |
+
instructions: '',
|
1281 |
+
quantity: quantity
|
1282 |
+
};
|
1283 |
+
|
1284 |
+
fetch('/cart/add', {
|
1285 |
+
method: 'POST',
|
1286 |
+
headers: {
|
1287 |
+
'Content-Type': 'application/json',
|
1288 |
+
},
|
1289 |
+
body: JSON.stringify(cartPayload)
|
1290 |
+
})
|
1291 |
+
.then(response => response.json())
|
1292 |
+
.then(data => {
|
1293 |
+
if (data.success) {
|
1294 |
+
alert('Item added to cart successfully!');
|
1295 |
+
updateCartUI(data.cart);
|
1296 |
+
const modal = bootstrap.Modal.getInstance(document.getElementById('softDrinkModal'));
|
1297 |
+
modal.hide();
|
1298 |
+
} else {
|
1299 |
+
console.error('Failed to add item to cart:', data.error);
|
1300 |
+
alert(data.error || 'Failed to add item to cart. Using local storage as fallback.');
|
1301 |
+
const cart = addToCartLocalStorage(cartPayload);
|
1302 |
+
updateCartUI(cart);
|
1303 |
+
const modal = bootstrap.Modal.getInstance(document.getElementById('softDrinkModal'));
|
1304 |
+
modal.hide();
|
1305 |
+
}
|
1306 |
+
})
|
1307 |
+
.catch(err => {
|
1308 |
+
console.error('Error adding item to cart:', err);
|
1309 |
+
alert('Error adding item to cart. Using local storage as fallback.');
|
1310 |
+
const cart = addToCartLocalStorage(cartPayload);
|
1311 |
+
updateCartUI(cart);
|
1312 |
+
const modal = bootstrap.Modal.getInstance(document.getElementById('softDrinkModal'));
|
1313 |
+
modal.hide();
|
1314 |
+
});
|
1315 |
+
}
|
1316 |
+
|
1317 |
function updateCartUI(cart) {
|
1318 |
if (!Array.isArray(cart)) {
|
1319 |
console.error('Invalid cart data:', cart);
|
|
|
1352 |
|
1353 |
const addButton = itemElement.querySelector('.btn-primary');
|
1354 |
const buttonContainer = addButton.closest('.button-container');
|
|
|
|
|
|
|
|
|
1355 |
const section = buttonContainer.getAttribute('data-item-section');
|
1356 |
+
|
1357 |
+
if (section === 'Soft Drinks') {
|
1358 |
+
showSoftDrinkModal(addButton);
|
1359 |
+
} else {
|
1360 |
+
const name = buttonContainer.getAttribute('data-item-name');
|
1361 |
+
const price = buttonContainer.getAttribute('data-item-price');
|
1362 |
+
const image = buttonContainer.getAttribute('data-item-image');
|
1363 |
+
const category = buttonContainer.getAttribute('data-item-category');
|
1364 |
+
|
1365 |
+
const description = itemElement.querySelector('.item-details h6:contains("Description") + p')?.textContent || 'No description available';
|
1366 |
+
const ingredients = itemElement.querySelector('.item-details h6:contains("Ingredients Info") + p')?.textContent || 'Not specified';
|
1367 |
+
const nutrition = itemElement.querySelector('.item-details h6:contains("Nutritional Info") + p')?.textContent || 'Not available';
|
1368 |
+
const allergens = itemElement.querySelector('.item-details h6:contains("Allergens") + p')?.textContent || 'None listed';
|
1369 |
+
|
1370 |
+
showItemDetails(
|
1371 |
+
name,
|
1372 |
+
price,
|
1373 |
+
image,
|
1374 |
+
description,
|
1375 |
+
ingredients,
|
1376 |
+
nutrition,
|
1377 |
+
allergens,
|
1378 |
+
section,
|
1379 |
+
category
|
1380 |
+
);
|
1381 |
+
|
1382 |
+
const modal = new bootstrap.Modal(document.getElementById('itemModal'));
|
1383 |
+
modal.show();
|
1384 |
+
}
|
1385 |
}
|
1386 |
|
1387 |
sessionStorage.removeItem('highlightItem');
|
|
|
1772 |
quantityInput.value = qty + 1;
|
1773 |
});
|
1774 |
|
1775 |
+
const softDrinkDecreaseBtn = document.getElementById('soft-drink-decrease');
|
1776 |
+
const softDrinkIncreaseBtn = document.getElementById('soft-drink-increase');
|
1777 |
+
const softDrinkQuantityInput = document.getElementById('soft-drink-quantity');
|
1778 |
+
softDrinkDecreaseBtn.addEventListener('click', function() {
|
1779 |
+
let qty = parseInt(softDrinkQuantityInput.value);
|
1780 |
+
if (qty > 1) softDrinkQuantityInput.value = qty - 1;
|
1781 |
+
});
|
1782 |
+
softDrinkIncreaseBtn.addEventListener('click', function() {
|
1783 |
+
let qty = parseInt(softDrinkQuantityInput.value);
|
1784 |
+
if (qty < 1000) softDrinkQuantityInput.value = qty + 1;
|
1785 |
+
});
|
1786 |
+
|
1787 |
const micIcon = document.getElementById('micIcon');
|
1788 |
const micUnsupported = document.getElementById('micUnsupported');
|
1789 |
const micPopup = document.getElementById('micPopup');
|
|
|
1953 |
handleAddonClick(event.target);
|
1954 |
}
|
1955 |
});
|
1956 |
+
function handleAddonClick(checkbox) {
|
|
|
1957 |
const groupName = checkbox.getAttribute('data-group');
|
1958 |
const isMultiSelectGroup = ["Extra Toppings", "Choose Raita/Sides", "Select Dip/Sauce", "Extra Add-ons", "Make it"].includes(groupName);
|
1959 |
const checkboxes = document.querySelectorAll(`.addon-option[data-group="${groupName}"]`);
|
|
|
2024 |
}
|
2025 |
</script>
|
2026 |
</body>
|
2027 |
+
</html>
|
2028 |
+
|