lokeshloki143 commited on
Commit
48794a2
·
verified ·
1 Parent(s): 9393216

Update templates/combined_summary.html

Browse files
Files changed (1) hide show
  1. templates/combined_summary.html +159 -62
templates/combined_summary.html CHANGED
@@ -4,10 +4,10 @@
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <meta http-equiv="x-ua-compatible" content="ie=edge">
7
- <title>Order Summary</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <style>
10
- /* Custom animations */
11
  @keyframes fadeIn {
12
  from { opacity: 0; transform: translateY(10px); }
13
  to { opacity: 1; transform: translateY(0); }
@@ -35,7 +35,6 @@
35
  .progress-bar {
36
  transition: width 0.6s ease-in-out, background 0.3s ease-in-out;
37
  }
38
- /* Progress bar color ranges */
39
  .progress-bar.range-0-100 {
40
  background: linear-gradient(90deg, #2DD4BF, #5EEAD4);
41
  }
@@ -66,7 +65,6 @@
66
  background: linear-gradient(45deg, transparent 0%, rgba(255, 255, 255, 0.3) 50%, transparent 100%);
67
  animation: shine 3s infinite;
68
  }
69
- /* Custom class for order items */
70
  .custom-class {
71
  text-align: center;
72
  border-radius: 12px;
@@ -86,13 +84,11 @@
86
  transform: translateY(-2px);
87
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
88
  }
89
- /* Order image wrapper for positioning text */
90
  .order-image-wrapper {
91
  position: relative;
92
  display: block;
93
  margin-bottom: 16px;
94
  }
95
- /* Order image styles */
96
  .order-image {
97
  max-width: 100%;
98
  max-height: 330px;
@@ -113,12 +109,10 @@
113
  transform: scale(1.04);
114
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
115
  }
116
- /* Fallback for placeholder images */
117
  .order-image[src$="placeholder.jpg"] {
118
  background: linear-gradient(135deg, #F9FAFB, #E5E7EB);
119
  object-fit: contain;
120
  }
121
- /* Item name below image */
122
  .order-item-name {
123
  display: block;
124
  text-align: center;
@@ -150,7 +144,6 @@
150
  border-radius: 8px;
151
  margin-bottom: 1rem;
152
  }
153
- /* Scrollable sector images */
154
  .sector-images-container {
155
  position: relative;
156
  display: flex;
@@ -217,7 +210,6 @@
217
  max-width: 150px;
218
  color: #1F2937;
219
  }
220
- /* Scroll buttons */
221
  .scroll-button {
222
  position: absolute;
223
  top: 50%;
@@ -250,7 +242,6 @@
250
  .scroll-button.right {
251
  right: 0;
252
  }
253
- /* Full-width gradient header */
254
  .back-to-menu {
255
  position: fixed;
256
  top: 0;
@@ -272,13 +263,11 @@
272
  background: linear-gradient(45deg, #FF8C61, #FF9E2C);
273
  transform: translateY(-1px);
274
  }
275
- /* Content spacing */
276
  .container {
277
  margin-top: 90px;
278
  max-width: 100%;
279
  padding: 20px;
280
  }
281
- /* Sector popup */
282
  #sector-popup {
283
  display: none;
284
  position: fixed;
@@ -350,7 +339,6 @@
350
  position: relative;
351
  z-index: 1;
352
  }
353
- /* Ingredient modal */
354
  .ingredient-modal-container {
355
  display: none;
356
  position: fixed;
@@ -380,7 +368,6 @@
380
  background: #F9FAFB;
381
  border-radius: 6px;
382
  }
383
- /* Ingredient images */
384
  .ingredient-image {
385
  max-width: 100%;
386
  max-height: 100px;
@@ -392,16 +379,13 @@
392
  border: 1px solid #D1D5DB;
393
  transition: transform 0.3s ease-in-out, border-color 0.3s ease-in-out;
394
  }
395
- /* Hover effect for ingredient buttons */
396
  .ingredient-button:hover .ingredient-image {
397
  transform: scale(1.1);
398
  border-color: #10B981;
399
  }
400
- /* Green border when section is visible */
401
  .ingredients-section:not(.hidden) .ingredient-image {
402
  border: 2px solid #10B981;
403
  }
404
- /* Ensure ingredient section is smooth */
405
  .ingredients-section {
406
  transition: opacity 0.3s ease-in-out, max-height 0.3s ease-in-out;
407
  max-height: 0;
@@ -412,11 +396,9 @@
412
  max-height: 1000px;
413
  opacity: 1;
414
  }
415
- /* Prevent body scroll when modal is open */
416
  body.modal-open {
417
  overflow: hidden;
418
  }
419
- /* Fallback messages */
420
  .no-data {
421
  text-align: center;
422
  color: #6B7280;
@@ -426,7 +408,6 @@
426
  border-radius: 8px;
427
  margin-bottom: 20px;
428
  }
429
- /* Order confirmed section */
430
  .order-confirmed {
431
  background: linear-gradient(135deg, #FFF7ED 0%, #FFE4D6 100%);
432
  position: relative;
@@ -450,7 +431,6 @@
450
  .order-confirmed.hidden {
451
  display: none;
452
  }
453
- /* Tier details animation */
454
  .tier-details {
455
  overflow: hidden;
456
  transition: max-height 0.5s ease-in-out, opacity 0.3s ease-in-out;
@@ -462,7 +442,6 @@
462
  opacity: 1;
463
  animation: slideDown 0.5s ease-in-out;
464
  }
465
- /* Price badge */
466
  .price-badge {
467
  display: inline-block;
468
  background: #FFE4D6;
@@ -471,12 +450,10 @@
471
  font-weight: 600;
472
  color: #C2410C;
473
  }
474
- /* Show Ingredients button focus style */
475
  .ingredients-toggle-button:focus {
476
  outline: none;
477
  transform: scale(1.05);
478
  }
479
- /* Timer styles */
480
  .countdown-timer {
481
  font-weight: 600;
482
  color: #C2410C;
@@ -485,6 +462,75 @@
485
  border-radius: 8px;
486
  display: inline-block;
487
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
  /* Responsive adjustments */
489
  @media (max-width: 768px) {
490
  .custom-class {
@@ -504,6 +550,13 @@
504
  .countdown-timer {
505
  font-size: 0.875rem;
506
  }
 
 
 
 
 
 
 
507
  }
508
  @media (max-width: 480px) {
509
  .custom-class {
@@ -515,6 +568,9 @@
515
  .order-item-name {
516
  font-size: 1.125rem;
517
  }
 
 
 
518
  }
519
  @media (max-width: 360px) {
520
  .custom-class {
@@ -605,7 +661,6 @@
605
 
606
  <div class="container mx-auto p-6 pt-2">
607
  <!-- Order Confirmation -->
608
- <!-- Hidden inputs for order ID and order count -->
609
  <input type="hidden" id="currentOrderId" value="{{ order_id | default('') }}">
610
  <input type="hidden" id="orderCount" value="{{ order_items | length }}">
611
 
@@ -634,14 +689,12 @@
634
  </svg>
635
  </div>
636
 
637
- <!-- Collapsible Content Section -->
638
  <div id="tierDetails" class="tier-details hidden">
639
  <div class="text-center mb-6">
640
  <p class="text-gray-600">Valid through December {{ validity_year }}</p>
641
  <p class="text-lg font-semibold mt-2 text-yellow-600" id="pointsDisplay">{{ user_points }} points</p>
642
  </div>
643
 
644
- <!-- Progress Bar -->
645
  <div class="relative h-4 bg-gray-200 rounded-full overflow-hidden mb-4">
646
  <div id="progressBar" class="absolute left-0 top-0 h-full progress-bar" style="width: {{ progress_percentage }}%"></div>
647
  </div>
@@ -657,7 +710,6 @@
657
  <span class="font-semibold text-orange-500" id="nextTier">{{ next_tier }}</span>
658
  </p>
659
 
660
- <!-- Tier Benefits -->
661
  <div class="mt-6 bg-gray-50 rounded-xl p-4">
662
  <h3 class="text-lg font-semibold mb-4 text-gray-800" id="benefitsTitle">
663
  Benefits of Reaching {{ next_tier }} Tier
@@ -856,10 +908,84 @@
856
  {% else %}
857
  <div class="no-data">No previous orders found.</div>
858
  {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
859
  </div>
860
 
861
  <script>
862
- // Debounce function for performance
863
  function debounce(func, wait) {
864
  let timeout;
865
  return function executedFunction(...args) {
@@ -872,7 +998,6 @@
872
  };
873
  }
874
 
875
- // Scroll container function
876
  function scrollContainer(direction) {
877
  try {
878
  const container = document.querySelector('.sector-images-container');
@@ -887,7 +1012,6 @@
887
  }
888
  }
889
 
890
- // Show sector description popup
891
  function showSectorDescription(description) {
892
  try {
893
  document.getElementById('sector-description').innerText = description || 'No description available.';
@@ -898,7 +1022,6 @@
898
  }
899
  }
900
 
901
- // Close sector popup
902
  function closePopup() {
903
  try {
904
  document.getElementById('sector-popup').style.display = 'none';
@@ -908,7 +1031,6 @@
908
  }
909
  }
910
 
911
- // Toggle tier details with animation
912
  function toggleTierDetails() {
913
  try {
914
  const tierDetails = document.getElementById('tierDetails');
@@ -923,7 +1045,6 @@
923
  }
924
  }
925
 
926
- // Toggle ingredients section
927
  function toggleIngredients(index) {
928
  try {
929
  const section = document.getElementById(`ingredientsSection${index}`);
@@ -936,7 +1057,6 @@
936
 
937
  const isHidden = section.classList.contains('hidden');
938
 
939
- // Close all other ingredient sections
940
  document.querySelectorAll('.ingredients-section').forEach(s => {
941
  s.classList.add('hidden');
942
  s.setAttribute('aria-hidden', 'true');
@@ -946,7 +1066,6 @@
946
  b.setAttribute('aria-expanded', 'false');
947
  });
948
 
949
- // Toggle the current section
950
  if (isHidden) {
951
  section.classList.remove('hidden');
952
  section.setAttribute('aria-hidden', 'false');
@@ -963,7 +1082,6 @@
963
  }
964
  }
965
 
966
- // Show ingredient details modal
967
  function showIngredientDetails(button) {
968
  try {
969
  const data = JSON.parse(button.getAttribute('data-ingredient'));
@@ -989,7 +1107,7 @@
989
  ? healthBenefitsList.map(item => `<li>${item.trim()}</li>`).join('')
990
  : '<li>No health benefits available.</li>';
991
  funFactsUl.innerHTML = funFactsList.length
992
- ? funfactsList.map(item => `<li>${item.trim()}</li>`).join('')
993
  : '<li>No fun facts available.</li>';
994
 
995
  modal.style.display = 'flex';
@@ -999,7 +1117,6 @@
999
  }
1000
  }
1001
 
1002
- // Close ingredient modal
1003
  function closeModal(index) {
1004
  try {
1005
  const modal = document.getElementById(`ingredientModal${index}`);
@@ -1012,78 +1129,63 @@
1012
  }
1013
  }
1014
 
1015
- // Timer logic
1016
  function initTimer() {
1017
  const orderId = document.getElementById('currentOrderId').value;
1018
  const orderCount = parseInt(document.getElementById('orderCount').value, 10) || 0;
1019
  const orderConfirmationSection = document.getElementById('orderConfirmationSection');
1020
  const countdownTimerSpan = document.getElementById('countdownTimer');
1021
 
1022
- // Determine timer duration based on order count
1023
- const timerDurationSeconds = orderCount >= 3 ? 45 * 60 : 15 * 60; // 45 min for 3+ orders, 15 min otherwise
1024
 
1025
- // Check if order is new and has a valid order ID
1026
  if (!orderId) {
1027
- // No valid order ID: hide confirmation section
1028
  orderConfirmationSection.classList.add('hidden');
1029
  return;
1030
  }
1031
 
1032
- // Check if order is already delivered
1033
  const deliveredOrders = JSON.parse(localStorage.getItem('deliveredOrders') || '[]');
1034
  if (deliveredOrders.includes(orderId)) {
1035
- // Order is delivered: show "Delivered!" message
1036
  orderConfirmationSection.classList.remove('hidden');
1037
  countdownTimerSpan.textContent = 'Delivered!';
1038
  return;
1039
  }
1040
 
1041
- // Check for existing timer in localStorage
1042
  let timerData = JSON.parse(localStorage.getItem('orderTimerData') || '{}');
1043
  let endTime = timerData[orderId] ? parseInt(timerData[orderId], 10) : null;
1044
 
1045
- // If no timer exists for this order, start a new one
1046
  if (!endTime) {
1047
  endTime = Date.now() + timerDurationSeconds * 1000;
1048
  timerData[orderId] = endTime;
1049
  localStorage.setItem('orderTimerData', JSON.stringify(timerData));
1050
  }
1051
 
1052
- // Update timer display
1053
  function updateTimer() {
1054
  const now = Date.now();
1055
  const timeLeftSeconds = Math.max(0, Math.floor((endTime - now) / 1000));
1056
 
1057
  if (timeLeftSeconds <= 0) {
1058
- // Timer expired: mark order as delivered and refresh page
1059
  deliveredOrders.push(orderId);
1060
  localStorage.setItem('deliveredOrders', JSON.stringify(deliveredOrders));
1061
  delete timerData[orderId];
1062
  localStorage.setItem('orderTimerData', JSON.stringify(timerData));
1063
  orderConfirmationSection.classList.remove('hidden');
1064
  countdownTimerSpan.textContent = 'Delivered!';
1065
- window.location.reload(); // Refresh page on timer expiry
1066
  return;
1067
  }
1068
 
1069
- // Format time as MM:SS
1070
  const minutes = Math.floor(timeLeftSeconds / 60);
1071
  const seconds = timeLeftSeconds % 60;
1072
  const paddedSeconds = seconds < 10 ? '0' + seconds : seconds;
1073
  countdownTimerSpan.textContent = `${minutes}m ${paddedSeconds}s`;
1074
 
1075
- // Show confirmation section
1076
  orderConfirmationSection.classList.remove('hidden');
1077
 
1078
- // Schedule next update
1079
  setTimeout(updateTimer, 1000);
1080
  }
1081
 
1082
- // Start timer
1083
  updateTimer();
1084
  }
1085
 
1086
- // Set progress bar color based on points and initialize timer
1087
  document.addEventListener('DOMContentLoaded', () => {
1088
  try {
1089
  const progressBar = document.getElementById('progressBar');
@@ -1098,13 +1200,11 @@
1098
  progressBar.classList.add('range-200-plus');
1099
  }
1100
 
1101
- // Initialize the timer
1102
  initTimer();
1103
  } catch (e) {
1104
  console.error('Error during DOMContentLoaded:', e);
1105
  }
1106
 
1107
- // Lazy load images with IntersectionObserver
1108
  const images = document.querySelectorAll('img.lazyload');
1109
  if ('IntersectionObserver' in window) {
1110
  const observer = new IntersectionObserver((entries, observer) => {
@@ -1126,7 +1226,6 @@
1126
  }
1127
  });
1128
 
1129
- // Close modals on outside click
1130
  document.addEventListener('click', (e) => {
1131
  try {
1132
  if (e.target.id === 'sector-popup') {
@@ -1143,7 +1242,6 @@
1143
  }
1144
  });
1145
 
1146
- // Keyboard navigation for scroll buttons
1147
  document.querySelectorAll('.scroll-button').forEach(button => {
1148
  button.addEventListener('keydown', function(e) {
1149
  if (e.key === 'Enter' || e.key === ' ') {
@@ -1153,7 +1251,6 @@
1153
  });
1154
  });
1155
 
1156
- // Keyboard navigation for toggle buttons
1157
  document.querySelectorAll('[id^="ingredientsToggleButton"]').forEach(button => {
1158
  button.addEventListener('keydown', (e) => {
1159
  if (e.key === 'Enter' || e.key === ' ') {
 
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <meta http-equiv="x-ua-compatible" content="ie=edge">
7
+ <title>Order Summary and Invoice</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <style>
10
+ /* Existing styles remain unchanged */
11
  @keyframes fadeIn {
12
  from { opacity: 0; transform: translateY(10px); }
13
  to { opacity: 1; transform: translateY(0); }
 
35
  .progress-bar {
36
  transition: width 0.6s ease-in-out, background 0.3s ease-in-out;
37
  }
 
38
  .progress-bar.range-0-100 {
39
  background: linear-gradient(90deg, #2DD4BF, #5EEAD4);
40
  }
 
65
  background: linear-gradient(45deg, transparent 0%, rgba(255, 255, 255, 0.3) 50%, transparent 100%);
66
  animation: shine 3s infinite;
67
  }
 
68
  .custom-class {
69
  text-align: center;
70
  border-radius: 12px;
 
84
  transform: translateY(-2px);
85
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
86
  }
 
87
  .order-image-wrapper {
88
  position: relative;
89
  display: block;
90
  margin-bottom: 16px;
91
  }
 
92
  .order-image {
93
  max-width: 100%;
94
  max-height: 330px;
 
109
  transform: scale(1.04);
110
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
111
  }
 
112
  .order-image[src$="placeholder.jpg"] {
113
  background: linear-gradient(135deg, #F9FAFB, #E5E7EB);
114
  object-fit: contain;
115
  }
 
116
  .order-item-name {
117
  display: block;
118
  text-align: center;
 
144
  border-radius: 8px;
145
  margin-bottom: 1rem;
146
  }
 
147
  .sector-images-container {
148
  position: relative;
149
  display: flex;
 
210
  max-width: 150px;
211
  color: #1F2937;
212
  }
 
213
  .scroll-button {
214
  position: absolute;
215
  top: 50%;
 
242
  .scroll-button.right {
243
  right: 0;
244
  }
 
245
  .back-to-menu {
246
  position: fixed;
247
  top: 0;
 
263
  background: linear-gradient(45deg, #FF8C61, #FF9E2C);
264
  transform: translateY(-1px);
265
  }
 
266
  .container {
267
  margin-top: 90px;
268
  max-width: 100%;
269
  padding: 20px;
270
  }
 
271
  #sector-popup {
272
  display: none;
273
  position: fixed;
 
339
  position: relative;
340
  z-index: 1;
341
  }
 
342
  .ingredient-modal-container {
343
  display: none;
344
  position: fixed;
 
368
  background: #F9FAFB;
369
  border-radius: 6px;
370
  }
 
371
  .ingredient-image {
372
  max-width: 100%;
373
  max-height: 100px;
 
379
  border: 1px solid #D1D5DB;
380
  transition: transform 0.3s ease-in-out, border-color 0.3s ease-in-out;
381
  }
 
382
  .ingredient-button:hover .ingredient-image {
383
  transform: scale(1.1);
384
  border-color: #10B981;
385
  }
 
386
  .ingredients-section:not(.hidden) .ingredient-image {
387
  border: 2px solid #10B981;
388
  }
 
389
  .ingredients-section {
390
  transition: opacity 0.3s ease-in-out, max-height 0.3s ease-in-out;
391
  max-height: 0;
 
396
  max-height: 1000px;
397
  opacity: 1;
398
  }
 
399
  body.modal-open {
400
  overflow: hidden;
401
  }
 
402
  .no-data {
403
  text-align: center;
404
  color: #6B7280;
 
408
  border-radius: 8px;
409
  margin-bottom: 20px;
410
  }
 
411
  .order-confirmed {
412
  background: linear-gradient(135deg, #FFF7ED 0%, #FFE4D6 100%);
413
  position: relative;
 
431
  .order-confirmed.hidden {
432
  display: none;
433
  }
 
434
  .tier-details {
435
  overflow: hidden;
436
  transition: max-height 0.5s ease-in-out, opacity 0.3s ease-in-out;
 
442
  opacity: 1;
443
  animation: slideDown 0.5s ease-in-out;
444
  }
 
445
  .price-badge {
446
  display: inline-block;
447
  background: #FFE4D6;
 
450
  font-weight: 600;
451
  color: #C2410C;
452
  }
 
453
  .ingredients-toggle-button:focus {
454
  outline: none;
455
  transform: scale(1.05);
456
  }
 
457
  .countdown-timer {
458
  font-weight: 600;
459
  color: #C2410C;
 
462
  border-radius: 8px;
463
  display: inline-block;
464
  }
465
+ /* New Invoice Section Styles */
466
+ .invoice-section {
467
+ background: #FFFFFF;
468
+ border-radius: 12px;
469
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
470
+ padding: 24px;
471
+ margin-bottom: 24px;
472
+ max-width: 800px;
473
+ margin-left: auto;
474
+ margin-right: auto;
475
+ }
476
+ .invoice-header {
477
+ text-align: center;
478
+ margin-bottom: 24px;
479
+ }
480
+ .invoice-header h1 {
481
+ font-size: 1.75rem;
482
+ font-weight: 700;
483
+ color: #1F2937;
484
+ }
485
+ .invoice-header p {
486
+ color: #6B7280;
487
+ font-size: 0.875rem;
488
+ }
489
+ .invoice-details {
490
+ display: grid;
491
+ grid-template-columns: repeat(2, 1fr);
492
+ gap: 16px;
493
+ margin-bottom: 24px;
494
+ }
495
+ .invoice-details p {
496
+ font-size: 0.875rem;
497
+ color: #1F2937;
498
+ }
499
+ .invoice-details p span {
500
+ font-weight: 600;
501
+ }
502
+ .invoice-table {
503
+ width: 100%;
504
+ border-collapse: collapse;
505
+ margin-bottom: 24px;
506
+ }
507
+ .invoice-table th, .invoice-table td {
508
+ border: 1px solid #E5E7EB;
509
+ padding: 8px;
510
+ text-align: left;
511
+ font-size: 0.875rem;
512
+ }
513
+ .invoice-table th {
514
+ background: #F9FAFB;
515
+ font-weight: 600;
516
+ color: #1F2937;
517
+ }
518
+ .invoice-table td {
519
+ color: #1F2937;
520
+ }
521
+ .invoice-table .total-row {
522
+ font-weight: 600;
523
+ background: #FFF7ED;
524
+ }
525
+ .invoice-footer {
526
+ text-align: center;
527
+ color: #6B7280;
528
+ font-size: 0.875rem;
529
+ margin-top: 16px;
530
+ }
531
+ .invoice-footer p {
532
+ margin: 4px 0;
533
+ }
534
  /* Responsive adjustments */
535
  @media (max-width: 768px) {
536
  .custom-class {
 
550
  .countdown-timer {
551
  font-size: 0.875rem;
552
  }
553
+ .invoice-details {
554
+ grid-template-columns: 1fr;
555
+ }
556
+ .invoice-table th, .invoice-table td {
557
+ font-size: 0.75rem;
558
+ padding: 6px;
559
+ }
560
  }
561
  @media (max-width: 480px) {
562
  .custom-class {
 
568
  .order-item-name {
569
  font-size: 1.125rem;
570
  }
571
+ .invoice-section {
572
+ padding: 16px;
573
+ }
574
  }
575
  @media (max-width: 360px) {
576
  .custom-class {
 
661
 
662
  <div class="container mx-auto p-6 pt-2">
663
  <!-- Order Confirmation -->
 
664
  <input type="hidden" id="currentOrderId" value="{{ order_id | default('') }}">
665
  <input type="hidden" id="orderCount" value="{{ order_items | length }}">
666
 
 
689
  </svg>
690
  </div>
691
 
 
692
  <div id="tierDetails" class="tier-details hidden">
693
  <div class="text-center mb-6">
694
  <p class="text-gray-600">Valid through December {{ validity_year }}</p>
695
  <p class="text-lg font-semibold mt-2 text-yellow-600" id="pointsDisplay">{{ user_points }} points</p>
696
  </div>
697
 
 
698
  <div class="relative h-4 bg-gray-200 rounded-full overflow-hidden mb-4">
699
  <div id="progressBar" class="absolute left-0 top-0 h-full progress-bar" style="width: {{ progress_percentage }}%"></div>
700
  </div>
 
710
  <span class="font-semibold text-orange-500" id="nextTier">{{ next_tier }}</span>
711
  </p>
712
 
 
713
  <div class="mt-6 bg-gray-50 rounded-xl p-4">
714
  <h3 class="text-lg font-semibold mb-4 text-gray-800" id="benefitsTitle">
715
  Benefits of Reaching {{ next_tier }} Tier
 
908
  {% else %}
909
  <div class="no-data">No previous orders found.</div>
910
  {% endif %}
911
+
912
+ <!-- Invoice Section -->
913
+ <div class="invoice-section">
914
+ <div class="invoice-header">
915
+ <h1>Tax Invoice</h1>
916
+ <p>ORIGINAL FOR RECIPIENT</p>
917
+ </div>
918
+ <div class="invoice-details">
919
+ <div>
920
+ <p><span>Legal Entity Name:</span> {{ restaurant.legal_name | default('DOUBLE TREE BY KVP HOSPITALITY LLP') }}</p>
921
+ <p><span>Restaurant Name:</span> {{ restaurant.name | default('Pista House') }}</p>
922
+ <p><span>Restaurant Address:</span> {{ restaurant.address | default('52 To 57, 69 & 70, 5-5-162 & 5-5-163, 5-5-164 & 5-5-165, Plot 1, Vanasthali Hills, Saheb Nagar, LB Nagar Circle 4, Vanasthalipuram, Hyderabad') }}</p>
923
+ <p><span>GSTIN:</span> {{ restaurant.gstin | default('36AATFD1209K1Z9') }}</p>
924
+ <p><span>FSSAI:</span> {{ restaurant.fssai | default('13622012000022') }}</p>
925
+ </div>
926
+ <div>
927
+ <p><span>Invoice No:</span> {{ order.id | default('247JD92F00043965') }}</p>
928
+ <p><span>Invoice Date:</span> {{ order.created_date | default('2024-12-12') }}</p>
929
+ <p><span>Customer Name:</span> {{ order.customer_name | default('SATHVIK GANTA') }}</p>
930
+ <p><span>Delivery Address:</span> {{ order.delivery_address | default('Plot no -80, Road no-4, Sharadha Nagar, Vanasthalipuram, 500070') }}</p>
931
+ <p><span>Place of Supply:</span> {{ order.place_of_supply | default('Telangana(36)') }}</p>
932
+ </div>
933
+ </div>
934
+ <table class="invoice-table">
935
+ <thead>
936
+ <tr>
937
+ <th>Particulars</th>
938
+ <th>Gross Value</th>
939
+ <th>Discount</th>
940
+ <th>Net Value</th>
941
+ <th>CGST (Rate)</th>
942
+ <th>CGST (INR)</th>
943
+ <th>SGST (Rate)</th>
944
+ <th>SGST (INR)</th>
945
+ <th>Total</th>
946
+ </tr>
947
+ </thead>
948
+ <tbody>
949
+ {% for item in order_items %}
950
+ <tr>
951
+ <td>{{ item.name | escape }}</td>
952
+ <td>{{ "%.2f"|format(item.price | default(0)) }}</td>
953
+ <td>{{ "%.2f"|format(item.discount | default(0)) }}</td>
954
+ <td>{{ "%.2f"|format((item.price | default(0)) - (item.discount | default(0))) }}</td>
955
+ <td>{{ order.cgst_rate | default('2.5%') }}</td>
956
+ <td>{{ "%.3f"|format(((item.price | default(0)) - (item.discount | default(0))) * (order.cgst_rate_float | default(0.025))) }}</td>
957
+ <td>{{ order.sgst_rate | default('2.5%') }}</td>
958
+ <td>{{ "%.3f"|format(((item.price | default(0)) - (item.discount | default(0))) * (order.sgst_rate_float | default(0.025))) }}</td>
959
+ <td>{{ "%.2f"|format(((item.price | default(0)) - (item.discount | default(0))) * (1 + (order.cgst_rate_float | default(0.025)) + (order.sgst_rate_float | default(0.025)))) }}</td>
960
+ </tr>
961
+ {% endfor %}
962
+ <tr class="total-row">
963
+ <td>Total</td>
964
+ <td>{{ "%.2f"|format(total_gross_value) }}</td>
965
+ <td>{{ "%.2f"|format(total_discount) }}</td>
966
+ <td>{{ "%.2f"|format(total_net_value) }}</td>
967
+ <td></td>
968
+ <td>{{ "%.3f"|format(total_cgst) }}</td>
969
+ <td></td>
970
+ <td>{{ "%.3f"|format(total_sgst) }}</td>
971
+ <td>{{ "%.2f"|format(total_amount) }}</td>
972
+ </tr>
973
+ </tbody>
974
+ </table>
975
+ <div class="invoice-footer">
976
+ <p>Amount (in words): {{ total_amount_in_words | default('Three Hundred Eighty Seven Rupees And Forty Five Paisa Only') }}</p>
977
+ <p>Payment Mode: {{ order.payment_mode | default('Digital') }}</p>
978
+ <p>Order ID: {{ order.id | default('6428970359') }}</p>
979
+ <p>Order Date: {{ order.created_date | default('2024-12-12') }}</p>
980
+ <p>Supply attracts reverse charge: {{ order.reverse_charge | default('No') }}</p>
981
+ <p>For {{ restaurant.legal_name | default('ZOMATO LIMITED') }}</p>
982
+ <p>Authorized Signatory</p>
983
+ </div>
984
+ </div>
985
  </div>
986
 
987
  <script>
988
+ // Existing JavaScript remains unchanged
989
  function debounce(func, wait) {
990
  let timeout;
991
  return function executedFunction(...args) {
 
998
  };
999
  }
1000
 
 
1001
  function scrollContainer(direction) {
1002
  try {
1003
  const container = document.querySelector('.sector-images-container');
 
1012
  }
1013
  }
1014
 
 
1015
  function showSectorDescription(description) {
1016
  try {
1017
  document.getElementById('sector-description').innerText = description || 'No description available.';
 
1022
  }
1023
  }
1024
 
 
1025
  function closePopup() {
1026
  try {
1027
  document.getElementById('sector-popup').style.display = 'none';
 
1031
  }
1032
  }
1033
 
 
1034
  function toggleTierDetails() {
1035
  try {
1036
  const tierDetails = document.getElementById('tierDetails');
 
1045
  }
1046
  }
1047
 
 
1048
  function toggleIngredients(index) {
1049
  try {
1050
  const section = document.getElementById(`ingredientsSection${index}`);
 
1057
 
1058
  const isHidden = section.classList.contains('hidden');
1059
 
 
1060
  document.querySelectorAll('.ingredients-section').forEach(s => {
1061
  s.classList.add('hidden');
1062
  s.setAttribute('aria-hidden', 'true');
 
1066
  b.setAttribute('aria-expanded', 'false');
1067
  });
1068
 
 
1069
  if (isHidden) {
1070
  section.classList.remove('hidden');
1071
  section.setAttribute('aria-hidden', 'false');
 
1082
  }
1083
  }
1084
 
 
1085
  function showIngredientDetails(button) {
1086
  try {
1087
  const data = JSON.parse(button.getAttribute('data-ingredient'));
 
1107
  ? healthBenefitsList.map(item => `<li>${item.trim()}</li>`).join('')
1108
  : '<li>No health benefits available.</li>';
1109
  funFactsUl.innerHTML = funFactsList.length
1110
+ ? funFactsList.map(item => `<li>${item.trim()}</li>`).join('')
1111
  : '<li>No fun facts available.</li>';
1112
 
1113
  modal.style.display = 'flex';
 
1117
  }
1118
  }
1119
 
 
1120
  function closeModal(index) {
1121
  try {
1122
  const modal = document.getElementById(`ingredientModal${index}`);
 
1129
  }
1130
  }
1131
 
 
1132
  function initTimer() {
1133
  const orderId = document.getElementById('currentOrderId').value;
1134
  const orderCount = parseInt(document.getElementById('orderCount').value, 10) || 0;
1135
  const orderConfirmationSection = document.getElementById('orderConfirmationSection');
1136
  const countdownTimerSpan = document.getElementById('countdownTimer');
1137
 
1138
+ const timerDurationSeconds = orderCount >= 3 ? 45 * 60 : 15 * 60;
 
1139
 
 
1140
  if (!orderId) {
 
1141
  orderConfirmationSection.classList.add('hidden');
1142
  return;
1143
  }
1144
 
 
1145
  const deliveredOrders = JSON.parse(localStorage.getItem('deliveredOrders') || '[]');
1146
  if (deliveredOrders.includes(orderId)) {
 
1147
  orderConfirmationSection.classList.remove('hidden');
1148
  countdownTimerSpan.textContent = 'Delivered!';
1149
  return;
1150
  }
1151
 
 
1152
  let timerData = JSON.parse(localStorage.getItem('orderTimerData') || '{}');
1153
  let endTime = timerData[orderId] ? parseInt(timerData[orderId], 10) : null;
1154
 
 
1155
  if (!endTime) {
1156
  endTime = Date.now() + timerDurationSeconds * 1000;
1157
  timerData[orderId] = endTime;
1158
  localStorage.setItem('orderTimerData', JSON.stringify(timerData));
1159
  }
1160
 
 
1161
  function updateTimer() {
1162
  const now = Date.now();
1163
  const timeLeftSeconds = Math.max(0, Math.floor((endTime - now) / 1000));
1164
 
1165
  if (timeLeftSeconds <= 0) {
 
1166
  deliveredOrders.push(orderId);
1167
  localStorage.setItem('deliveredOrders', JSON.stringify(deliveredOrders));
1168
  delete timerData[orderId];
1169
  localStorage.setItem('orderTimerData', JSON.stringify(timerData));
1170
  orderConfirmationSection.classList.remove('hidden');
1171
  countdownTimerSpan.textContent = 'Delivered!';
1172
+ window.location.reload();
1173
  return;
1174
  }
1175
 
 
1176
  const minutes = Math.floor(timeLeftSeconds / 60);
1177
  const seconds = timeLeftSeconds % 60;
1178
  const paddedSeconds = seconds < 10 ? '0' + seconds : seconds;
1179
  countdownTimerSpan.textContent = `${minutes}m ${paddedSeconds}s`;
1180
 
 
1181
  orderConfirmationSection.classList.remove('hidden');
1182
 
 
1183
  setTimeout(updateTimer, 1000);
1184
  }
1185
 
 
1186
  updateTimer();
1187
  }
1188
 
 
1189
  document.addEventListener('DOMContentLoaded', () => {
1190
  try {
1191
  const progressBar = document.getElementById('progressBar');
 
1200
  progressBar.classList.add('range-200-plus');
1201
  }
1202
 
 
1203
  initTimer();
1204
  } catch (e) {
1205
  console.error('Error during DOMContentLoaded:', e);
1206
  }
1207
 
 
1208
  const images = document.querySelectorAll('img.lazyload');
1209
  if ('IntersectionObserver' in window) {
1210
  const observer = new IntersectionObserver((entries, observer) => {
 
1226
  }
1227
  });
1228
 
 
1229
  document.addEventListener('click', (e) => {
1230
  try {
1231
  if (e.target.id === 'sector-popup') {
 
1242
  }
1243
  });
1244
 
 
1245
  document.querySelectorAll('.scroll-button').forEach(button => {
1246
  button.addEventListener('keydown', function(e) {
1247
  if (e.key === 'Enter' || e.key === ' ') {
 
1251
  });
1252
  });
1253
 
 
1254
  document.querySelectorAll('[id^="ingredientsToggleButton"]').forEach(button => {
1255
  button.addEventListener('keydown', (e) => {
1256
  if (e.key === 'Enter' || e.key === ' ') {