geethareddy commited on
Commit
ea9c5f2
·
verified ·
1 Parent(s): 6198433

Update templates/menu.html

Browse files
Files changed (1) hide show
  1. templates/menu.html +27 -399
templates/menu.html CHANGED
@@ -1,399 +1,27 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Menu</title>
7
- <!-- Bootstrap CSS -->
8
- <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
- <style>
10
- body {
11
- font-family: Arial, sans-serif;
12
- background-color: #f8f9fa;
13
- margin: 0;
14
- padding: 0;
15
- }
16
-
17
- .container {
18
- max-width: 900px;
19
- }
20
-
21
- .menu-card {
22
- max-width: 350px;
23
- border-radius: 15px;
24
- overflow: hidden;
25
- background-color: #fff;
26
- margin: auto;
27
- }
28
-
29
- .menu-image {
30
- height: 200px;
31
- width: 100%;
32
- object-fit: cover;
33
- border-radius: 15px 15px 0 0;
34
- }
35
-
36
- .card-title {
37
- font-size: 1.2rem;
38
- font-weight: bold;
39
- }
40
-
41
- .card-text {
42
- font-size: 1rem;
43
- color: #6c757d;
44
- }
45
-
46
- .btn-primary {
47
- font-size: 0.9rem;
48
- border-radius: 20px;
49
- width: 100px;
50
- }
51
-
52
- .filter-container {
53
- margin-bottom: 15px;
54
- }
55
-
56
- .addons-container {
57
- max-height: 150px;
58
- overflow-y: auto;
59
- border: 1px solid #ddd;
60
- padding: 10px;
61
- background-color: #f8f9fa;
62
- border-radius: 5px;
63
- }
64
-
65
- .addons-container::-webkit-scrollbar {
66
- width: 6px;
67
- }
68
-
69
- .addons-container::-webkit-scrollbar-thumb {
70
- background-color: #aaa;
71
- border-radius: 3px;
72
- }
73
-
74
- .addons-container::-webkit-scrollbar-track {
75
- background-color: #f1f1f1;
76
- }
77
-
78
- .view-cart-container {
79
- position: fixed;
80
- bottom: 20px;
81
- right: 20px;
82
- z-index: 999;
83
- }
84
-
85
- .view-cart-button {
86
- background-color: #007bff;
87
- color: #fff;
88
- padding: 10px 20px;
89
- border-radius: 50px;
90
- font-size: 1rem;
91
- font-weight: bold;
92
- text-decoration: none;
93
- box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
94
- display: flex;
95
- align-items: center;
96
- justify-content: center;
97
- }
98
-
99
- .view-cart-button:hover {
100
- background-color: #0056b3;
101
- text-decoration: none;
102
- }
103
-
104
- /* Toast container for messages */
105
- .toast-container {
106
- position: fixed;
107
- top: 10px;
108
- right: 10px;
109
- z-index: 1055; /* Ensure it appears above other elements */
110
- width: auto;
111
- max-width: 300px;
112
- }
113
-
114
- /* Toast box */
115
- .toast {
116
- background-color: #28a745; /* Success green background */
117
- color: #fff; /* White text */
118
- padding: 10px 20px;
119
- border-radius: 8px;
120
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
121
- font-size: 0.9rem;
122
- font-weight: bold;
123
- display: flex;
124
- align-items: center;
125
- justify-content: space-between;
126
- }
127
-
128
- /* Toast close button */
129
- .toast .btn-close {
130
- color: #fff;
131
- background: transparent;
132
- border: none;
133
- font-size: 1.2rem;
134
- font-weight: bold;
135
- cursor: pointer;
136
- }
137
-
138
- .toast .btn-close:hover {
139
- color: #ccc; /* Light gray on hover */
140
- }
141
-
142
- /* Smooth slide-in and fade-out animations */
143
- @keyframes slideIn {
144
- from {
145
- transform: translateY(-20px);
146
- opacity: 0;
147
- }
148
- to {
149
- transform: translateY(0);
150
- opacity: 1;
151
- }
152
- }
153
-
154
- @keyframes fadeOut {
155
- from {
156
- opacity: 1;
157
- }
158
- to {
159
- opacity: 0;
160
- }
161
- }
162
-
163
- .toast {
164
- animation: slideIn 0.5s ease-out, fadeOut 3s 2s ease-out forwards;
165
- }
166
- .logout-button-container {
167
- position: absolute;
168
- top: 20px;
169
- right: 20px;
170
- }
171
-
172
- .logout-button {
173
- padding: 10px 20px;
174
- background-color: #f44336; /* Red color */
175
- color: white;
176
- border: none;
177
- border-radius: 5px;
178
- font-size: 16px;
179
- cursor: pointer;
180
- transition: background-color 0.3s;
181
- }
182
-
183
- .logout-button:hover {
184
- background-color: #d32f2f; /* Darker red on hover */
185
- }
186
-
187
- </style>
188
- </head>
189
- <body>
190
- <div class="logout-button-container">
191
- <form action="{{ url_for('logout') }}" method="POST">
192
- <button type="submit" class="logout-button">Logout</button>
193
- </form>
194
- </div>
195
- <div class="container mt-4">
196
- <h1 class="text-center">Menu</h1>
197
-
198
- <!-- Filter Section -->
199
- <form method="get" action="/menu" class="text-center mb-4">
200
- <label for="category" class="form-label fw-bold">Filter by Category:</label>
201
- <select id="category" name="category" class="form-select" onchange="this.form.submit()">
202
- <option value="All" {% if selected_category == 'All' %}selected{% endif %}>All</option>
203
- {% for category in categories %}
204
- <option value="{{ category }}" {% if selected_category == category %}selected{% endif %}>
205
- {{ category }}
206
- </option>
207
- {% endfor %}
208
- </select>
209
- </form>
210
-
211
- <!-- Menu Items -->
212
- <div class="row">
213
- {% for item in food_items %}
214
- <div class="col-md-6 mb-4">
215
- <div class="card menu-card">
216
- <img src="{{ item.Image1__c }}" class="card-img-top menu-image" alt="{{ item.Name }}" onerror="this.src='/static/placeholder.jpg';">
217
- <div class="card-body">
218
- <h5 class="card-title">{{ item.Name }}</h5>
219
- <p class="card-text">${{ item.Price__c }}</p>
220
- <p class="card-text"><small class="text-muted">{{ item.Category__c }}</small></p>
221
- <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModal"
222
- onclick="showItemDetails('{{ item.Name }}', '{{ item.Price__c }}', '{{ item.Image1__c }}', '{{ item.Description__c }}')">
223
- Add +
224
- </button>
225
- </div>
226
- </div>
227
- </div>
228
- {% endfor %}
229
- </div>
230
- </div>
231
-
232
- <!-- View Cart Button -->
233
- <div class="view-cart-container">
234
- <a href="/cart" class="view-cart-button">
235
- View Cart
236
- </a>
237
- </div>
238
-
239
- <!-- Modal for Item Details -->
240
- <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
241
- <div class="modal-dialog modal-dialog-centered">
242
- <div class="modal-content">
243
- <div class="modal-header">
244
- <h5 class="modal-title" id="itemModalLabel">Item Details</h5>
245
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
246
- </div>
247
- <div class="modal-body">
248
- <!-- Item Image -->
249
- <img id="modal-img" class="img-fluid rounded mb-3 d-block mx-auto" alt="Item Image" style="max-height: 200px; object-fit: cover;">
250
- <!-- Item Name -->
251
- <h5 id="modal-name" class="fw-bold text-center"></h5>
252
- <!-- Item Price -->
253
- <p id="modal-price" class="text-muted text-center"></p>
254
- <!-- Item Description -->
255
- <p id="modal-description" class="text-secondary"></p>
256
- <!-- Add-ons -->
257
- <div id="modal-addons" class="modal-addons mt-4">
258
- <h6>Add-ons</h6>
259
- <div id="addons-list" class="addons-container">Loading add-ons...</div>
260
- </div>
261
- </div>
262
- <div class="modal-footer">
263
- <button type="button" class="btn btn-primary" onclick="addToCartFromModal()">Add to Cart</button>
264
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
265
- </div>
266
- </div>
267
- </div>
268
- </div>
269
-
270
- <!-- JavaScript -->
271
- <script>
272
-
273
- // Attach event listener to close button
274
- document.addEventListener('DOMContentLoaded', function () {
275
- document.querySelector('.btn-close').addEventListener('click', function () {
276
- const triggerButton = document.querySelector('[data-bs-target="#itemModal"]');
277
- if (triggerButton) {
278
- triggerButton.focus(); // Return focus to the trigger button
279
- }
280
- });
281
- });
282
-
283
- function showItemDetails(name, price, image, description) {
284
- // Set modal content dynamically
285
- document.getElementById('modal-name').innerText = name;
286
- document.getElementById('modal-price').innerText = `$${price}`;
287
- document.getElementById('modal-img').src = image || '/static/placeholder.jpg';
288
- document.getElementById('modal-description').innerText = description || 'No description available.';
289
- document.getElementById('addons-list').innerHTML = 'Loading add-ons...';
290
-
291
- // Fetch add-ons dynamically based on item Name
292
- fetch(`/api/addons?item_name=${encodeURIComponent(name)}`)
293
- .then(response => response.json())
294
- .then(data => {
295
- const addonsList = document.getElementById('addons-list');
296
- addonsList.innerHTML = ''; // Clear previous content
297
-
298
- // If no add-ons are available, display message
299
- if (!data.success || !data.addons || data.addons.length === 0) {
300
- addonsList.innerHTML = 'No add-ons available.';
301
- return;
302
- }
303
-
304
- // Populate the add-ons list
305
- data.addons.forEach(addon => {
306
- const listItem = document.createElement('div');
307
- listItem.innerHTML = `
308
- <input type="checkbox" id="addon-${addon.Id}" value="${addon.Id}" />
309
- <label for="addon-${addon.Id}">${addon.Name} - $${addon.Price__c}</label>
310
- `;
311
- addonsList.appendChild(listItem);
312
- });
313
- })
314
- .catch(err => {
315
- console.error('Error fetching add-ons:', err);
316
- document.getElementById('addons-list').innerHTML = 'Unable to fetch add-ons. Please try again later.';
317
- });
318
- }
319
- function addToCartFromModal() {
320
- const itemName = document.getElementById('modal-name').innerText;
321
- const itemPrice = parseFloat(document.getElementById('modal-price').innerText.replace('$', ''));
322
- const itemImage = document.getElementById('modal-img').src;
323
- const selectedAddOns = Array.from(
324
- document.querySelectorAll('#addons-list input[type="checkbox"]:checked')
325
- ).map(addon => addon.value);
326
-
327
-
328
- //console.log("Add to cart payload:", { itemName, itemPrice, itemImage, selectedAddOns });
329
-
330
- if (!itemName || !itemPrice) {
331
- alert('Failed to add item to cart. Please try again.');
332
- return;
333
- }
334
-
335
- const cartPayload = {
336
- itemName: itemName,
337
- itemPrice: itemPrice,
338
- itemImage: itemImage,
339
- addons: selectedAddOns
340
- };
341
-
342
- fetch('/cart/add', {
343
- method: 'POST',
344
- headers: {
345
- 'Content-Type': 'application/json',
346
- },
347
- body: JSON.stringify(cartPayload)
348
- })
349
- .then(response => response.json())
350
- .then(data => {
351
- console.log("Server response:", data);
352
- if (data.success) {
353
- // Show a toast notification instead of redirecting
354
- showToast('Item added to cart successfully!');
355
-
356
- //close the modal
357
- const modal = bootstrap.Modal.getInstance(document.getElementById('itemModal'));
358
- if (modal) {
359
- modal.hide();
360
- console.log("Modal closed");
361
- }
362
- } else {
363
- console.error('Error adding item to cart:', data.error);
364
- alert(data.error || 'Failed to add item to cart.');
365
- }
366
- })
367
- .catch(err => {
368
- console.error('Error adding item to cart:', err);
369
- alert('This item is already there in cart.');
370
- });
371
- }
372
-
373
- // Helper function to show toast notification
374
- function showToast(message) {
375
- const toastEl = document.getElementById('cartToast');
376
- const toastBody = document.querySelector('#cartToast .toast-body');
377
- toastBody.innerText = message; // Update toast message
378
- const toast = new bootstrap.Toast(toastEl);
379
- toast.show();
380
- }
381
-
382
- </script>
383
-
384
- <!-- Bootstrap JS -->
385
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
386
-
387
- <div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1055;">
388
- <div id="cartToast" class="toast align-items-center text-bg-success" role="alert" aria-live="assertive" aria-atomic="true">
389
- <div class="d-flex">
390
- <div class="toast-body">
391
- Item added to cart successfully!
392
- </div>
393
- <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
394
- </div>
395
- </div>
396
- </div>
397
-
398
- </body>
399
- </html>
 
1
+ from flask import Flask, render_template, request
2
+ from simple_salesforce import Salesforce
3
+
4
+ app = Flask(__name__)
5
+ app.secret_key = 'your_secret_key'
6
+
7
+ # Salesforce Connection (Replace with your credentials)
8
+ sf = Salesforce(username='your_username', password='your_password', security_token='your_token')
9
+
10
+ @app.route("/menu")
11
+ def menu():
12
+ selected_category = request.args.get("category", "All")
13
+ try:
14
+ query = "SELECT Name, Price__c, Image1__c, Category__c, Description__c FROM Menu_Item__c"
15
+ result = sf.query(query)
16
+ food_items = result['records'] if 'records' in result else []
17
+ categories = {item['Category__c'] for item in food_items if 'Category__c' in item}
18
+ if selected_category != "All":
19
+ food_items = [item for item in food_items if item.get("Category__c") == selected_category]
20
+ except Exception as e:
21
+ food_items = []
22
+ categories = []
23
+ print(f"Error fetching data: {e}")
24
+ return render_template("menu.html", food_items=food_items, categories=categories, selected_category=selected_category)
25
+
26
+ if __name__ == "__main__":
27
+ app.run(debug=True)