geethareddy commited on
Commit
b53057b
·
verified ·
1 Parent(s): e92b578

Update templates/cart.html

Browse files
Files changed (1) hide show
  1. templates/cart.html +386 -540
templates/cart.html CHANGED
@@ -6,11 +6,11 @@
6
  <title>Cart</title>
7
  <!-- Bootstrap CSS -->
8
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
 
9
  <style>
10
-
11
- body {
12
  font-family: Arial, sans-serif;
13
- background-color: #fdf4e3; /* Updated background color */
14
  color: #333;
15
  }
16
  .cart-container {
@@ -19,114 +19,105 @@
19
  padding: 15px;
20
  background-color: #FFFFFF;
21
  border-radius: 10px;
22
-
23
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
24
  }
25
- .cart-container2 {
26
- background-color:#FFFFFF;
27
- }
28
- /* Green Back Button styling */
29
  .back-button {
30
  position: absolute;
31
  top: 15px;
32
  left: 15px;
33
  display: inline-block;
34
- background-color: green; /* Green color */
35
  color: white;
36
  padding: 10px 20px;
37
  text-decoration: none;
38
  font-weight: bold;
39
  border-radius: 4px;
40
- z-index: 10; /* Ensure it stays above other content */
41
  }
42
  .back-button:hover {
43
- background-color: darkgreen; /* Darker green color on hover */
44
- }
45
- .cart-item {
46
- display: flex;
47
- align-items: flex-start;
48
- justify-content: space-between;
49
- border: 1px solid transparent; /* Set the border to transparent */
50
- padding: 30px 15px 15px;
51
- background-color: #fff;/* Padding for the content */
52
- box-sizing: border-box;
53
- min-height: 100px;
54
- position: relative; /* Make the cart item a reference for the absolute positioning of the remove icon */
55
- border: 1px solid #fdf4e3; /* light Orange border around each item */
56
- border-radius: 8px; /* Rounded corners for items */
57
- }
58
- .remove-btn {
59
- border: none; /* Remove the border around the button */
60
- background-color: transparent; /* Transparent background */
61
- cursor: pointer; /* Change cursor to pointer */
62
- font-size: 1.2rem; /* Slightly decrease the size of the trash icon */
63
- margin-bottom: 10px; /* Add space below the delete icon */
64
- transition: color 0.3s ease; /* Smooth transition for icon color */
65
- position: relative; /* Make it relative for movement */
66
- top: -35px; /* Move the button 10px upwards */
67
- left: 50px; /* Move the button 30px to the right */
68
- }
69
- .remove-btn i {
70
- color: red; /* Make the trash icon red */
71
- }
72
- /* Hover effect */
73
- .remove-btn:hover {
74
- color: black; /* Change the icon color to black on hover */
75
- background-color: transparent; /* Keep background transparent on hover */
76
- }
77
- /* Prevent background color on focus or click */
78
- .remove-btn:focus {
79
- outline: none; /* Remove the outline */
80
- background-color: transparent; /* Keep background transparent after clicking */
81
- }
82
- /* Green Color for Prices */
83
- .text-primary {
84
- color: #2e7d32; /* Green color for the prices */
85
- text-align: right; /* Center-align the price */
86
- font-weight: bold; /* Make the price text bold */
87
- white-space: nowrap; /* Prevent price text from wrapping */
88
- }
89
- /* For the image container */
90
- .image-wrapper {
91
- width: 80px; /* Width of the image container */
92
- height: 80px !important; /* Set the height of the container to match the image */
93
- display: flex; /* Flex container for the image */
94
- align-items: center; /* Center image vertically */
95
- justify-content: center; /* Center image horizontally */
96
- }
97
- /* For the image */
98
- .cart-item img {
99
- width: 70px; /* Set the width to 70px */
100
- height: 70px; /* Set the height to 70px */
101
- object-fit: cover; /* Ensure the image covers the container without stretching */
102
- border-radius: 5px; /* Optional: rounded corners */
103
- border: 1px solid #ffcc80; /* Light orange border around images */
104
- margin: 0; /* Ensure no extra space around the image */
105
- }
106
-
107
  .cart-item img:hover {
108
  transform: scale(1.05);
109
  }
110
  .cart-item-title {
111
  font-size: 1.1rem;
112
- font-weight: bold; /* Make the title text bold */
113
  }
114
-
115
  .checkout-button {
116
- background-color: #ff5722; /* Full Orange color */
117
- color: #ffffff; /* White text */
118
- padding: 12px;
119
- border-radius: 8px;
120
- border: none;
121
- width: 100%;
122
- font-size: 1.2rem;
123
- cursor: pointer;
124
- transition: background-color 0.3s, color 0.3s;
125
- }
126
- .checkout-button:hover {
127
- background-color: #ff5722; /* Full Orange color on hover */
128
- color: #ffffff; /* White text on hover */
129
- }
130
  .add-back-button {
131
  padding: 6px 20px;
132
  font-size: 0.9rem;
@@ -141,12 +132,10 @@
141
  background-color: #fff;
142
  color: #0FAA39;
143
  }
144
-
145
  .cart-item-details {
146
  flex: 1;
147
  margin-left: 15px;
148
  }
149
-
150
  .cart-item-quantity {
151
  display: flex;
152
  align-items: center;
@@ -169,243 +158,193 @@
169
  font-size: 1rem;
170
  margin: 0 5px;
171
  }
