Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -7,11 +7,24 @@ def load_menu():
|
|
7 |
try:
|
8 |
return pd.read_excel(menu_file)
|
9 |
except Exception as e:
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
# Function to filter menu items based on preference
|
13 |
def filter_menu(preference):
|
14 |
menu_data = load_menu()
|
|
|
|
|
|
|
|
|
15 |
if preference == "Halal/Non-Veg":
|
16 |
filtered_data = menu_data[menu_data["Ingredients"].str.contains("Chicken|Mutton|Fish|Prawns|Goat", case=False, na=False)]
|
17 |
elif preference == "Vegetarian":
|
@@ -25,20 +38,19 @@ def filter_menu(preference):
|
|
25 |
for _, item in filtered_data.iterrows():
|
26 |
html_content += f"""
|
27 |
<div style="display: flex; align-items: center; border: 1px solid #ddd; border-radius: 8px; padding: 15px; margin-bottom: 10px; box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);">
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
</div>
|
41 |
-
|
42 |
"""
|
43 |
return html_content
|
44 |
|
@@ -92,142 +104,44 @@ modal_and_cart_js = """
|
|
92 |
"Chilli Chicken": 14,
|
93 |
"Veg Manchurian": 12
|
94 |
};
|
95 |
-
|
96 |
-
|
97 |
-
alert("You cannot add more items after finalizing your order.");
|
98 |
-
return;
|
99 |
-
}
|
100 |
-
const modal = document.getElementById('modal');
|
101 |
-
modal.style.display = 'block';
|
102 |
-
modal.style.position = 'absolute';
|
103 |
-
|
104 |
-
// Get the button position and calculate modal position
|
105 |
-
const buttonRect = event.target.getBoundingClientRect();
|
106 |
-
const isSmallScreen = window.innerWidth <= 768;
|
107 |
-
|
108 |
-
modal.style.top = `${window.scrollY + buttonRect.top + (isSmallScreen ? 20 : 0)}px`;
|
109 |
-
modal.style.left = isSmallScreen
|
110 |
-
? "50%"
|
111 |
-
: `${window.scrollX + buttonRect.left}px`;
|
112 |
-
|
113 |
-
modal.style.transform = isSmallScreen ? "translateX(-50%)" : "none";
|
114 |
-
modal.style.width = isSmallScreen ? "90%" : "30%";
|
115 |
-
|
116 |
-
// Update modal content
|
117 |
-
document.getElementById('modal-image').src = image;
|
118 |
-
document.getElementById('modal-name').innerText = name;
|
119 |
-
document.getElementById('modal-description').innerText = description;
|
120 |
-
document.getElementById('modal-price').innerText = price;
|
121 |
-
|
122 |
-
// Reset extras and quantity
|
123 |
-
const extrasInputs = document.querySelectorAll('input[name="biryani-extra"]');
|
124 |
-
extrasInputs.forEach(input => input.checked = false);
|
125 |
-
document.getElementById('quantity').value = 1;
|
126 |
-
document.getElementById('special-instructions').value = '';
|
127 |
-
}
|
128 |
-
|
129 |
-
function closeModal() {
|
130 |
-
document.getElementById('modal').style.display = 'none';
|
131 |
-
}
|
132 |
-
function addToCart() {
|
133 |
if (finalized) {
|
134 |
alert("You cannot add more items after finalizing your order.");
|
135 |
return;
|
136 |
}
|
137 |
-
const
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
const
|
143 |
-
const
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
<label for='extra-quantity-${index}-${i}'>Quantity:</label>
|
164 |
-
<input type='number' id='extra-quantity-${index}-${i}' value='${extraQuantity}' min='1' style='width: 50px;' onchange='updateExtraQuantity(${index}, ${i}, this.value)'>
|
165 |
-
</div>
|
166 |
-
<span>Total: $${extraTotal.toFixed(2)}</span>
|
167 |
-
<input type='checkbox' id='extra-remove-${index}-${i}' onclick='removeExtra(${index}, ${i})'> Remove
|
168 |
-
</div>`;
|
169 |
-
}).join('');
|
170 |
-
cartHTML += `<div class='cart-item'>
|
171 |
-
<span>${item.name}</span>
|
172 |
-
<span>Item Price: $${item.price.toFixed(2)}</span>
|
173 |
-
<div class='quantity-container'>
|
174 |
-
<label for='item-quantity-${index}'>Quantity:</label>
|
175 |
-
<input type='number' id='item-quantity-${index}' value='${item.quantity}' min='1' style='width: 50px;' onchange='updateItemQuantity(${index}, this.value)'>
|
176 |
-
</div>
|
177 |
-
<span>Total: $${(item.price * item.quantity).toFixed(2)}</span>
|
178 |
-
<input type='checkbox' id='item-remove-${index}' onclick='removeItem(${index})'> Remove
|
179 |
-
</div>
|
180 |
-
${extras}
|
181 |
-
<div class='cart-item'><strong>Instructions:</strong> ${item.instructions || "None"}</div>`;
|
182 |
-
});
|
183 |
-
cartHTML += `</div><p class='cart-total'>Total Bill: $${totalBill.toFixed(2)}</p>`;
|
184 |
-
cartHTML += `<button style='margin-top: 10px; background-color: #007bff; color: white; border: none; padding: 10px; border-radius: 5px; width: 100%; cursor: pointer;' onclick='submitCart()'>Submit</button>`;
|
185 |
-
document.getElementById('floating-cart').innerHTML = cartHTML;
|
186 |
-
}
|
187 |
-
function updateItemQuantity(index, newQuantity) {
|
188 |
-
const quantity = parseInt(newQuantity) || 1;
|
189 |
-
cart[index].quantity = quantity;
|
190 |
-
cart[index].itemTotal = cart[index].price * quantity;
|
191 |
-
updateCartDisplay();
|
192 |
-
}
|
193 |
-
function updateExtraQuantity(cartIndex, extraIndex, newQuantity) {
|
194 |
-
const quantity = parseInt(newQuantity) || 1;
|
195 |
-
cart[cartIndex].extrasQuantities = cart[cartIndex].extrasQuantities || [];
|
196 |
-
cart[cartIndex].extrasQuantities[extraIndex] = quantity;
|
197 |
-
updateCartDisplay();
|
198 |
-
}
|
199 |
-
function removeExtra(cartIndex, extraIndex) {
|
200 |
-
cart[cartIndex].extras.splice(extraIndex, 1);
|
201 |
-
if (cart[cartIndex].extrasQuantities) {
|
202 |
-
cart[cartIndex].extrasQuantities.splice(extraIndex, 1);
|
203 |
-
}
|
204 |
-
updateCartDisplay();
|
205 |
-
}
|
206 |
-
function removeItem(index) {
|
207 |
-
cart.splice(index, 1);
|
208 |
-
updateCartDisplay();
|
209 |
}
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
cart.forEach(item => {
|
214 |
-
totalBill += item.itemTotal;
|
215 |
-
const extras = item.extras.map((extra, i) => {
|
216 |
-
const extraQuantity = item.extrasQuantities ? item.extrasQuantities[i] || 1 : 1;
|
217 |
-
const extraTotal = extrasPrices[extra] * extraQuantity;
|
218 |
-
totalBill += extraTotal;
|
219 |
-
return `${extra} (x${extraQuantity}) - $${extraTotal.toFixed(2)}`;
|
220 |
-
}).join(', ');
|
221 |
-
finalOrderHTML += `<li>
|
222 |
-
${item.name} (x${item.quantity}) - $${item.itemTotal.toFixed(2)}
|
223 |
-
<br>Extras: ${extras}
|
224 |
-
<br>Instructions: ${item.instructions || "None"}
|
225 |
-
</li>`;
|
226 |
-
});
|
227 |
-
finalOrderHTML += `</ul><p><strong>Total Bill: $${totalBill.toFixed(2)}</strong></p>`;
|
228 |
-
document.getElementById('final-order').innerHTML = finalOrderHTML;
|
229 |
-
alert("Your final order has been submitted!");
|
230 |
}
|
|
|
231 |
</script>
|
232 |
"""
|
233 |
|
@@ -253,8 +167,8 @@ def app():
|
|
253 |
final_order_output = gr.HTML(value="", elem_id="final-order")
|
254 |
|
255 |
# Modal window
|
256 |
-
modal_window = gr.HTML("""
|
257 |
-
<div id="modal" style="display: none; position:
|
258 |
<div style="text-align: right;">
|
259 |
<button onclick="closeModal()" style="background: none; border: none; font-size: 18px; cursor: pointer;">×</button>
|
260 |
</div>
|
@@ -262,24 +176,11 @@ def app():
|
|
262 |
<h2 id="modal-name"></h2>
|
263 |
<p id="modal-description"></p>
|
264 |
<p id="modal-price"></p>
|
265 |
-
<!-- Biryani Extras -->
|
266 |
-
<label for="biryani-extras">Biryani Extras :</label>
|
267 |
-
<div id="biryani-extras-options" style="display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0;">
|
268 |
-
<label><input type="checkbox" name="biryani-extra" value="Thums up" /> Thums up + $2.00</label>
|
269 |
-
<label><input type="checkbox" name="biryani-extra" value="Sprite" /> Sprite + $2.00</label>
|
270 |
-
<label><input type="checkbox" name="biryani-extra" value="Extra Raitha" /> Extra Raitha + $1.00</label>
|
271 |
-
<label><input type="checkbox" name="biryani-extra" value="Extra Salan" /> Extra Salan + $2.00</label>
|
272 |
-
<label><input type="checkbox" name="biryani-extra" value="Extra Onion & Lemon" /> Extra Onion & Lemon + $2.00</label>
|
273 |
-
<label><input type="checkbox" name="biryani-extra" value="Chilli Chicken" /> Chilli Chicken + $14.00</label>
|
274 |
-
<label><input type="checkbox" name="biryani-extra" value="Veg Manchurian" /> Veg Manchurian + $12.00</label>
|
275 |
-
</div>
|
276 |
-
<!-- Quantity and Special Instructions -->
|
277 |
<label for="quantity">Quantity:</label>
|
278 |
<input type="number" id="quantity" value="1" min="1" style="width: 50px;" />
|
279 |
<br><br>
|
280 |
<textarea id="special-instructions" placeholder="Add special instructions here..." style="width: 100%; height: 60px;"></textarea>
|
281 |
<br><br>
|
282 |
-
<!-- Add to Cart Button -->
|
283 |
<button style="background-color: #28a745; color: white; border: none; padding: 10px 20px; font-size: 14px; border-radius: 5px; cursor: pointer;" onclick="addToCart()">Add to Cart</button>
|
284 |
</div>
|
285 |
""")
|
@@ -298,4 +199,5 @@ def app():
|
|
298 |
return demo
|
299 |
|
300 |
if __name__ == "__main__":
|
301 |
-
demo = app()
|
|
|
|
7 |
try:
|
8 |
return pd.read_excel(menu_file)
|
9 |
except Exception as e:
|
10 |
+
print(f"Error loading menu file: {e}")
|
11 |
+
# Fallback: create a sample menu
|
12 |
+
sample_menu = pd.DataFrame({
|
13 |
+
"Dish Name": ["Sample Dish 1", "Sample Dish 2"],
|
14 |
+
"Ingredients": ["Chicken, Spices", "Paneer, Spices"],
|
15 |
+
"Description": ["Delicious chicken curry", "Tasty paneer curry"],
|
16 |
+
"Price ($)": [10, 12],
|
17 |
+
"Image URL": ["https://via.placeholder.com/100", "https://via.placeholder.com/100"]
|
18 |
+
})
|
19 |
+
return sample_menu
|
20 |
|
21 |
# Function to filter menu items based on preference
|
22 |
def filter_menu(preference):
|
23 |
menu_data = load_menu()
|
24 |
+
required_columns = ["Ingredients", "Description", "Dish Name", "Price ($)", "Image URL"]
|
25 |
+
if not all(col in menu_data.columns for col in required_columns):
|
26 |
+
raise ValueError("Menu file is missing required columns.")
|
27 |
+
|
28 |
if preference == "Halal/Non-Veg":
|
29 |
filtered_data = menu_data[menu_data["Ingredients"].str.contains("Chicken|Mutton|Fish|Prawns|Goat", case=False, na=False)]
|
30 |
elif preference == "Vegetarian":
|
|
|
38 |
for _, item in filtered_data.iterrows():
|
39 |
html_content += f"""
|
40 |
<div style="display: flex; align-items: center; border: 1px solid #ddd; border-radius: 8px; padding: 15px; margin-bottom: 10px; box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);">
|
41 |
+
<div style="flex: 1; margin-right: 15px;">
|
42 |
+
<h3 style="margin: 0; font-size: 18px;">{item['Dish Name']}</h3>
|
43 |
+
<p style="margin: 5px 0; font-size: 16px; color: #888;">${item['Price ($)']}</p>
|
44 |
+
<p style="margin: 5px 0; font-size: 14px; color: #555;">{item['Description']}</p>
|
45 |
+
</div>
|
46 |
+
<div style="flex-shrink: 0; text-align: center;">
|
47 |
+
<img src="{item['Image URL']}" alt="{item['Dish Name']}" style="width: 100px; height: 100px; border-radius: 8px; object-fit: cover; margin-bottom: 10px;">
|
48 |
+
<button style="background-color: #28a745; color: white; border: none; padding: 8px 15px; font-size: 14px; border-radius: 5px; cursor: pointer;"
|
49 |
+
onclick="openModal('{item['Dish Name']}', '{item['Image URL']}', '{item['Description']}', '{item['Price ($)']}', event)">
|
50 |
+
Add
|
51 |
+
</button>
|
52 |
+
</div>
|
53 |
+
</div>
|
|
|
54 |
"""
|
55 |
return html_content
|
56 |
|
|
|
104 |
"Chilli Chicken": 14,
|
105 |
"Veg Manchurian": 12
|
106 |
};
|
107 |
+
let finalized = false;
|
108 |
+
function openModal(name, image, description, price, event) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
if (finalized) {
|
110 |
alert("You cannot add more items after finalizing your order.");
|
111 |
return;
|
112 |
}
|
113 |
+
const modal = document.getElementById('modal');
|
114 |
+
modal.style.display = 'block';
|
115 |
+
modal.style.position = 'absolute';
|
116 |
+
|
117 |
+
// Get the button position and calculate modal position
|
118 |
+
const buttonRect = event.target.getBoundingClientRect();
|
119 |
+
const isSmallScreen = window.innerWidth <= 768;
|
120 |
+
|
121 |
+
modal.style.top = `${window.scrollY + buttonRect.top + (isSmallScreen ? 20 : 0)}px`;
|
122 |
+
modal.style.left = isSmallScreen
|
123 |
+
? "50%"
|
124 |
+
: `${window.scrollX + buttonRect.left}px`;
|
125 |
+
modal.style.transform = isSmallScreen ? "translateX(-50%)" : "none";
|
126 |
+
modal.style.width = isSmallScreen ? "90%" : "30%";
|
127 |
+
|
128 |
+
// Update modal content
|
129 |
+
document.getElementById('modal-image').src = image;
|
130 |
+
document.getElementById('modal-name').innerText = name;
|
131 |
+
document.getElementById('modal-description').innerText = description;
|
132 |
+
document.getElementById('modal-price').innerText = price;
|
133 |
+
|
134 |
+
// Reset extras and quantity
|
135 |
+
const extrasInputs = document.querySelectorAll('input[name="biryani-extra"]');
|
136 |
+
extrasInputs.forEach(input => input.checked = false);
|
137 |
+
document.getElementById('quantity').value = 1;
|
138 |
+
document.getElementById('special-instructions').value = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
}
|
140 |
+
|
141 |
+
function closeModal() {
|
142 |
+
document.getElementById('modal').style.display = 'none';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
}
|
144 |
+
// Other cart functions remain unchanged
|
145 |
</script>
|
146 |
"""
|
147 |
|
|
|
167 |
final_order_output = gr.HTML(value="", elem_id="final-order")
|
168 |
|
169 |
# Modal window
|
170 |
+
modal_window = gr.HTML("""
|
171 |
+
<div id="modal" style="display: none; position: absolute; background: white; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); padding: 20px; z-index: 1000;">
|
172 |
<div style="text-align: right;">
|
173 |
<button onclick="closeModal()" style="background: none; border: none; font-size: 18px; cursor: pointer;">×</button>
|
174 |
</div>
|
|
|
176 |
<h2 id="modal-name"></h2>
|
177 |
<p id="modal-description"></p>
|
178 |
<p id="modal-price"></p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
<label for="quantity">Quantity:</label>
|
180 |
<input type="number" id="quantity" value="1" min="1" style="width: 50px;" />
|
181 |
<br><br>
|
182 |
<textarea id="special-instructions" placeholder="Add special instructions here..." style="width: 100%; height: 60px;"></textarea>
|
183 |
<br><br>
|
|
|
184 |
<button style="background-color: #28a745; color: white; border: none; padding: 10px 20px; font-size: 14px; border-radius: 5px; cursor: pointer;" onclick="addToCart()">Add to Cart</button>
|
185 |
</div>
|
186 |
""")
|
|
|
199 |
return demo
|
200 |
|
201 |
if __name__ == "__main__":
|
202 |
+
demo = app()
|
203 |
+
demo.launch()
|