Spaces:
Runtime error
Runtime error
Update templates/menu.html
Browse files- templates/menu.html +228 -220
templates/menu.html
CHANGED
@@ -115,46 +115,45 @@
|
|
115 |
box-shadow: none;
|
116 |
transform: scale(0.98);
|
117 |
}
|
118 |
-
.
|
119 |
position: fixed;
|
120 |
bottom: 20px;
|
121 |
right: 20px;
|
122 |
z-index: 999;
|
123 |
-
}
|
124 |
-
.side-cart-button {
|
125 |
display: flex;
|
126 |
align-items: center;
|
127 |
-
|
128 |
-
|
129 |
-
height: 60px;
|
130 |
background-color: #0FAA39;
|
131 |
-
|
|
|
|
|
|
|
|
|
132 |
text-decoration: none;
|
133 |
-
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.
|
134 |
-
|
|
|
|
|
|
|
135 |
}
|
136 |
-
.
|
137 |
background-color: #109835;
|
138 |
-
|
139 |
-
}
|
140 |
-
.cart-icon {
|
141 |
-
font-size: 24px;
|
142 |
color: #fff;
|
143 |
}
|
144 |
-
.cart-
|
145 |
-
|
146 |
-
|
147 |
-
right: -5px;
|
148 |
-
background-color: #ff4d4d;
|
149 |
-
color: #fff;
|
150 |
-
font-size: 12px;
|
151 |
-
font-weight: bold;
|
152 |
-
width: 20px;
|
153 |
-
height: 20px;
|
154 |
border-radius: 50%;
|
|
|
|
|
155 |
display: flex;
|
156 |
align-items: center;
|
157 |
justify-content: center;
|
|
|
|
|
|
|
158 |
}
|
159 |
.avatar-dropdown-container {
|
160 |
position: absolute;
|
@@ -657,20 +656,13 @@
|
|
657 |
height: 18px;
|
658 |
font-size: 9px;
|
659 |
}
|
660 |
-
.
|
661 |
-
|
662 |
-
|
663 |
-
}
|
664 |
-
.side-cart-button {
|
665 |
-
width: 50px;
|
666 |
-
height: 50px;
|
667 |
-
}
|
668 |
-
.cart-icon {
|
669 |
-
font-size: 20px;
|
670 |
}
|
671 |
-
.cart-
|
672 |
-
width:
|
673 |
-
height:
|
674 |
font-size: 10px;
|
675 |
}
|
676 |
}
|
@@ -797,109 +789,11 @@
|
|
797 |
{% endif %}
|
798 |
</div>
|
799 |
|
800 |
-
<div class="side-cart-container">
|
801 |
-
<a href="{{ url_for('cart.cart') }}" class="side-cart-button" title="View Cart">
|
802 |
-
<i class="bi bi-cart3 cart-icon"></i>
|
803 |
-
<span class="cart-count" id="cart-count">0</span>
|
804 |
-
</a>
|
805 |
-
</div>
|
806 |
-
|
807 |
-
<form method="get" action="/menu" class="text-center mb-4" id="categoryForm">
|
808 |
-
<label class="form-label fw-bold">Select a Category:</label>
|
809 |
-
<div class="category-buttons">
|
810 |
-
{% for category in categories %}
|
811 |
-
<button type="button" class="category-button {% if selected_category == category %}selected{% endif %}" data-category="{{ category }}">{{ category }}</button>
|
812 |
-
{% endfor %}
|
813 |
-
<button type="button" class="category-button {% if selected_category == 'Customized Dish' %}selected{% endif %}" data-category="Customized Dish">Customized Dish</button>
|
814 |
-
</div>
|
815 |
-
<input type="hidden" name="category" id="selectedCategoryInput" value="{{ selected_category }}">
|
816 |
-
</form>
|
817 |
-
|
818 |
-
<div class="container mt-4">
|
819 |
-
{% if selected_category == "Customized Dish" %}
|
820 |
-
<div id="custom-dish-form" class="mt-4">
|
821 |
-
<h3>Create Your Custom Dish</h3>
|
822 |
-
<form method="POST" action="/customdish/generate_custom_dish">
|
823 |
-
<div class="mb-3">
|
824 |
-
<label for="custom-dish-name" class="form-label">Dish Name</label>
|
825 |
-
<input type="text" class="form-control" id="custom-dish-name" name="name" required>
|
826 |
-
</div>
|
827 |
-
<div class="mb-3">
|
828 |
-
<label for="custom-dish-description" class="form-label">Dish Description</label>
|
829 |
-
<textarea class="form-control" id="custom-dish-description" name="description" required></textarea>
|
830 |
-
</div>
|
831 |
-
<button type="submit" class="btn btn-primary">Submit</button>
|
832 |
-
</form>
|
833 |
-
</div>
|
834 |
-
{% else %}
|
835 |
-
{% for section, items in ordered_menu.items() %}
|
836 |
-
<h3>{{ section }}</h3>
|
837 |
-
<div class="row">
|
838 |
-
{% for item in items %}
|
839 |
-
<div class="col-md-6 mb-4">
|
840 |
-
<div class="card menu-card">
|
841 |
-
<picture>
|
842 |
-
<source srcset="{{ item.Image1__c_webp if item.Image1__c_webp else item.Image1__c }}" type="image/webp">
|
843 |
-
<img src="{{ item.Image1__c }}"
|
844 |
-
srcset="{{ item.Image1__c }} 350w, {{ item.Image1__c_small if item.Image1__c_small else item.Image1__c }} 175w"
|
845 |
-
sizes="(max-width: 576px) 175px, 350px"
|
846 |
-
class="card-img-top menu-image"
|
847 |
-
alt="{{ item.Name }}"
|
848 |
-
width="350" height="200"
|
849 |
-
loading="lazy"
|
850 |
-
onerror="this.src='/static/placeholder.jpg';">
|
851 |
-
</picture>
|
852 |
-
<div class="addbutton">
|
853 |
-
<div class="card-body d-flex align-items-center justify-content-between">
|
854 |
-
<div>
|
855 |
-
<h5 class="card-title">{{ item.Name }}</h5>
|
856 |
-
<p class="card-text">${{ item.Price__c }}</p>
|
857 |
-
</div>
|
858 |
-
<div class="d-flex flex-column align-item-center justify-content-center">
|
859 |
-
<div class="button-container" data-item-name="{{ item.Name }}" data-item-price="{{ item.Price__c }}" data-item-image="{{ item.Image1__c }}" data-item-section="{{ item.Section__c }}" data-item-category="{{ selected_category }}">
|
860 |
-
{% if item.Section__c == 'Soft Drinks' %}
|
861 |
-
<button class="btn btn-primary add-to-cart-btn" onclick="handleSoftDrinkAdd(this)">ADD</button>
|
862 |
-
<div class="quantity-selector" style="display: none;">
|
863 |
-
<button class="btn btn-outline-secondary decrease-btn" onclick="decreaseQuantity(this)">-</button>
|
864 |
-
<select class="quantity-to-remove">
|
865 |
-
{% for i in range(1, 21) %}
|
866 |
-
<option value="{{ i }}">{{ i }}</option>
|
867 |
-
{% endfor %}
|
868 |
-
</select>
|
869 |
-
<span class="quantity-display">0</span>
|
870 |
-
<button class="btn btn-outline-secondary increase-btn" onclick="increaseQuantity(this)">+</button>
|
871 |
-
<select class="quantity-to-add">
|
872 |
-
{% for i in range(1, 21) %}
|
873 |
-
<option value="{{ i }}">{{ i }}</option>
|
874 |
-
{% endfor %}
|
875 |
-
</select>
|
876 |
-
</div>
|
877 |
-
{% else %}
|
878 |
-
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal"
|
879 |
-
onclick="showItemDetails('{{ item.Name }}', '{{ item.Price__c }}', '{{ item.Image2__c }}', '{{ item.Description__c }}', '{{ item.Section__c }}','{{ selected_category }}')">
|
880 |
-
ADD
|
881 |
-
</button>
|
882 |
-
{% endif %}
|
883 |
-
{% if item.Section__c != 'Apetizer' and item.Section__c != 'Customized dish' and item.Section__c !='Soft Drinks' %}
|
884 |
-
<span class="customisable-text">Customisable</span>
|
885 |
-
{% endif %}
|
886 |
-
</div>
|
887 |
-
</div>
|
888 |
-
</div>
|
889 |
-
</div>
|
890 |
-
<div class="toggle-details" data-item-name="{{ item.Name }}">Show Details</div>
|
891 |
-
<div class="item-details" id="details-{{ item.Name | replace(' ', '-') }}"></div>
|
892 |
-
</div>
|
893 |
-
</div>
|
894 |
-
{% endfor %}
|
895 |
-
</div>
|
896 |
-
{% endfor %}
|
897 |
-
{% endif %}
|
898 |
-
</div>
|
899 |
-
|
900 |
<div class="view-cart-container">
|
901 |
<a href="{{ url_for('cart.cart') }}" class="view-cart-button">
|
|
|
902 |
View Cart
|
|
|
903 |
</a>
|
904 |
</div>
|
905 |
|
@@ -957,28 +851,30 @@
|
|
957 |
</div>
|
958 |
|
959 |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
960 |
-
|
961 |
<script>
|
962 |
-
//
|
963 |
const menuItems = [
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
"
|
973 |
-
"
|
974 |
-
"
|
975 |
-
"
|
976 |
-
"
|
977 |
-
"
|
978 |
-
"
|
979 |
-
"
|
980 |
-
"
|
981 |
-
"
|
|
|
|
|
|
|
982 |
];
|
983 |
|
984 |
const menuItemDetails = {
|
@@ -1177,15 +1073,22 @@
|
|
1177 |
entries.forEach(entry => {
|
1178 |
if (entry.isIntersecting) {
|
1179 |
const img = entry.target;
|
|
|
|
|
|
|
|
|
1180 |
img.onload = () => img.classList.add('loaded');
|
1181 |
-
img.onerror = () =>
|
|
|
|
|
|
|
1182 |
observer.unobserve(img);
|
1183 |
}
|
1184 |
});
|
1185 |
}, {
|
1186 |
root: null,
|
1187 |
-
rootMargin: '
|
1188 |
-
threshold: 0.
|
1189 |
});
|
1190 |
|
1191 |
menuCards.forEach(card => cardObserver.observe(card));
|
@@ -1219,7 +1122,6 @@
|
|
1219 |
});
|
1220 |
});
|
1221 |
|
1222 |
-
// Autocomplete functionality
|
1223 |
const searchBar = document.getElementById('searchBar');
|
1224 |
const suggestionsContainer = document.getElementById('autocompleteSuggestions');
|
1225 |
|
@@ -1230,7 +1132,7 @@
|
|
1230 |
|
1231 |
if (input) {
|
1232 |
const filteredItems = menuItems.filter(item =>
|
1233 |
-
item.toLowerCase().
|
1234 |
);
|
1235 |
if (filteredItems.length > 0) {
|
1236 |
filteredItems.forEach(item => {
|
@@ -1247,6 +1149,7 @@
|
|
1247 |
suggestionsContainer.style.display = 'block';
|
1248 |
}
|
1249 |
}
|
|
|
1250 |
});
|
1251 |
|
1252 |
document.addEventListener('click', function (event) {
|
@@ -1255,7 +1158,93 @@
|
|
1255 |
}
|
1256 |
});
|
1257 |
|
1258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1259 |
});
|
1260 |
|
1261 |
function debounce(func, wait) {
|
@@ -1266,6 +1255,48 @@
|
|
1266 |
};
|
1267 |
}
|
1268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1269 |
function showItemDetails(name, price, image, description, section, selectedCategory) {
|
1270 |
document.getElementById('modal-name').innerText = name;
|
1271 |
document.getElementById('modal-price').innerText = `$${price}`;
|
@@ -1514,37 +1545,6 @@
|
|
1514 |
}
|
1515 |
}
|
1516 |
|
1517 |
-
function filterMenu() {
|
1518 |
-
let input = document.getElementById('searchBar').value.toLowerCase();
|
1519 |
-
let sections = document.querySelectorAll('h3');
|
1520 |
-
let items = document.querySelectorAll('.menu-card');
|
1521 |
-
let matchedSections = new Set();
|
1522 |
-
|
1523 |
-
items.forEach(item => {
|
1524 |
-
let itemName = item.querySelector('.card-title').innerText.toLowerCase();
|
1525 |
-
let itemSection = item.closest('.row').previousElementSibling.innerText.toLowerCase();
|
1526 |
-
|
1527 |
-
if (itemName.includes(input) || (itemSection && itemSection.includes(input))) {
|
1528 |
-
item.style.display = 'block';
|
1529 |
-
item.classList.add('visible');
|
1530 |
-
matchedSections.add(item.closest('.row'));
|
1531 |
-
} else {
|
1532 |
-
item.style.display = 'none';
|
1533 |
-
}
|
1534 |
-
});
|
1535 |
-
|
1536 |
-
sections.forEach(section => {
|
1537 |
-
let sectionRow = section.nextElementSibling;
|
1538 |
-
if (matchedSections.has(sectionRow)) {
|
1539 |
-
section.style.display = 'block';
|
1540 |
-
sectionRow.style.display = 'flex';
|
1541 |
-
} else {
|
1542 |
-
section.style.display = 'none';
|
1543 |
-
sectionRow.style.display = 'none';
|
1544 |
-
}
|
1545 |
-
});
|
1546 |
-
}
|
1547 |
-
|
1548 |
function addToCartFromModal() {
|
1549 |
const itemName = document.getElementById('modal-name').innerText;
|
1550 |
let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
|
@@ -1645,30 +1645,37 @@
|
|
1645 |
|
1646 |
function handleSoftDrinkAdd(button) {
|
1647 |
const buttonContainer = button.closest('.button-container');
|
1648 |
-
const addButton = buttonContainer.querySelector('.add-to-cart-btn');
|
1649 |
const quantitySelector = buttonContainer.querySelector('.quantity-selector');
|
|
|
1650 |
const quantityDisplay = quantitySelector.querySelector('.quantity-display');
|
1651 |
-
|
1652 |
-
|
1653 |
-
quantitySelector.style.display = 'flex';
|
1654 |
-
|
1655 |
const itemName = buttonContainer.getAttribute('data-item-name');
|
1656 |
const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
|
1657 |
const itemImage = buttonContainer.getAttribute('data-item-image');
|
1658 |
const section = buttonContainer.getAttribute('data-item-section');
|
1659 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1660 |
|
1661 |
const cartPayload = {
|
1662 |
itemName: itemName,
|
1663 |
itemPrice: itemPrice,
|
1664 |
itemImage: itemImage,
|
1665 |
section: section,
|
1666 |
-
category:
|
1667 |
addons: [],
|
1668 |
instructions: '',
|
1669 |
-
quantity:
|
1670 |
};
|
1671 |
|
|
|
|
|
1672 |
fetch('/cart/add', {
|
1673 |
method: 'POST',
|
1674 |
headers: {
|
@@ -1684,14 +1691,13 @@
|
|
1684 |
})
|
1685 |
.then(data => {
|
1686 |
if (data.success) {
|
1687 |
-
alert(
|
1688 |
updateCartUI(data.cart);
|
1689 |
-
quantityDisplay.innerText = 1;
|
1690 |
} else {
|
1691 |
console.error('Failed to add item to cart:', data.error);
|
1692 |
alert(data.error || 'Failed to add item to cart.');
|
1693 |
-
|
1694 |
-
|
1695 |
}
|
1696 |
})
|
1697 |
.catch(err => {
|
@@ -1699,7 +1705,9 @@
|
|
1699 |
alert('An error occurred while adding the item to the cart: ' + err.message);
|
1700 |
const cart = addToCartLocalStorage(cartPayload);
|
1701 |
updateCartUI(cart);
|
1702 |
-
|
|
|
|
|
1703 |
});
|
1704 |
}
|
1705 |
|
@@ -1708,30 +1716,27 @@
|
|
1708 |
const quantityDisplay = buttonContainer.querySelector('.quantity-display');
|
1709 |
const quantityToAddSelect = buttonContainer.querySelector('.quantity-to-add');
|
1710 |
const quantityToAdd = parseInt(quantityToAddSelect.value);
|
1711 |
-
let currentQuantity = parseInt(quantityDisplay.innerText);
|
1712 |
-
|
1713 |
-
currentQuantity += quantityToAdd;
|
1714 |
-
quantityDisplay.innerText = currentQuantity;
|
1715 |
-
|
1716 |
const itemName = buttonContainer.getAttribute('data-item-name');
|
1717 |
const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
|
1718 |
const itemImage = buttonContainer.getAttribute('data-item-image');
|
1719 |
const section = buttonContainer.getAttribute('data-item-section');
|
1720 |
-
const
|
|
|
|
|
|
|
|
|
1721 |
|
1722 |
const cartPayload = {
|
1723 |
itemName: itemName,
|
1724 |
itemPrice: itemPrice,
|
1725 |
itemImage: itemImage,
|
1726 |
section: section,
|
1727 |
-
category:
|
1728 |
addons: [],
|
1729 |
instructions: '',
|
1730 |
quantity: quantityToAdd
|
1731 |
};
|
1732 |
|
1733 |
-
button.disabled = true;
|
1734 |
-
|
1735 |
fetch('/cart/add', {
|
1736 |
method: 'POST',
|
1737 |
headers: {
|
@@ -1761,9 +1766,6 @@
|
|
1761 |
alert('An error occurred while adding the item to the cart: ' + err.message);
|
1762 |
const cart = addToCartLocalStorage(cartPayload);
|
1763 |
updateCartUI(cart);
|
1764 |
-
})
|
1765 |
-
.finally(() => {
|
1766 |
-
button.disabled = false;
|
1767 |
});
|
1768 |
}
|
1769 |
|
@@ -1852,9 +1854,15 @@
|
|
1852 |
console.error('Invalid cart data:', cart);
|
1853 |
return;
|
1854 |
}
|
|
|
|
|
|
|
|
|
|
|
1855 |
const cartIcon = document.getElementById('cart-icon');
|
1856 |
if (cartIcon) {
|
1857 |
-
cartIcon.innerText =
|
|
|
1858 |
}
|
1859 |
|
1860 |
const buttonContainers = document.querySelectorAll('.button-container');
|
|
|
115 |
box-shadow: none;
|
116 |
transform: scale(0.98);
|
117 |
}
|
118 |
+
.view-cart-container {
|
119 |
position: fixed;
|
120 |
bottom: 20px;
|
121 |
right: 20px;
|
122 |
z-index: 999;
|
|
|
|
|
123 |
display: flex;
|
124 |
align-items: center;
|
125 |
+
}
|
126 |
+
.view-cart-button {
|
|
|
127 |
background-color: #0FAA39;
|
128 |
+
color: #fff;
|
129 |
+
padding: 10px 20px;
|
130 |
+
border-radius: 30px;
|
131 |
+
font-size: 1rem;
|
132 |
+
font-weight: bold;
|
133 |
text-decoration: none;
|
134 |
+
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
|
135 |
+
display: flex;
|
136 |
+
align-items: center;
|
137 |
+
justify-content: center;
|
138 |
+
gap: 8px;
|
139 |
}
|
140 |
+
.view-cart-button:hover {
|
141 |
background-color: #109835;
|
142 |
+
text-decoration: none;
|
|
|
|
|
|
|
143 |
color: #fff;
|
144 |
}
|
145 |
+
.cart-icon-badge {
|
146 |
+
background-color: #fff;
|
147 |
+
color: #0FAA39;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
border-radius: 50%;
|
149 |
+
width: 24px;
|
150 |
+
height: 24px;
|
151 |
display: flex;
|
152 |
align-items: center;
|
153 |
justify-content: center;
|
154 |
+
font-size: 12px;
|
155 |
+
font-weight: bold;
|
156 |
+
margin-left: 5px;
|
157 |
}
|
158 |
.avatar-dropdown-container {
|
159 |
position: absolute;
|
|
|
656 |
height: 18px;
|
657 |
font-size: 9px;
|
658 |
}
|
659 |
+
.view-cart-button {
|
660 |
+
padding: 8px 16px;
|
661 |
+
font-size: 14px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
662 |
}
|
663 |
+
.cart-icon-badge {
|
664 |
+
width: 20px;
|
665 |
+
height: 20px;
|
666 |
font-size: 10px;
|
667 |
}
|
668 |
}
|
|
|
789 |
{% endif %}
|
790 |
</div>
|
791 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
792 |
<div class="view-cart-container">
|
793 |
<a href="{{ url_for('cart.cart') }}" class="view-cart-button">
|
794 |
+
<i class="bi bi-cart"></i>
|
795 |
View Cart
|
796 |
+
<span class="cart-icon-badge" id="cart-icon">0</span>
|
797 |
</a>
|
798 |
</div>
|
799 |
|
|
|
851 |
</div>
|
852 |
|
853 |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
|
|
854 |
<script>
|
855 |
+
// Dynamically populate menuItems from ordered_menu
|
856 |
const menuItems = [
|
857 |
+
{% for section, items in ordered_menu.items() %}
|
858 |
+
{% for item in items %}
|
859 |
+
"{{ item.Name }}",
|
860 |
+
{% endfor %}
|
861 |
+
{% endfor %}
|
862 |
+
];
|
863 |
+
|
864 |
+
const ingredientsList = [
|
865 |
+
"Basmati Rice", "Bell Pepper", "Biryani Masala", "Butter", "Capsicum", "Cauliflower",
|
866 |
+
"Chickpea Flour (Besan)", "Chickpea Flour (for batter)", "Chickpeas (Channa)", "Chili Powder",
|
867 |
+
"Chili Sauce", "Coconut Milk", "Coriander Powder", "Cornflour", "Cream", "Cumin Powder",
|
868 |
+
"Cumin Seeds", "Curd (Yogurt)", "Curry Leaves", "Fish (e.g., King Fish or Salmon)",
|
869 |
+
"Fresh Coriander Leaves", "Garam Masala", "Garlic", "Ghee (Clarified Butter)", "Ginger",
|
870 |
+
"Ginger-Garlic Paste", "Goat Meat (Mutton)", "Green Chilies", "Honey",
|
871 |
+
"Kasuri Methi (dried fenugreek leaves)", "Lemon Juice", "Mango Puree", "Mint Leaves",
|
872 |
+
"Mixed Vegetables (Carrot, Peas, Potato, Cauliflower)", "Mixed Vegetables (Carrot, Peas, Potato)",
|
873 |
+
"Mustard Seeds", "Mutton (Goat Meat)", "Oil", "Oil (for frying)", "Onion",
|
874 |
+
"Paneer (Indian Cottage Cheese)", "Peas", "Potatoes", "Prawns", "Red Chili Powder",
|
875 |
+
"Rice Flour", "Saffron", "Salt", "Soy Sauce", "Spring Onion", "Tamarind (for sourness)",
|
876 |
+
"Tomato Ketchup", "Tomatoes", "Turmeric Powder", "Vinegar", "Water", "Wheat Flour (for dough)",
|
877 |
+
"Whole Wheat Flour", "Yogurt (Curd)"
|
878 |
];
|
879 |
|
880 |
const menuItemDetails = {
|
|
|
1073 |
entries.forEach(entry => {
|
1074 |
if (entry.isIntersecting) {
|
1075 |
const img = entry.target;
|
1076 |
+
const src = img.getAttribute('data-src');
|
1077 |
+
if (src && img.src !== src) {
|
1078 |
+
img.src = src;
|
1079 |
+
}
|
1080 |
img.onload = () => img.classList.add('loaded');
|
1081 |
+
img.onerror = () => {
|
1082 |
+
img.src = '/static/placeholder.jpg';
|
1083 |
+
img.classList.add('loaded');
|
1084 |
+
};
|
1085 |
observer.unobserve(img);
|
1086 |
}
|
1087 |
});
|
1088 |
}, {
|
1089 |
root: null,
|
1090 |
+
rootMargin: '200px',
|
1091 |
+
threshold: 0.01
|
1092 |
});
|
1093 |
|
1094 |
menuCards.forEach(card => cardObserver.observe(card));
|
|
|
1122 |
});
|
1123 |
});
|
1124 |
|
|
|
1125 |
const searchBar = document.getElementById('searchBar');
|
1126 |
const suggestionsContainer = document.getElementById('autocompleteSuggestions');
|
1127 |
|
|
|
1132 |
|
1133 |
if (input) {
|
1134 |
const filteredItems = menuItems.filter(item =>
|
1135 |
+
item.toLowerCase().includes(input)
|
1136 |
);
|
1137 |
if (filteredItems.length > 0) {
|
1138 |
filteredItems.forEach(item => {
|
|
|
1149 |
suggestionsContainer.style.display = 'block';
|
1150 |
}
|
1151 |
}
|
1152 |
+
filterMenu();
|
1153 |
});
|
1154 |
|
1155 |
document.addEventListener('click', function (event) {
|
|
|
1158 |
}
|
1159 |
});
|
1160 |
|
1161 |
+
const descriptionTextarea = document.getElementById('custom-dish-description');
|
1162 |
+
const descriptionSuggestions = document.getElementById('descriptionSuggestions');
|
1163 |
+
|
1164 |
+
if (descriptionTextarea && descriptionSuggestions) {
|
1165 |
+
let usedIngredients = new Set();
|
1166 |
+
|
1167 |
+
function updateUsedIngredients() {
|
1168 |
+
const inputText = descriptionTextarea.value.trim();
|
1169 |
+
usedIngredients.clear();
|
1170 |
+
if (inputText) {
|
1171 |
+
const words = inputText.split(/,\s*/).map(word => word.trim());
|
1172 |
+
words.forEach(word => {
|
1173 |
+
if (word && ingredientsList.includes(word)) {
|
1174 |
+
usedIngredients.add(word);
|
1175 |
+
}
|
1176 |
+
});
|
1177 |
+
}
|
1178 |
+
}
|
1179 |
+
|
1180 |
+
descriptionTextarea.addEventListener('input', function () {
|
1181 |
+
const inputText = this.value.trim();
|
1182 |
+
const words = inputText.split(/,\s*/);
|
1183 |
+
const lastWord = words[words.length - 1].trim().toLowerCase();
|
1184 |
+
descriptionSuggestions.innerHTML = '';
|
1185 |
+
descriptionSuggestions.style.display = 'none';
|
1186 |
+
|
1187 |
+
updateUsedIngredients();
|
1188 |
+
|
1189 |
+
if (lastWord) {
|
1190 |
+
const filteredIngredients = ingredientsList.filter(ingredient =>
|
1191 |
+
ingredient.toLowerCase().includes(lastWord) && !usedIngredients.has(ingredient)
|
1192 |
+
);
|
1193 |
+
if (filteredIngredients.length > 0) {
|
1194 |
+
filteredIngredients.forEach(ingredient => {
|
1195 |
+
const suggestionDiv = document.createElement('div');
|
1196 |
+
suggestionDiv.classList.add('suggestion-item');
|
1197 |
+
suggestionDiv.innerText = ingredient;
|
1198 |
+
suggestionDiv.addEventListener('click', function () {
|
1199 |
+
const currentValue = descriptionTextarea.value;
|
1200 |
+
const lastCommaIndex = currentValue.lastIndexOf(',');
|
1201 |
+
const baseText = lastCommaIndex !== -1 ? currentValue.substring(0, lastCommaIndex + 1) : '';
|
1202 |
+
descriptionTextarea.value = baseText + (baseText ? ' ' : '') + ingredient + ', ';
|
1203 |
+
descriptionSuggestions.style.display = 'none';
|
1204 |
+
descriptionTextarea.focus();
|
1205 |
+
updateUsedIngredients();
|
1206 |
+
});
|
1207 |
+
descriptionSuggestions.appendChild(suggestionDiv);
|
1208 |
+
});
|
1209 |
+
descriptionSuggestions.style.display = 'block';
|
1210 |
+
}
|
1211 |
+
}
|
1212 |
+
});
|
1213 |
+
|
1214 |
+
document.addEventListener('click', function (event) {
|
1215 |
+
if (!descriptionTextarea.contains(event.target) && !descriptionSuggestions.contains(event.target)) {
|
1216 |
+
descriptionSuggestions.style.display = 'none';
|
1217 |
+
}
|
1218 |
+
});
|
1219 |
+
}
|
1220 |
+
|
1221 |
+
fetch('/cart/get')
|
1222 |
+
.then(response => {
|
1223 |
+
if (!response.ok) {
|
1224 |
+
throw new Error(`HTTP error! Status: ${response.status}`);
|
1225 |
+
}
|
1226 |
+
return response.json();
|
1227 |
+
})
|
1228 |
+
.then(data => {
|
1229 |
+
if (data.success) {
|
1230 |
+
updateCartUI(data.cart);
|
1231 |
+
} else {
|
1232 |
+
console.error('Failed to fetch cart:', data.error);
|
1233 |
+
const cart = getCartLocalStorage();
|
1234 |
+
updateCartUI(cart);
|
1235 |
+
}
|
1236 |
+
})
|
1237 |
+
.catch(err => {
|
1238 |
+
console.error('Error fetching cart:', err);
|
1239 |
+
const cart = getCartLocalStorage();
|
1240 |
+
updateCartUI(cart);
|
1241 |
+
});
|
1242 |
+
|
1243 |
+
const preloadedImages = document.querySelectorAll('link[rel="preload"]');
|
1244 |
+
preloadedImages.forEach(link => {
|
1245 |
+
const img = new Image();
|
1246 |
+
img.src = link.href;
|
1247 |
+
});
|
1248 |
});
|
1249 |
|
1250 |
function debounce(func, wait) {
|
|
|
1255 |
};
|
1256 |
}
|
1257 |
|
1258 |
+
function filterMenu() {
|
1259 |
+
const input = document.getElementById('searchBar').value.trim().toLowerCase();
|
1260 |
+
const sections = document.querySelectorAll('h3');
|
1261 |
+
const items = document.querySelectorAll('.menu-card');
|
1262 |
+
let matchedSections = new Set();
|
1263 |
+
|
1264 |
+
items.forEach(item => {
|
1265 |
+
const itemName = item.querySelector('.card-title').innerText.toLowerCase();
|
1266 |
+
const itemSection = item.closest('.row').previousElementSibling.innerText.toLowerCase();
|
1267 |
+
|
1268 |
+
if (itemName.includes(input) || (itemSection && itemSection.includes(input))) {
|
1269 |
+
item.style.display = 'block';
|
1270 |
+
item.classList.add('visible');
|
1271 |
+
matchedSections.add(item.closest('.row'));
|
1272 |
+
} else {
|
1273 |
+
item.style.display = 'none';
|
1274 |
+
}
|
1275 |
+
});
|
1276 |
+
|
1277 |
+
sections.forEach(section => {
|
1278 |
+
const sectionRow = section.nextElementSibling;
|
1279 |
+
if (matchedSections.has(sectionRow)) {
|
1280 |
+
section.style.display = 'block';
|
1281 |
+
sectionRow.style.display = 'flex';
|
1282 |
+
} else {
|
1283 |
+
section.style.display = 'none';
|
1284 |
+
sectionRow.style.display = 'none';
|
1285 |
+
}
|
1286 |
+
});
|
1287 |
+
|
1288 |
+
if (!input) {
|
1289 |
+
sections.forEach(section => {
|
1290 |
+
section.style.display = 'block';
|
1291 |
+
section.nextElementSibling.style.display = 'flex';
|
1292 |
+
});
|
1293 |
+
items.forEach(item => {
|
1294 |
+
item.style.display = 'block';
|
1295 |
+
item.classList.add('visible');
|
1296 |
+
});
|
1297 |
+
}
|
1298 |
+
}
|
1299 |
+
|
1300 |
function showItemDetails(name, price, image, description, section, selectedCategory) {
|
1301 |
document.getElementById('modal-name').innerText = name;
|
1302 |
document.getElementById('modal-price').innerText = `$${price}`;
|
|
|
1545 |
}
|
1546 |
}
|
1547 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1548 |
function addToCartFromModal() {
|
1549 |
const itemName = document.getElementById('modal-name').innerText;
|
1550 |
let itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
|
|
|
1645 |
|
1646 |
function handleSoftDrinkAdd(button) {
|
1647 |
const buttonContainer = button.closest('.button-container');
|
|
|
1648 |
const quantitySelector = buttonContainer.querySelector('.quantity-selector');
|
1649 |
+
const addButton = buttonContainer.querySelector('.add-to-cart-btn');
|
1650 |
const quantityDisplay = quantitySelector.querySelector('.quantity-display');
|
1651 |
+
const quantityToAddSelect = quantitySelector.querySelector('.quantity-to-add');
|
1652 |
+
const quantityToAdd = parseInt(quantityToAddSelect.value);
|
|
|
|
|
1653 |
const itemName = buttonContainer.getAttribute('data-item-name');
|
1654 |
const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
|
1655 |
const itemImage = buttonContainer.getAttribute('data-item-image');
|
1656 |
const section = buttonContainer.getAttribute('data-item-section');
|
1657 |
+
const selectedCategory = buttonContainer.getAttribute('data-item-category');
|
1658 |
+
|
1659 |
+
addButton.style.display = 'none';
|
1660 |
+
quantitySelector.style.display = 'flex';
|
1661 |
+
|
1662 |
+
let currentQuantity = parseInt(quantityDisplay.innerText) || 0;
|
1663 |
+
currentQuantity += quantityToAdd;
|
1664 |
+
quantityDisplay.innerText = currentQuantity;
|
1665 |
|
1666 |
const cartPayload = {
|
1667 |
itemName: itemName,
|
1668 |
itemPrice: itemPrice,
|
1669 |
itemImage: itemImage,
|
1670 |
section: section,
|
1671 |
+
category: selectedCategory,
|
1672 |
addons: [],
|
1673 |
instructions: '',
|
1674 |
+
quantity: quantityToAdd
|
1675 |
};
|
1676 |
|
1677 |
+
button.disabled = true;
|
1678 |
+
|
1679 |
fetch('/cart/add', {
|
1680 |
method: 'POST',
|
1681 |
headers: {
|
|
|
1691 |
})
|
1692 |
.then(data => {
|
1693 |
if (data.success) {
|
1694 |
+
alert(`Added ${quantityToAdd} item(s) to cart successfully!`);
|
1695 |
updateCartUI(data.cart);
|
|
|
1696 |
} else {
|
1697 |
console.error('Failed to add item to cart:', data.error);
|
1698 |
alert(data.error || 'Failed to add item to cart.');
|
1699 |
+
currentQuantity -= quantityToAdd;
|
1700 |
+
quantityDisplay.innerText = currentQuantity;
|
1701 |
}
|
1702 |
})
|
1703 |
.catch(err => {
|
|
|
1705 |
alert('An error occurred while adding the item to the cart: ' + err.message);
|
1706 |
const cart = addToCartLocalStorage(cartPayload);
|
1707 |
updateCartUI(cart);
|
1708 |
+
})
|
1709 |
+
.finally(() => {
|
1710 |
+
button.disabled = false;
|
1711 |
});
|
1712 |
}
|
1713 |
|
|
|
1716 |
const quantityDisplay = buttonContainer.querySelector('.quantity-display');
|
1717 |
const quantityToAddSelect = buttonContainer.querySelector('.quantity-to-add');
|
1718 |
const quantityToAdd = parseInt(quantityToAddSelect.value);
|
|
|
|
|
|
|
|
|
|
|
1719 |
const itemName = buttonContainer.getAttribute('data-item-name');
|
1720 |
const itemPrice = parseFloat(buttonContainer.getAttribute('data-item-price'));
|
1721 |
const itemImage = buttonContainer.getAttribute('data-item-image');
|
1722 |
const section = buttonContainer.getAttribute('data-item-section');
|
1723 |
+
const selectedCategory = buttonContainer.getAttribute('data-item-category');
|
1724 |
+
|
1725 |
+
let currentQuantity = parseInt(quantityDisplay.innerText) || 0;
|
1726 |
+
currentQuantity += quantityToAdd;
|
1727 |
+
quantityDisplay.innerText = currentQuantity;
|
1728 |
|
1729 |
const cartPayload = {
|
1730 |
itemName: itemName,
|
1731 |
itemPrice: itemPrice,
|
1732 |
itemImage: itemImage,
|
1733 |
section: section,
|
1734 |
+
category: selectedCategory,
|
1735 |
addons: [],
|
1736 |
instructions: '',
|
1737 |
quantity: quantityToAdd
|
1738 |
};
|
1739 |
|
|
|
|
|
1740 |
fetch('/cart/add', {
|
1741 |
method: 'POST',
|
1742 |
headers: {
|
|
|
1766 |
alert('An error occurred while adding the item to the cart: ' + err.message);
|
1767 |
const cart = addToCartLocalStorage(cartPayload);
|
1768 |
updateCartUI(cart);
|
|
|
|
|
|
|
1769 |
});
|
1770 |
}
|
1771 |
|
|
|
1854 |
console.error('Invalid cart data:', cart);
|
1855 |
return;
|
1856 |
}
|
1857 |
+
|
1858 |
+
// Calculate total items in cart
|
1859 |
+
const totalItems = cart.reduce((total, item) => total + item.quantity, 0);
|
1860 |
+
|
1861 |
+
// Update cart icon badge
|
1862 |
const cartIcon = document.getElementById('cart-icon');
|
1863 |
if (cartIcon) {
|
1864 |
+
cartIcon.innerText = totalItems;
|
1865 |
+
cartIcon.style.display = totalItems > 0 ? 'flex' : 'none';
|
1866 |
}
|
1867 |
|
1868 |
const buttonContainers = document.querySelectorAll('.button-container');
|