172
- /* Make the parent container position relative */
173
- .cart-summary {
174
- position: relative; /* Make sure dropdown is positioned relative to this container */
175
- text-align: left;
176
- margin-top: 15px;
177
- padding: 20px;
178
- background-color: #fff;
179
- border-radius: 12px;
180
- border: 2px solid #fdf4e3; /* light Orange border around the cart summary */
181
- box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
182
- }
183
- .cart-item-instructions {
184
- word-wrap: break-word; /* Ensure that long instructions text wraps to the next line */
185
- white-space: normal; /* Allow text to wrap and prevent overflow */
186
- overflow: hidden; /* Hide any overflow text */
187
- max-width: 100%; /* Ensure instructions text stays within the container's width */
188
- word-break: break-word; /* Break the word when necessary */
189
-
190
- }
191
- /* Coupon Section styling */
192
- .coupon-selection {
193
- display: flex; /* Use flexbox to align items */
194
- justify-content: space-between; /* Space between the label and the link */
195
- align-items: center;
196
- font-size: 1rem;
197
- margin-bottom: 20px; /* Add space below Apply Coupon section */
198
- position: relative; /* Ensure dropdown is within this container */
199
- }
200
- /* Ensure the Apply Coupon label and link are aligned correctly */
201
- .coupon-selection label {
202
- font-weight: bold;
203
- color: black;
204
- }
205
- .coupon-selection a {
206
- color: #007bff; /* Blue for the link */
207
- font-size: 1rem;
208
- text-decoration: none;
209
- text-align: right;
210
- }
211
- /* Coupon Dropdown styling */
212
- #couponDropdown {
213
- width: 30%; /* Set dropdown to 30% of the width */
214
- display: none; /* Hidden by default */
215
- background-color: #fff;
216
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Add shadow */
217
- z-index: 10; /* Ensure it's above other content */
218
- margin-top: 10px; /* Add space from the link */
219
- margin-left: auto; /* Push it to the right side */
220
- margin-right: 0; /* Ensure it doesn't overflow outside */
221
- }
222
- /* Show the dropdown when it's active */
223
- #couponDropdown.show {
224
- display: block;
225
- }
226
- /* Ensure Apply Coupon section aligns correctly */
227
- .coupon-selection {
228
- display: flex;
229
- justify-content: space-between;
230
- align-items: center;
231
- font-size: 1rem;
232
- margin-bottom: 20px; /* Add space below Apply Coupon section */
233
- }
234
- /* Apply Coupon link and label styles */
235
- .coupon-selection label {
236
- font-weight: bold;
237
- color: black;
238
- }
239
- .coupon-selection a {
240
- color: #007bff; /* Blue for the link */
241
- font-size: 1rem;
242
- text-decoration: none;
243
- text-align: right;
244
- }
245
- /* Bill details grid structure */
246
- .bill-details {
247
- display: grid;
248
- grid-template-columns: 1fr 1fr; /* Two-column layout */
249
- grid-gap: 10px;
250
- margin-bottom: 10px;
251
- }
252
- /* Adjust label and amount for bill details */
253
- .bill-details .label {
254
- font-weight: 600;
255
- font-size: 1rem;
256
- }
257
- .bill-details .amount {
258
- text-align: right;
259
- font-weight: 600;
260
- font-size: 1rem;
261
- }
262
- /* Divider line between bill sections */
263
- .dotted-line {
264
- border-bottom: 2px dotted #ccc;
265
- margin: 15px 0;
266
- }
267
- /* Total bill grid layout */
268
- .total-bill {
269
- display: grid;
270
- grid-template-columns: 1fr 1fr;
271
- font-weight: 600;
272
- font-size: 1.2rem;
273
- margin-top: 10px;
274
- margin-bottom: 10px; /* Add 10px space between To Pay and Submit Button */
275
- }
276
- .total-bill .label {
277
- font-size: 1.1rem;
278
- }
279
- .total-bill .amount {
280
- text-align: right;
281
- font-size: 1.1rem;
282
- color: #2e7d32; /* Green for Total Bill Price */
283
- }
284
- /* Margin to add space for dropdown when visible */
285
- .cart-summary.has-dropdown {
286
- margin-bottom: 80px; /* Create space below the content when dropdown is visible */
287
- }
288
- .checkout-button {
289
- background-color: #ff5722;
290
- color: #ffffff;
291
- padding: 12px;
292
- border-radius: 8px;
293
- border: none;
294
- height: 44px;
295
- width: 100%;
296
- font-size: 1.2rem;
297
- cursor: pointer;
298
- transition: background-color 0.3s, color 0.3s;
299
- display: flex;
300
- justify-content: center;
301
- align-items: center;
302
- text-align: center;
303
- }
304
- .suggestion-section {
305
- margin-top: 25px;
306
- padding: 15px;
307
- background-color: #fff;
308
- border-radius: 10px;
309
- border: 2px solid #fdf4e3; /* light Orange border around the complete meal box */
310
- }
311
- .suggestion-items-container {
312
- display: flex;
313
- overflow-x: auto; /* Horizontal scrolling */
314
- gap: 10px; /* Space between items */
315
- padding-bottom: 10px;
316
- padding-top: 10px;
317
- }
318
- /* Styling for the suggestion item card */
319
- .suggestion-item {
320
- display: flex; /* Align items horizontally */
321
- align-items: center; /* Center image and text vertically */
322
- justify-content: flex-start; /* Align items to the start (left side) */
323
- flex-shrink: 0;
324
- width: 160px; /* Set fixed width for each suggestion item */
325
- padding: 10px;
326
- border-radius: 8px; /* Rounded corners */
327
- background-color: #fff;
328
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
329
- transition: transform 0.3s ease;
330
- margin-right: 10px; /* Ensure there's space between the cards */
331
- position: relative; /* For positioning the + icon */
332
- text-align: left; /* Align text to the left */
333
- overflow: visible; /* Allow the button to overflow outside */
334
- border: 2px solid #fdf4e3; /* light Orange border around the suggestion items */
335
- }
336
- .suggestion-item:hover {
337
- transform: scale(1.05); /* Slight zoom effect on hover */
338
- }
339
- .suggestion-item img {
340
- width: 50px; /* Set a fixed width for the image */
341
- height: 50px; /* Set a fixed height for the image */
342
- object-fit: cover; /* Ensure image fits correctly without distortion */
343
- border-radius: 5px; /* Rounded corners for the image */
344
- margin-right: 12px; /* Space between the image and text */
345
- }
346
- .suggestion-item div {
347
- flex-grow: 1; /* Allow the text section to expand and fill available space */
348
- text-align: left; /* Align text to the left */
349
- }
350
- /* Styling for the + symbol button (with green border, white background, and black text) */
351
- .add-back-button {
352
- position: absolute;
353
- top: -5px;
354
- right: -10px;
355
- font-size: 1rem; /* Smaller font size */
356
- padding: 0; /* Remove padding */
357
- width: 30px; /* Set fixed width */
358
- height: 30px; /* Set fixed height */
359
- background-color: #fff;
360
- color: #0FAA39;
361
- border: 2px solid #0FAA39;
362
- border-radius: 0; /* Square shape */
363
- cursor: pointer;
364
- transition: background-color 0.3s, color 0.3s, border-color 0.3s;
365
- z-index: 2; /* Increased z-index to ensure it stays above the borders */
366
- }
367
- .add-back-button:hover {
368
- background-color: #fff; /* Green background on hover */
369
- color: #0FAA39; /* White color for the + symbol when hovered */
370
- border-color: #0FAA39; /* Green border on hover */
371
- z-index: 3; /* Ensure button stays on top when hovered */
372
- }
373
- /* Ensure the scroll container works fine */
374
- .suggestion-items-container::-webkit-scrollbar {
375
- height: 8px; /* Height of the scrollbar */
376
- }
377
- .suggestion-items-container::-webkit-scrollbar-thumb {
378
- background-color: #fff; /* Green color for scrollbar thumb */
379
- border-radius: 4px;
380
- }
381
- .suggestion-items-container::-webkit-scrollbar-track {
382
- background-color: #f1f1f1;
383
- }
384
-
385
- .cart-item-actions {
386
- display: flex; /* Use flexbox to align items horizontally */
387
- align-items: flex-start; /* Align the price at the top of the cart item (like the item name) */
388
- margin-left: auto; /* This will push the price to the right side of the cart item */
389
- }
390
- h4.mb-4.fw-bold {
391
- text-align: center; /* Centers the title */
392
- color: #FF5722; /* Orange color for the title */
393
- .cart-container h4 {
394
- text-align: center; /* This will center the title horizontally */
395
- color: #FF5722; /* Orange color */
396
- font-weight: bold; /* Make it bold */
397
- }
398
-
399
  </style>
400
  </head>
401
  <body>
402
  <div class="container">
403
  <div class="cart-container">
404
  <div style="text-align: right;">
405
- <a href="/menu" style="text-decoration: none; font-size: 1.5rem; color: #007bff;">&times;</a>
406
  </div>
407
 
408
- <h4 class="mb-4 fw-bold">Your Cart</h4>
409
 
410
  <!-- Cart Items -->
411
  <div class="cart-container2">
@@ -419,7 +358,7 @@
419
  {{ item.Name }}
420
  </div>
421
  <div class="cart-item-addons">
422
- <small class="text-muted">Add-ons: {{ item.Add_Ons__c }}</small>
423
  </div>
424
  <div class="cart-item-instructions">
425
  <small class="text-muted">Instructions: {{ item.Instructions__c or "None" }}</small>
@@ -431,20 +370,15 @@
431
  </div>
432
  </div>
433
  <div class="cart-item-actions">
434
- <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
435
-
436
- <!-- Delete Button with Trash Icon and onclick handler -->
437
  <button type="button" class="btn btn-light text-dark remove-btn" onclick="removeItemFromCart('{{ item.Name }}')">
438
  <i class="bi bi-trash"></i>
439
  </button>
440
-
441
  <div class="text-primary" style="color: #000 !important;">
442
  $<span class="base-price">{{ item.Price__c }}</span>
443
  </div>
444
  </div>
445
  </div>
446
  {% else %}
447
- <!-- Code to handle the case when cart_items is empty -->
448
  <p>No items in your cart.</p>
449
  {% endfor %}
450
  </div>
@@ -461,331 +395,243 @@
461
  <div>{{ suggestion.Name }}</div>
462
  <div class="text-muted">${{ suggestion.Price__c }}</div>
463
  </div>
464
- <!-- Replace add button with a cart icon -->
465
  <button class="add-back-button" onclick="addToCartSuggestion('{{ suggestion.Name }}', '{{ suggestion.Price__c }}', '{{ suggestion.Image1__c }}', '{{ suggestion.Id }}')">+</button>
466
-
467
-
468
  </div>
469
  {% endfor %}
470
  </div>
471
  </div>
472
-
473
  {% endif %}
474
 
475
  <!-- Subtotal -->
476
  <div class="cart-summary">
477
- <!-- Coupon Section -->
478
- {% if coupons %}
479
- <div class="coupon-selection d-flex justify-content-between align-items-center">
480
- <label class="text-dark font-weight-bold mb-0">Apply Coupon</label>
481
- <a href="javascript:void(0);" id="applyCouponLink" onclick="toggleCouponDropdown()" class="text-primary">+ Apply Coupon</a>
482
- </div>
483
-
484
- <!-- Coupon Dropdown, positioned below Apply Coupon -->
485
- <select id="couponDropdown" class="form-select mt-2" style="display:none;" onchange="calculateDiscount()">
486
- <option value="">Select a coupon</option>
487
- {% for coupon in coupons %}
488
- <option value="{{ coupon }}">{{ coupon }}</option>
489
- {% endfor %}
490
- </select>
491
- {% endif %}
492
-
493
-
494
 
495
  <div class="bill-details">
496
  <div class="label">Cart Total</div>
497
- <div class="amount">${{ subtotal }}</div>
498
-
499
-
500
  <div class="label">Discount</div>
501
- <div class="amount" id="discountText">-${{ discount }}</div>
502
-
503
-
504
-
505
-
506
  </div>
507
 
508
  <div class="dotted-line"></div>
509
 
510
  <div class="total-bill">
511
- <div class="label">To Pay</div>
512
- <div class="amount" id="totalBillText">${{ subtotal }}</div>
513
  </div>
514
  <button class="checkout-button" onclick="proceedToOrder()">Proceed to Order</button>
515
  </div>
516
  </div>
517
  </div>
518
 
519
-
520
  <script>
521
- // Example function to handle the increase/decrease button clicks
522
- function updateQuantity(action, itemName, customerEmail) {
523
- let quantityInput = document.querySelector(`input[data-item-name="${itemName}"]`);
524
- if (!quantityInput) {
525
- alert("Quantity input not found for item: " + itemName);
526
- return;
527
- }
528
-
529
- let quantity = parseInt(quantityInput.value);
530
- let originalQuantity = quantity; // Store original quantity to revert on failure
531
 
532
- // Update quantity based on action
533
- if (action === 'increase') {
534
- quantity++;
535
- } else if (action === 'decrease' && quantity > 1) {
536
- quantity--;
537
- }
538
 
539
- // Validate quantity
540
- if (isNaN(quantity) || quantity < 1) {
541
- alert("Invalid quantity!");
542
- return;
543
- }
544
 
545
- // Optimistically update the UI
546
- quantityInput.value = quantity;
 
 
 
547
 
548
- // Calculate and update subtotal dynamically
549
- let itemElement = quantityInput.closest(".cart-item");
550
- if (!itemElement) {
551
- console.error(`Parent cart item element not found for item: ${itemName}`);
552
- quantityInput.value = originalQuantity; // Revert on failure
553
- return;
554
- }
555
 
556
- let basePriceElement = itemElement.querySelector(".base-price");
557
- let addonsPriceElement = itemElement.querySelector(".addons-price");
558
- let subtotalElement = itemElement.querySelector(".subtotal");
559
 
560
- if (!basePriceElement || !subtotalElement) {
561
- console.error(`Price or subtotal element not found for item: ${itemName}`);
562
- quantityInput.value = originalQuantity; // Revert on failure
563
- return;
564
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
565
 
566
- let basePrice = parseFloat(basePriceElement.innerText);
567
- let addonsPrice = addonsPriceElement ? parseFloat(addonsPriceElement.innerText) : 0;
568
- let subtotal = quantity * (basePrice + addonsPrice);
569
- subtotalElement.innerText = subtotal.toFixed(2);
 
 
 
570
 
571
- // Update total price
572
- updateTotalPrice();
 
573
 
574
- // Send updated quantity to the server
575
- fetch('/cart/update_quantity', {
576
- method: 'POST',
577
- headers: { 'Content-Type': 'application/json' },
578
- body: JSON.stringify({ email: customerEmail, item_name: itemName, quantity: quantity }),
579
- credentials: 'include' // Include credentials for session-based carts
580
- })
581
- .then(response => response.json())
582
- .then(data => {
583
- if (data.success) {
584
- // Server update successful, UI is already updated
585
- console.log(`Quantity updated for ${itemName}: ${quantity}`);
586
- } else {
587
- // Revert UI changes on failure
588
- quantityInput.value = originalQuantity;
589
- let revertedSubtotal = originalQuantity * (basePrice + addonsPrice);
590
- subtotalElement.innerText = revertedSubtotal.toFixed(2);
591
- updateTotalPrice();
592
- alert(`Error updating quantity: ${data.error || 'Unknown error'}`);
593
- }
594
- })
595
- .catch(err => {
596
- // Revert UI changes on network error
597
- quantityInput.value = originalQuantity;
598
- let revertedSubtotal = originalQuantity * (basePrice + addonsPrice);
599
- subtotalElement.innerText = revertedSubtotal.toFixed(2);
600
- updateTotalPrice();
601
- alert(`Network error while updating quantity: ${err.message}`);
602
- console.error("Error:", err);
603
- });
604
- }
605
  function toggleCouponDropdown() {
606
  let couponDropdown = document.getElementById('couponDropdown');
607
-
608
- // Toggle the visibility of the coupon dropdown
609
  if (couponDropdown.style.display === "none" || couponDropdown.style.display === "") {
610
  couponDropdown.style.display = "block";
611
  } else {
612
  couponDropdown.style.display = "none";
613
  }
614
  }
 
615
  function calculateDiscount() {
616
- let couponDropdown = document.getElementById('couponDropdown'); // Get coupon dropdown
617
- let selectedCoupon = couponDropdown.value.trim(); // Get the selected coupon value
618
- let subtotal = parseFloat("{{ subtotal }}"); // Get the subtotal (from the backend)
619
- // If a valid coupon is selected
620
  if (selectedCoupon && selectedCoupon.toLowerCase() !== "none") {
621
- // Apply 10% discount
622
  let discount = subtotal * 0.10;
623
  let total = subtotal - discount;
624
- // Update UI with discount and total bill
625
- document.getElementById("discountText").innerText = `$${discount.toFixed(2)}`;
626
  document.getElementById("totalBillText").innerText = `$${total.toFixed(2)}`;
627
  } else {
628
- // If no coupon is selected or "None" is selected, reset the discount
629
- document.getElementById("discountText").innerText = `$0.00`;
630
  document.getElementById("totalBillText").innerText = `$${subtotal.toFixed(2)}`;
631
  }
632
  }
633
-
634
  function proceedToOrder() {
635
  let couponDropdown = document.getElementById('couponDropdown');
636
-
637
- // Initialize selectedCoupon to an empty string by default
638
- let selectedCoupon = "";
639
-
640
- // Only proceed if couponDropdown exists
641
- if (couponDropdown) {
642
- // If the value is not null or undefined, strip the value
643
- if (couponDropdown.value != null) {
644
- selectedCoupon = couponDropdown.value.trim(); // safely call .trim() if value is not null
645
- } else {
646
- selectedCoupon = ""; // Assign empty string if value is null
647
- }
648
- }
649
- // If no coupon is selected or the value is empty, treat it as no coupon
650
  if (selectedCoupon === "" || selectedCoupon === "None" || selectedCoupon === "Null") {
651
- selectedCoupon = null; // Treat it as no coupon selected
652
  }
653
- // Send the selected coupon to the backend for processing
654
- fetch('/cart/checkout', {
655
  method: 'POST',
656
  headers: { 'Content-Type': 'application/json' },
657
- body: JSON.stringify({ selectedCoupon: selectedCoupon })
 
658
  })
659
  .then(response => response.json())
660
  .then(data => {
661
  if (data.success) {
662
- alert(data.message); // Success message
663
- window.location.href = '/order'; // Redirect to order page
664
  } else {
665
- alert(data.error || data.message); // Handle error message
666
  }
667
  })
668
  .catch(err => console.error('Error during checkout:', err));
669
  }
670
- function calculateSubtotal() {
671
- let subtotal = 0;
672
- document.querySelectorAll('.cart-item').forEach(item => {
673
- const quantity = parseInt(item.querySelector('input').value);
674
- const basePrice = parseFloat(item.querySelector('.base-price').innerText.replace('$', '')); // Base Price
675
- const addonsPrice = parseFloat(item.querySelector('.addons-price').innerText.replace('$', '')) || 0; // Add-ons Price
676
- subtotal += (basePrice * quantity) + addonsPrice; // Include add-ons price in subtotal
677
- });
678
- // Update the subtotal in the HTML
679
- document.querySelector('.cart-summary p').innerText = `Subtotal: $${subtotal.toFixed(2)}`;
680
- return subtotal;
681
- }
682
- function addSuggestion(itemId) {
683
- fetch(`/cart/add_suggestion/${itemId}`, {
684
- method: 'POST',
685
- headers: { 'Content-Type': 'application/json' },
686
- body: JSON.stringify({})
687
- })
688
- .then(response => response.json())
689
- .then(data => {
690
- if (data.success) {
691
- alert('Item added to cart!');
692
- location.reload();
693
- } else {
694
- alert(data.error);
695
- }
696
- })
697
- .catch(err => console.error('Error adding suggestion:', err));
698
- }
699
  function removeItemFromCart(itemName) {
700
- fetch(`/cart/remove/${encodeURIComponent(itemName)}`, {
701
  method: 'POST',
702
- headers: {
703
- 'Content-Type': 'application/json'
704
- }
705
  })
706
  .then(response => response.json())
707
  .then(data => {
708
  if (data.success) {
709
  alert(data.message);
710
- location.reload(); // Reload the page to update the cart
711
  } else {
712
  alert(data.message);
713
  }
714
  })
715
  .catch(err => console.error('Error removing item:', err));
716
  }
 
717
  function addToCart(itemName, customerEmail) {
718
- fetch(`/cart/add_item`, {
719
  method: "POST",
720
  headers: { "Content-Type": "application/json" },
721
  body: JSON.stringify({
722
  email: customerEmail,
723
- item_name: itemName.trim(), //Ensure the item name is trimmed
724
- quantity: 0 // DEFAULT QUANTITY PASSED HERE
725
- })
 
726
  })
727
  .then(response => response.json())
728
  .then(data => {
729
  if (data.success) {
730
  alert("Item added/updated successfully.");
731
- location.reload(); // Reload the page to update the cart
732
- } else {
733
- alert(data.error || "Failed to add item to cart.");
734
- }
735
- })
736
- .catch(err => console.error("Error adding item to cart:", err));
737
- }
738
- function addSuggestion(itemId) {
739
- fetch(`/cart/add_suggestion/${itemId}`, {
740
- method: 'POST',
741
- headers: { 'Content-Type': 'application/json' },
742
- body: JSON.stringify({})
743
- })
744
- .then(response => response.json())
745
- .then(data => {
746
- if (data.success) {
747
- alert('Item added to cart!');
748
  location.reload();
749
  } else {
750
- alert(data.error);
751
  }
752
  })
753
- .catch(err => console.error('Error adding suggestion:', err));
 
 
 
754
  }
 
755
  function addToCartSuggestion(itemName, itemPrice, itemImage, itemId) {
756
- const customerEmail = "{{ customer_email }}"; // Get customer email from session
757
- // Create the data object to send to the ser ver
758
  const data = {
759
  item_name: itemName,
760
  item_price: itemPrice,
761
  item_image: itemImage,
762
  item_id: itemId,
763
- addons: [], // Default to empty, you can adjust if needed
764
- instructions: "", // Default to empty, you can adjust if needed
765
  customer_email: customerEmail
766
  };
767
- // Send the data to the backend via a POST request
768
- fetch('/cart/add_suggestion_to_cart', {
769
  method: 'POST',
770
- headers: {
771
- 'Content-Type': 'application/json'
772
- },
773
- body: JSON.stringify(data)
774
  })
775
  .then(response => response.json())
776
  .then(data => {
777
  if (data.success) {
778
  alert('Item added to cart!');
779
- location.reload(); // Reload to update the cart view
780
  } else {
781
  alert('Error adding item to cart: ' + data.error);
782
  }
783
  })
784
- .catch(err => console.error('Error adding item:', err));
 
 
 
785
  }
786
-
787
-
788
- </script>
789
 
 
 
 
 
 
790
  </body>
791
- </html>
 
6
  <title>Cart</title>
7
  <!-- Bootstrap CSS -->
8
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
10
  <style>
11
+ body {
 
12
  font-family: Arial, sans-serif;
13
+ background-color: #fdf4e3;
14
  color: #333;
15
  }
16
  .cart-container {
 
19
  padding: 15px;
20
  background-color: #FFFFFF;
21
  border-radius: 10px;
 
22
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
23
  }
24
+ .cart-container2 {
25
+ background-color: #FFFFFF;
26
+ }
 
27
  .back-button {
28
  position: absolute;
29
  top: 15px;
30
  left: 15px;
31
  display: inline-block;
32
+ background-color: green;
33
  color: white;
34
  padding: 10px 20px;
35
  text-decoration: none;
36
  font-weight: bold;
37
  border-radius: 4px;
38
+ z-index: 10;
39
  }
40
  .back-button:hover {
41
+ background-color: darkgreen;
42
+ }
43
+ .cart-item {
44
+ display: flex;
45
+ align-items: flex-start;
46
+ justify-content: space-between;
47
+ border: 1px solid transparent;
48
+ padding: 30px 15px 15px;
49
+ background-color: #fff;
50
+ box-sizing: border-box;
51
+ min-height: 100px;
52
+ position: relative;
53
+ border: 1px solid #fdf4e3;
54
+ border-radius: 8px;
55
+ }
56
+ .remove-btn {
57
+ border: none;
58
+ background-color: transparent;
59
+ cursor: pointer;
60
+ font-size: 1.2rem;
61
+ margin-bottom: 10px;
62
+ transition: color 0.3s ease;
63
+ position: relative;
64
+ top: -35px;
65
+ left: 50px;
66
+ }
67
+ .remove-btn i {
68
+ color: red;
69
+ }
70
+ .remove-btn:hover {
71
+ color: black;
72
+ background-color: transparent;
73
+ }
74
+ .remove-btn:focus {
75
+ outline: none;
76
+ background-color: transparent;
77
+ }
78
+ .text-primary {
79
+ color: #2e7d32;
80
+ text-align: right;
81
+ font-weight: bold;
82
+ white-space: nowrap;
83
+ }
84
+ .image-wrapper {
85
+ width: 80px;
86
+ height: 80px !important;
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ }
91
+ .cart-item img {
92
+ width: 70px;
93
+ height: 70px;
94
+ object-fit: cover;
95
+ border-radius: 5px;
96
+ border: 1px solid #ffcc80;
97
+ margin: 0;
98
+ }
 
 
 
 
 
 
99
  .cart-item img:hover {
100
  transform: scale(1.05);
101
  }
102
  .cart-item-title {
103
  font-size: 1.1rem;
104
+ font-weight: bold;
105
  }
 
106
  .checkout-button {
107
+ background-color: #ff5722;
108
+ color: #ffffff;
109
+ padding: 12px;
110
+ border-radius: 8px;
111
+ border: none;
112
+ width: 100%;
113
+ font-size: 1.2rem;
114
+ cursor: pointer;
115
+ transition: background-color 0.3s, color 0.3s;
116
+ }
117
+ .checkout-button:hover {
118
+ background-color: #ff5722;
119
+ color: #ffffff;
120
+ }
121
  .add-back-button {
122
  padding: 6px 20px;
123
  font-size: 0.9rem;
 
132
  background-color: #fff;
133
  color: #0FAA39;
134
  }
 
135
  .cart-item-details {
136
  flex: 1;
137
  margin-left: 15px;
138
  }
 
139
  .cart-item-quantity {
140
  display: flex;
141
  align-items: center;
 
158
  font-size: 1rem;
159
  margin: 0 5px;
160
  }
161
+ .cart-summary {
162
+ position: relative;
163
+ text-align: left;
164
+ margin-top: 15px;
165
+ padding: 20px;
166
+ background-color: #fff;
167
+ border-radius: 12px;
168
+ border: 2px solid #fdf4e3;
169
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
170
+ }
171
+ .cart-item-instructions {
172
+ word-wrap: break-word;
173
+ white-space: normal;
174
+ overflow: hidden;
175
+ max-width: 100%;
176
+ word-break: break-word;
177
+ }
178
+ .coupon-selection {
179
+ display: flex;
180
+ justify-content: space-between;
181
+ align-items: center;
182
+ font-size: 1rem;
183
+ margin-bottom: 20px;
184
+ position: relative;
185
+ }
186
+ .coupon-selection label {
187
+ font-weight: bold;
188
+ color: black;
189
+ }
190
+ .coupon-selection a {
191
+ color: #007bff;
192
+ font-size: 1rem;
193
+ text-decoration: none;
194
+ text-align: right;
195
+ }
196
+ #couponDropdown {
197
+ width: 30%;
198
+ display: none;
199
+ background-color: #fff;
200
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
201
+ z-index: 10;
202
+ margin-top: 10px;
203
+ margin-left: auto;
204
+ margin-right: 0;
205
+ }
206
+ #couponDropdown.show {
207
+ display: block;
208
+ }
209
+ .bill-details {
210
+ display: grid;
211
+ grid-template-columns: 1fr 1fr;
212
+ grid-gap: 10px;
213
+ margin-bottom: 10px;
214
+ }
215
+ .bill-details .label {
216
+ font-weight: 600;
217
+ font-size: 1rem;
218
+ }
219
+ .bill-details .amount {
220
+ text-align: right;
221
+ font-weight: 600;
222
+ font-size: 1rem;
223
+ }
224
+ .dotted-line {
225
+ border-bottom: 2px dotted #ccc;
226
+ margin: 15px 0;
227
+ }
228
+ .total-bill {
229
+ display: grid;
230
+ grid-template-columns: 1fr 1fr;
231
+ font-weight: 600;
232
+ font-size: 1.2rem;
233
+ margin-top: 10px;
234
+ margin-bottom: 10px;
235
+ }
236
+ .total-bill .label {
237
+ font-size: 1.1rem;
238
+ }
239
+ .total-bill .amount {
240
+ text-align: right;
241
+ font-size: 1.1rem;
242
+ color: #2e7d32;
243
+ }
244
+ .cart-summary.has-dropdown {
245
+ margin-bottom: 80px;
246
+ }
247
+ .suggestion-section {
248
+ margin-top: 25px;
249
+ padding: 15px;
250
+ background-color: #fff;
251
+ border-radius: 10px;
252
+ border: 2px solid #fdf4e3;
253
+ }
254
+ .suggestion-items-container {
255
+ display: flex;
256
+ overflow-x: auto;
257
+ gap: 10px;
258
+ padding-bottom: 10px;
259
+ padding-top: 10px;
260
+ }
261
+ .suggestion-item {
262
+ display: flex;
263
+ align-items: center;
264
+ justify-content: flex-start;
265
+ flex-shrink: 0;
266
+ width: 160px;
267
+ padding: 10px;
268
+ border-radius: 8px;
269
+ background-color: #fff;
270
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
271
+ transition: transform 0.3s ease;
272
+ margin-right: 10px;
273
+ position: relative;
274
+ text-align: left;
275
+ overflow: visible;
276
+ border: 2px solid #fdf4e3;
277
+ }
278
+ .suggestion-item:hover {
279
+ transform: scale(1.05);
280
+ }
281
+ .suggestion-item img {
282
+ width: 50px;
283
+ height: 50px;
284
+ object-fit: cover;
285
+ border-radius: 5px;
286
+ margin-right: 12px;
287
+ }
288
+ .suggestion-item div {
289
+ flex-grow: 1;
290
+ text-align: left;
291
+ }
292
+ .add-back-button {
293
+ position: absolute;
294
+ top: -5px;
295
+ right: -10px;
296
+ font-size: 1rem;
297
+ padding: 0;
298
+ width: 30px;
299
+ height: 30px;
300
+ background-color: #fff;
301
+ color: #0FAA39;
302
+ border: 2px solid #0FAA39;
303
+ border-radius: 0;
304
+ cursor: pointer;
305
+ transition: background-color 0.3s, color 0.3s, border-color 0.3s;
306
+ z-index: 2;
307
+ }
308
+ .add-back-button:hover {
309
+ background-color: #fff;
310
+ color: #0FAA39;
311
+ border-color: #0FAA39;
312
+ z-index: 3;
313
+ }
314
+ .suggestion-items-container::-webkit-scrollbar {
315
+ height: 8px;
316
+ }
317
+ .suggestion-items-container::-webkit-scrollbar-thumb {
318
+ background-color: #fff;
319
+ border-radius: 4px;
320
+ }
321
+ .suggestion-items-container::-webkit-scrollbar-track {
322
+ background-color: #f1f1f1;
323
+ }
324
+ .cart-item-actions {
325
+ display: flex;
326
+ align-items: flex-start;
327
+ margin-left: auto;
328
+ }
329
+ h4.mb-4.fw-bold {
330
+ text-align: center;
331
+ color: #FF5722;
332
+ }
333
+ .cart-container h4 {
334
+ text-align: center;
335
+ color: #FF5722;
336
+ font-weight: bold;
337
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  </style>
339
  </head>
340
  <body>
341
  <div class="container">
342
  <div class="cart-container">
343
  <div style="text-align: right;">
344
+ <a href="/menu" style="text-decoration: none; font-size: 1.5rem; color: #007bff;">×</a>
345
  </div>
346
 
347
+ <h4 class="mb-4 fw-bold">Your Cart</h4>
348
 
349
  <!-- Cart Items -->
350
  <div class="cart-container2">
 
358
  {{ item.Name }}
359
  </div>
360
  <div class="cart-item-addons">
361
+ <small class="text-muted">Add-ons: {{ item.Add_Ons__c|join(', ') if item.Add_Ons__c else 'None' }}</small>
362
  </div>
363
  <div class="cart-item-instructions">
364
  <small class="text-muted">Instructions: {{ item.Instructions__c or "None" }}</small>
 
370
  </div>
371
  </div>
372
  <div class="cart-item-actions">
 
 
 
373
  <button type="button" class="btn btn-light text-dark remove-btn" onclick="removeItemFromCart('{{ item.Name }}')">
374
  <i class="bi bi-trash"></i>
375
  </button>
 
376
  <div class="text-primary" style="color: #000 !important;">
377
  $<span class="base-price">{{ item.Price__c }}</span>
378
  </div>
379
  </div>
380
  </div>
381
  {% else %}
 
382
  <p>No items in your cart.</p>
383
  {% endfor %}
384
  </div>
 
395
  <div>{{ suggestion.Name }}</div>
396
  <div class="text-muted">${{ suggestion.Price__c }}</div>
397
  </div>
 
398
  <button class="add-back-button" onclick="addToCartSuggestion('{{ suggestion.Name }}', '{{ suggestion.Price__c }}', '{{ suggestion.Image1__c }}', '{{ suggestion.Id }}')">+</button>
 
 
399
  </div>
400
  {% endfor %}
401
  </div>
402
  </div>
 
403
  {% endif %}
404
 
405
  <!-- Subtotal -->
406
  <div class="cart-summary">
407
+ {% if coupons %}
408
+ <div class="coupon-selection d-flex justify-content-between align-items-center">
409
+ <label class="text-dark font-weight-bold mb-0">Apply Coupon</label>
410
+ <a href="javascript:void(0);" id="applyCouponLink" onclick="toggleCouponDropdown()" class="text-primary">+ Apply Coupon</a>
411
+ </div>
412
+ <select id="couponDropdown" class="form-select mt-2" style="display:none;" onchange="calculateDiscount()">
413
+ <option value="">Select a coupon</option>
414
+ {% for coupon in coupons %}
415
+ <option value="{{ coupon }}">{{ coupon }}</option>
416
+ {% endfor %}
417
+ </select>
418
+ {% endif %}
 
 
 
 
 
419
 
420
  <div class="bill-details">
421
  <div class="label">Cart Total</div>
422
+ <div class="amount" id="cartTotal">${{ subtotal }}</div>
 
 
423
  <div class="label">Discount</div>
424
+ <div class="amount" id="discountText">-$0.00</div>
 
 
 
 
425
  </div>
426
 
427
  <div class="dotted-line"></div>
428
 
429
  <div class="total-bill">
430
+ <div class="label">To Pay</div>
431
+ <div class="amount" id="totalBillText">${{ subtotal }}</div>
432
  </div>
433
  <button class="checkout-button" onclick="proceedToOrder()">Proceed to Order</button>
434
  </div>
435
  </div>
436
  </div>
437
 
 
438
  <script>
439
+ // Base URL for API requests
440
+ const BASE_URL = window.location.hostname === '127.0.0.1' ? 'http://127.0.0.1:5000' : 'https://your-backend-url.com';
 
 
 
 
 
 
 
 
441
 
442
+ function updateQuantity(action, itemName, customerEmail) {
443
+ let quantityInput = document.querySelector(`input[data-item-name="${itemName}"]`);
444
+ if (!quantityInput) {
445
+ alert("Quantity input not found for item: " + itemName);
446
+ return;
447
+ }
448
 
449
+ let quantity = parseInt(quantityInput.value);
450
+ let originalQuantity = quantity;
 
 
 
451
 
452
+ if (action === 'increase') {
453
+ quantity++;
454
+ } else if (action === 'decrease' && quantity > 1) {
455
+ quantity--;
456
+ }
457
 
458
+ if (isNaN(quantity) || quantity < 1) {
459
+ alert("Invalid quantity!");
460
+ return;
461
+ }
 
 
 
462
 
463
+ quantityInput.value = quantity;
464
+ updateSubtotal();
 
465
 
466
+ fetch(`${BASE_URL}/cart/update_quantity`, {
467
+ method: 'POST',
468
+ headers: { 'Content-Type': 'application/json' },
469
+ body: JSON.stringify({ email: customerEmail, item_name: itemName, quantity: quantity }),
470
+ credentials: 'include'
471
+ })
472
+ .then(response => response.json())
473
+ .then(data => {
474
+ if (data.success) {
475
+ console.log(`Quantity updated for ${itemName}: ${quantity}`);
476
+ updateSubtotal();
477
+ } else {
478
+ quantityInput.value = originalQuantity;
479
+ updateSubtotal();
480
+ alert(`Error updating quantity: ${data.error || 'Unknown error'}`);
481
+ }
482
+ })
483
+ .catch(err => {
484
+ quantityInput.value = originalQuantity;
485
+ updateSubtotal();
486
+ alert(`Network error while updating quantity: ${err.message}`);
487
+ console.error("Error:", err);
488
+ });
489
+ }
490
 
491
+ function updateSubtotal() {
492
+ let subtotal = 0;
493
+ document.querySelectorAll('.cart-item').forEach(item => {
494
+ const quantity = parseInt(item.querySelector('input').value);
495
+ const basePrice = parseFloat(item.querySelector('.base-price').innerText);
496
+ subtotal += basePrice * quantity;
497
+ });
498
 
499
+ document.getElementById('cartTotal').innerText = `$${subtotal.toFixed(2)}`;
500
+ calculateDiscount();
501
+ }
502
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
  function toggleCouponDropdown() {
504
  let couponDropdown = document.getElementById('couponDropdown');
 
 
505
  if (couponDropdown.style.display === "none" || couponDropdown.style.display === "") {
506
  couponDropdown.style.display = "block";
507
  } else {
508
  couponDropdown.style.display = "none";
509
  }
510
  }
511
+
512
  function calculateDiscount() {
513
+ let couponDropdown = document.getElementById('couponDropdown');
514
+ let selectedCoupon = couponDropdown ? couponDropdown.value.trim() : "";
515
+ let subtotal = parseFloat(document.getElementById('cartTotal').innerText.replace('$', ''));
516
+
517
  if (selectedCoupon && selectedCoupon.toLowerCase() !== "none") {
 
518
  let discount = subtotal * 0.10;
519
  let total = subtotal - discount;
520
+ document.getElementById("discountText").innerText = `-$${discount.toFixed(2)}`;
 
521
  document.getElementById("totalBillText").innerText = `$${total.toFixed(2)}`;
522
  } else {
523
+ document.getElementById("discountText").innerText = `-$0.00`;
 
524
  document.getElementById("totalBillText").innerText = `$${subtotal.toFixed(2)}`;
525
  }
526
  }
527
+
528
  function proceedToOrder() {
529
  let couponDropdown = document.getElementById('couponDropdown');
530
+ let selectedCoupon = couponDropdown ? couponDropdown.value.trim() : "";
531
+
 
 
 
 
 
 
 
 
 
 
 
 
532
  if (selectedCoupon === "" || selectedCoupon === "None" || selectedCoupon === "Null") {
533
+ selectedCoupon = null;
534
  }
535
+
536
+ fetch(`${BASE_URL}/cart/checkout`, {
537
  method: 'POST',
538
  headers: { 'Content-Type': 'application/json' },
539
+ body: JSON.stringify({ selectedCoupon: selectedCoupon }),
540
+ credentials: 'include'
541
  })
542
  .then(response => response.json())
543
  .then(data => {
544
  if (data.success) {
545
+ alert(data.message);
546
+ window.location.href = '/order';
547
  } else {
548
+ alert(data.error || data.message);
549
  }
550
  })
551
  .catch(err => console.error('Error during checkout:', err));
552
  }
553
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  function removeItemFromCart(itemName) {
555
+ fetch(`${BASE_URL}/cart/remove/${encodeURIComponent(itemName)}`, {
556
  method: 'POST',
557
+ headers: { 'Content-Type': 'application/json' },
558
+ credentials: 'include'
 
559
  })
560
  .then(response => response.json())
561
  .then(data => {
562
  if (data.success) {
563
  alert(data.message);
564
+ location.reload();
565
  } else {
566
  alert(data.message);
567
  }
568
  })
569
  .catch(err => console.error('Error removing item:', err));
570
  }
571
+
572
  function addToCart(itemName, customerEmail) {
573
+ fetch(`${BASE_URL}/cart/add_item`, {
574
  method: "POST",
575
  headers: { "Content-Type": "application/json" },
576
  body: JSON.stringify({
577
  email: customerEmail,
578
+ item_name: itemName.trim(),
579
+ quantity: 1
580
+ }),
581
+ credentials: 'include'
582
  })
583
  .then(response => response.json())
584
  .then(data => {
585
  if (data.success) {
586
  alert("Item added/updated successfully.");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  location.reload();
588
  } else {
589
+ alert(data.error || "Failed to add item to cart.");
590
  }
591
  })
592
+ .catch(err => {
593
+ console.error("Error adding item to cart:", err);
594
+ alert("An error occurred while adding the item to the cart.");
595
+ });
596
  }
597
+
598
  function addToCartSuggestion(itemName, itemPrice, itemImage, itemId) {
599
+ const customerEmail = "{{ customer_email }}";
 
600
  const data = {
601
  item_name: itemName,
602
  item_price: itemPrice,
603
  item_image: itemImage,
604
  item_id: itemId,
605
+ addons: [],
606
+ instructions: "",
607
  customer_email: customerEmail
608
  };
609
+
610
+ fetch(`${BASE_URL}/cart/add_suggestion_to_cart`, {
611
  method: 'POST',
612
+ headers: { 'Content-Type': 'application/json' },
613
+ body: JSON.stringify(data),
614
+ credentials: 'include'
 
615
  })
616
  .then(response => response.json())
617
  .then(data => {
618
  if (data.success) {
619
  alert('Item added to cart!');
620
+ location.reload();
621
  } else {
622
  alert('Error adding item to cart: ' + data.error);
623
  }
624
  })
625
+ .catch(err => {
626
+ console.error('Error adding item:', err);
627
+ alert('An error occurred while adding the item to the cart.');
628
+ });
629
  }
 
 
 
630
 
631
+ // Initialize subtotal on page load
632
+ document.addEventListener('DOMContentLoaded', function() {
633
+ updateSubtotal();
634
+ });
635
+ </script>
636
  </body>
637
+ </html>