lokeshloki143 commited on
Commit
aa19fd3
·
verified ·
1 Parent(s): 6d180ea

Update templates/combined_summary.html

Browse files
Files changed (1) hide show
  1. templates/combined_summary.html +1054 -247
templates/combined_summary.html CHANGED
@@ -1,266 +1,1073 @@
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>User Profile</title>
7
- <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
8
- <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet"/>
9
- <style>
10
- body {
11
- background-color: #FDF4E3;
12
- margin: 0;
13
- padding: 0;
14
- position: relative;
15
- min-height: 100vh;
16
- }
17
- /* Top orange bar */
18
- .top-bar {
19
- background-color: #FF6F3C;
20
- width: 100%;
21
- padding: 10px 15px;
22
- display: flex;
23
- align-items: center;
24
- box-sizing: border-box;
25
- }
26
- .back-link {
27
- display: flex;
28
- align-items: center;
29
- text-decoration: none;
30
- }
31
- .back-arrow {
32
- font-size: 1.8rem;
33
- color: #000; /* Dark black */
34
- font-weight: bold;
35
- }
36
- .back-label {
37
- margin-left: 10px;
38
- color: white;
39
- font-weight: bold;
40
- font-size: 1rem;
41
- }
42
- h1 {
43
- color: #1C1C1C;
44
- font-size: 1.2rem;
45
- margin: 30px 0 15px; /* Default margin for larger screens */
46
- text-align: center;
47
- }
48
- /* For mobile view */
49
- @media (max-width: 576px) {
50
- h1 {
51
- margin-top: 2px; /* Reduced top margin for mobile */
52
- }
53
- }
54
- .form-control {
55
- border: 1px solid #333;
56
- color: #808080;
57
- background-color: #F9F9F9;
58
- }
59
- #referralCode, #rewardPoints {
60
- color: #000 !important;
61
- }
62
- .form-label {
63
- color: #000 !important;
64
- font-size: 0.8rem;
65
- }
66
- input.form-control[readonly], textarea.form-control[readonly] {
67
- color: #808080;
68
- background-color: #F9F9F9 !important;
69
- }
70
- input.form-control.editable, textarea.form-control.editable {
71
- background-color: #FFF8E1 !important;
72
- color: #000 !important;
73
- }
74
- .input-group {
75
- position: relative;
76
- }
77
- .pen-icon {
78
- position: absolute;
79
- right: 5px;
80
- top: 50%;
81
- transform: translateY(-50%);
82
- cursor: pointer;
83
- font-size: 1.2rem;
84
- color: black;
85
- }
86
- .pen-icon.editing {
87
- color: #333;
88
- }
89
- .button-container {
90
- display: flex;
91
- flex-direction: column;
92
- margin-top: 10px;
93
- }
94
- /* Updated label button style */
95
- .orange-label {
96
- background-color: #ffffff;
97
- color: white;
98
- padding: 8px 16px;
99
- border-radius: 5px;
100
- font-weight: bold;
101
- text-align: center;
102
- margin-top: 20px;
103
- width: 100%; /* Ensure the label is full width */
104
- position: absolute;
105
- bottom: 0;
106
- }
107
- .update-btn {
108
- background-color: #0FAA39; /* Green button */
109
- color: white;
110
- border: none;
111
- border-radius: 5px;
112
- padding: 5px 12px;
113
- font-size: 0.8rem;
114
- font-weight: bold;
115
- width: 60%; /* Full width inside orange label */
116
- }
117
- .update-btn:hover {
118
- background-color: #0f8e29;
119
- }
120
- @media (max-width: 576px) {
121
- .container {
122
- padding: 10px;
123
- }
124
- .update-btn {
125
- width: 100%;
126
- }
127
- .form-label {
128
- font-size: 0.75rem;
129
- }
130
- .form-control {
131
- font-size: 0.8rem;
132
- }
133
- }
134
- </style>
135
-
136
- <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
137
- <script>
138
- function toggleEditableField(fieldId, penIcon) {
139
- var input = document.getElementById(fieldId);
140
- var icon = document.getElementById(penIcon);
141
- if (input.hasAttribute('readonly')) {
142
- input.removeAttribute('readonly');
143
- input.classList.add('editable');
144
- icon.classList.add('editing');
145
- } else {
146
- input.setAttribute('readonly', true);
147
- input.classList.remove('editable');
148
- icon.classList.remove('editing');
149
- }
150
- }
151
- function updateProfile(event) {
152
- event.preventDefault();
153
- var formData = $('#profileForm').serialize();
154
- $.ajax({
155
- type: "POST",
156
- url: "/update_profile", // Update this URL with your back-end processing URL
157
- data: formData,
158
- success: function(response) {
159
- if (response.status === "success") {
160
- alert(response.message);
161
- location.reload();
162
- } else {
163
- alert(response.message);
164
- }
165
- },
166
- error: function() {
167
- alert("An error occurred while updating the profile.");
168
- }
169
- });
170
- }
171
- function copyReferralCode() {
172
- var referralInput = document.getElementById("referralCode");
173
- referralInput.select();
174
- referralInput.setSelectionRange(0, 99999);
175
- document.execCommand("copy");
176
- alert("Referral code copied: " + referralInput.value);
177
- }
178
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  </head>
 
 
 
 
 
 
 
180
 
181
- <body>
 
 
 
 
 
182
 
183
- <!-- Top Orange Label Bar -->
184
- <div class="top-bar">
185
- <a href="/menu" class="back-link">
186
- <span class="back-arrow">&#10216;</span>
187
- <span class="back-label">Back to Menu</span>
188
- </a>
189
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- <!-- Main Container -->
192
- <div class="container mt-4">
193
- <h1>User Profile</h1>
 
 
 
194
 
195
- {% with messages = get_flashed_messages(with_categories=true) %}
196
- {% if messages %}
197
- <div class="alert alert-{{ messages[0][0] }}">
198
- {{ messages[0][1] }}
199
- </div>
200
- {% endif %}
201
- {% endwith %}
202
-
203
- <div class="card">
204
- <div class="card-body">
205
- <form id="profileForm" method="POST" onsubmit="updateProfile(event)">
206
- <!-- Name -->
207
- <div class="mb-3">
208
- <label for="customerName" class="form-label"><strong>Name:</strong></label>
209
- <div class="input-group">
210
- <input type="text" id="customerName" name="customerName" class="form-control" value="{{ customer['name'] }}" readonly>
211
- <span id="pen-icon-customerName" class="pen-icon" onclick="toggleEditableField('customerName', 'pen-icon-customerName')">
212
- <i class="fas fa-pen"></i>
213
- </span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  </div>
215
- </div>
216
-
217
- <!-- Email -->
218
- <div class="mb-3">
219
- <label for="email" class="form-label"><strong>Email:</strong></label>
220
- <div class="input-group">
221
- <input type="email" id="email" name="email" class="form-control" value="{{ customer['email'] }}" readonly>
222
- <span id="pen-icon-email" class="pen-icon" onclick="toggleEditableField('email', 'pen-icon-email')">
223
- <i class="fas fa-pen"></i>
224
- </span>
 
 
 
 
 
 
 
 
 
225
  </div>
226
- </div>
227
-
228
- <!-- Phone -->
229
- <div class="mb-3">
230
- <label for="phone" class="form-label"><strong>Phone:</strong></label>
231
- <div class="input-group">
232
- <input type="text" id="phone" name="phone" class="form-control" value="{{ customer['phone'] }}" readonly>
233
- <span id="pen-icon-phone" class="pen-icon" onclick="toggleEditableField('phone', 'pen-icon-phone')">
234
- <i class="fas fa-pen"></i>
235
- </span>
 
 
 
 
 
 
 
 
 
 
236
  </div>
237
- </div>
238
-
239
- <!-- Referral Code -->
240
- <div class="mb-3">
241
- <label for="referralCode" class="form-label"><strong>Referral Code:</strong></label>
242
- <div class="input-group">
243
- <input type="text" id="referralCode" name="referralCode" class="form-control" value="{{ customer['referral_code'] }}" readonly>
244
- <button type="button" class="copy-btn" onclick="copyReferralCode()">📋</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  </div>
246
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
- <!-- Reward Points -->
249
- <div class="mb-3">
250
- <label for="rewardPoints" class="form-label"><strong>Reward Points:</strong></label>
251
- <input type="text" id="rewardPoints" name="rewardPoints" class="form-control" value="{{ customer['reward_points'] }}" readonly>
252
- </div>
 
 
 
 
 
253
 
254
- </form>
255
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  </div>
257
 
258
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
- <!-- Orange Label with Update Profile Button at the Bottom -->
261
- <div class="orange-label">
262
- <button type="submit" class="update-btn" form="profileForm">Update Profile</button>
263
- </div>
 
 
 
 
 
264
 
 
 
 
 
 
 
 
 
 
 
 
265
  </body>
266
- </html>
 
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
+ <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); }
14
+ }
15
+ @keyframes lightMoveUp {
16
+ 0% { background-position: 0 100%; }
17
+ 100% { background-position: 0 0%; }
18
+ }
19
+ @keyframes shine {
20
+ from { transform: rotate(0deg) translateX(-100%); }
21
+ to { transform: rotate(25deg) translateX(100%); }
22
+ }
23
+ @keyframes pulse {
24
+ 0% { box-shadow: 0 0 0 0 rgba(255, 179, 71, 0.7); }
25
+ 70% { box-shadow: 0 0 0 10px rgba(255, 179, 71, 0); }
26
+ 100% { box-shadow: 0 0 0 0 rgba(255, 179, 71, 0); }
27
+ }
28
+ @keyframes slideDown {
29
+ from { max-height: 0; opacity: 0; }
30
+ to { max-height: 1000px; opacity: 1; }
31
+ }
32
+ .modal, .popup {
33
+ animation: fadeIn 0.3s ease-in-out;
34
+ }
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
+ }
42
+ .progress-bar.range-100-200 {
43
+ background: linear-gradient(90deg, #10B981, #34D399);
44
+ }
45
+ .progress-bar.range-200-plus {
46
+ background: linear-gradient(90deg, #F59E0B, #FBBF24);
47
+ }
48
+ .ingredient-button:hover .ingredient-image {
49
+ transform: scale(1.1);
50
+ border-color: #10B981;
51
+ }
52
+ .tier-badge {
53
+ position: relative;
54
+ overflow: hidden;
55
+ background-color: #FFB347;
56
+ animation: pulse 2s infinite;
57
+ will-change: box-shadow;
58
+ }
59
+ .tier-badge::after {
60
+ content: '';
61
+ position: absolute;
62
+ top: -50%;
63
+ left: -50%;
64
+ width: 200%;
65
+ height: 200%;
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;
73
+ border-width: 1px;
74
+ border-color: #E5E7EB;
75
+ padding: 24px !important;
76
+ margin-bottom: 16px;
77
+ background-color: #FFFFFF;
78
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
79
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
80
+ width: 100%;
81
+ max-width: clamp(288px, 100%, 488px);
82
+ margin-left: auto;
83
+ margin-right: auto;
84
+ }
85
+ .custom-class:hover {
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;
99
+ width: auto;
100
+ height: auto;
101
+ aspect-ratio: 4/3;
102
+ object-fit: contain;
103
+ border-radius: 10px;
104
+ border: 3px solid #D1D5DB;
105
+ box-sizing: border-box;
106
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
107
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
108
+ will-change: transform, box-shadow;
109
+ display: block;
110
+ margin: 0 auto 20px;
111
+ }
112
+ .order-image:hover {
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;
125
+ color: #000000;
126
+ font-size: 1.5rem;
127
+ font-weight: 600;
128
+ margin-top: 12px;
129
+ padding: 8px 16px;
130
+ background: #FFFFFF;
131
+ border-radius: 8px;
132
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
133
+ white-space: nowrap;
134
+ overflow: hidden;
135
+ text-overflow: ellipsis;
136
+ max-width: 100%;
137
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
138
+ }
139
+ .order-image-wrapper:hover .order-item-name {
140
+ transform: translateY(-2px);
141
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
142
+ }
143
+ .history {
144
+ display: flex;
145
+ justify-content: center;
146
+ font-size: 1.75rem;
147
+ font-weight: 700;
148
+ padding: 1.5rem;
149
+ background: linear-gradient(45deg, #FFF7ED, #FFE4D6);
150
+ border-radius: 8px;
151
+ margin-bottom: 1rem;
152
+ }
153
+ /* Scrollable sector images */
154
+ .sector-images-container {
155
+ position: relative;
156
+ display: flex;
157
+ flex-wrap: nowrap;
158
+ overflow-x: auto;
159
+ overflow-y: hidden;
160
+ padding: 0 10px;
161
+ gap: 20px;
162
+ width: 100%;
163
+ max-width: none;
164
+ scroll-behavior: smooth;
165
+ scrollbar-width: thin;
166
+ scrollbar-color: #FFB347 #E5E7EB;
167
+ }
168
+ .sector-images-container::-webkit-scrollbar {
169
+ height: 8px;
170
+ }
171
+ .sector-images-container::-webkit-scrollbar-track {
172
+ background: #E5E7EB;
173
+ }
174
+ .sector-images-container::-webkit-scrollbar-thumb {
175
+ background: #FFB347;
176
+ border-radius: 4px;
177
+ }
178
+ .sector-item {
179
+ display: flex;
180
+ flex-direction: column;
181
+ align-items: center;
182
+ margin: 0 auto;
183
+ flex-shrink: 0;
184
+ background: #FFF7ED;
185
+ border-radius: 8px;
186
+ padding: 8px;
187
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
188
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
189
+ }
190
+ .sector-item:hover {
191
+ transform: translateY(-2px);
192
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
193
+ }
194
+ .sector-image {
195
+ max-width: 150px;
196
+ max-height: 100px;
197
+ width: auto;
198
+ height: auto;
199
+ aspect-ratio: 3/2;
200
+ object-fit: contain;
201
+ cursor: pointer;
202
+ border-radius: 8px;
203
+ border: 1px solid #D1D5DB;
204
+ box-sizing: border-box;
205
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
206
+ transition: transform 0.15s ease-in-out;
207
+ will-change: transform;
208
+ }
209
+ .sector-image:hover {
210
+ transform: scale(1.08);
211
+ }
212
+ .sector-name {
213
+ text-align: center;
214
+ font-size: 0.75rem;
215
+ font-weight: 600;
216
+ margin-top: 6px;
217
+ max-width: 150px;
218
+ color: #1F2937;
219
+ }
220
+ /* Scroll buttons */
221
+ .scroll-button {
222
+ position: absolute;
223
+ top: 50%;
224
+ transform: translateY(-50%);
225
+ background: #FFB347;
226
+ color: #FFFFFF;
227
+ width: 40px;
228
+ height: 40px;
229
+ border-radius: 50%;
230
+ display: flex;
231
+ align-items: center;
232
+ justify-content: center;
233
+ font-size: 20px;
234
+ cursor: pointer;
235
+ opacity: 0;
236
+ transition: opacity 0.3s ease-in-out, transform 0.2s ease-in-out;
237
+ z-index: 10;
238
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
239
+ }
240
+ .scroll-button:hover {
241
+ background: #FF9E2C;
242
+ transform: translateY(-50%) scale(1.1);
243
+ }
244
+ .sector-images-container:hover .scroll-button {
245
+ opacity: 1;
246
+ }
247
+ .scroll-button.left {
248
+ left: 0;
249
+ }
250
+ .scroll-button.right {
251
+ right: 0;
252
+ }
253
+ /* Full-width gradient header */
254
+ .back-to-menu {
255
+ position: fixed;
256
+ top: 0;
257
+ left: 0;
258
+ right: 0;
259
+ display: flex;
260
+ align-items: center;
261
+ padding: 14px 24px;
262
+ background: linear-gradient(45deg, #FFA07A, #FFB347);
263
+ color: #FFFFFF;
264
+ font-size: 1.125rem;
265
+ font-weight: 600;
266
+ text-decoration: none;
267
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
268
+ z-index: 9999;
269
+ transition: background-color 0.3s ease, transform 0.2s ease;
270
+ }
271
+ .back-to-menu:hover {
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;
285
+ inset: 0;
286
+ background: rgba(17, 24, 39, 0.6);
287
+ justify-content: center;
288
+ align-items: center;
289
+ z-index: 10000;
290
+ animation: fadeIn 0.3s ease-in-out;
291
+ }
292
+ #popup-content {
293
+ background: linear-gradient(135deg, #FFFFFF 0%, #F9FAFB 100%);
294
+ padding: 24px;
295
+ border-radius: 12px;
296
+ width: 90%;
297
+ max-width: 550px;
298
+ max-height: 85vh;
299
+ overflow-y: auto;
300
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
301
+ border: 1px solid #E5E7EB;
302
+ position: relative;
303
+ contain: layout;
304
+ }
305
+ .popup-header {
306
+ position: relative;
307
+ padding-bottom: 12px;
308
+ margin-bottom: 16px;
309
+ border-bottom: 2px solid #FFB347;
310
+ display: flex;
311
+ justify-content: space-between;
312
+ align-items: center;
313
+ }
314
+ .popup-close {
315
+ background: #FFB347;
316
+ color: #FFFFFF;
317
+ border-radius: 50%;
318
+ width: 40px;
319
+ height: 40px;
320
+ display: flex;
321
+ align-items: center;
322
+ justify-content: center;
323
+ font-size: 24px;
324
+ font-weight: bold;
325
+ border: none;
326
+ cursor: pointer;
327
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
328
+ line-height: 1;
329
+ padding: 0;
330
+ position: relative;
331
+ overflow: hidden;
332
+ will-change: transform, background;
333
+ }
334
+ .popup-close::before {
335
+ content: '';
336
+ position: absolute;
337
+ top: 100%;
338
+ left: 0;
339
+ width: 100%;
340
+ height: 100%;
341
+ background: linear-gradient(to top, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
342
+ animation: lightMoveUp 1.5s infinite linear;
343
+ z-index: 0;
344
+ }
345
+ .popup-close:hover {
346
+ background: #FF9E2C;
347
+ transform: scale(1.1);
348
+ }
349
+ .popup-close span {
350
+ position: relative;
351
+ z-index: 1;
352
+ }
353
+ /* Ingredient modal */
354
+ .ingredient-modal-container {
355
+ display: none;
356
+ position: fixed;
357
+ inset: 0;
358
+ background: rgba(0, 0, 0, 0.6);
359
+ justify-content: center;
360
+ align-items: center;
361
+ z-index: 10000;
362
+ animation: fadeIn 0.3s ease-in-out;
363
+ }
364
+ .ingredient-modal {
365
+ background: linear-gradient(135deg, #FFFFFF 0%, #F9FAFB 100%);
366
+ border-radius: 12px;
367
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
368
+ border: 1px solid #E5E7EB;
369
+ width: 90%;
370
+ max-width: 500px;
371
+ max-height: 90vh;
372
+ overflow-y: auto;
373
+ position: relative;
374
+ contain: layout;
375
+ }
376
+ .modal-section {
377
+ padding: 16px;
378
+ border-left: 4px solid #2DD4BF;
379
+ margin-bottom: 16px;
380
+ background: #F9FAFB;
381
+ border-radius: 6px;
382
+ }
383
+ /* Ingredient images */
384
+ .ingredient-image {
385
+ max-width: 100%;
386
+ max-height: 100px;
387
+ width: 100%;
388
+ height: 100px;
389
+ aspect-ratio: 1/1;
390
+ object-fit: cover;
391
+ border-radius: 6px;
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;
408
+ opacity: 0;
409
+ overflow: hidden;
410
+ }
411
+ .ingredients-section:not(.hidden) {
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;
423
+ font-size: 1.125rem;
424
+ padding: 20px;
425
+ background: #F9FAFB;
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;
433
+ overflow: hidden;
434
+ }
435
+ .order-confirmed::before {
436
+ content: '✔';
437
+ position: absolute;
438
+ top: 50%;
439
+ left: 50%;
440
+ transform: translate(-50%, -50%);
441
+ font-size: 120px;
442
+ color: rgba(16, 185, 129, 0.1);
443
+ z-index: 0;
444
+ }
445
+ .order-confirmed h1 {
446
+ font-size: 2.25rem;
447
+ z-index: 1;
448
+ position: relative;
449
+ }
450
+ /* Tier details animation */
451
+ .tier-details {
452
+ overflow: hidden;
453
+ transition: max-height 0.5s ease-in-out, opacity 0.3s ease-in-out;
454
+ max-height: 0;
455
+ opacity: 0;
456
+ }
457
+ .tier-details:not(.hidden) {
458
+ max-height: 1000px;
459
+ opacity: 1;
460
+ animation: slideDown 0.5s ease-in-out;
461
+ }
462
+ /* Price badge */
463
+ .price-badge {
464
+ display: inline-block;
465
+ background: #FFE4D6;
466
+ padding: 6px 14px;
467
+ border-radius: 14px;
468
+ font-weight: 600;
469
+ color: #C2410C;
470
+ }
471
+ /* Show Ingredients button focus style */
472
+ .ingredients-toggle-button:focus {
473
+ outline: none;
474
+ transform: scale(1.05);
475
+ }
476
+ /* Responsive adjustments */
477
+ @media (max-width: 768px) {
478
+ .custom-class {
479
+ padding: 20px !important;
480
+ max-width: 400px;
481
+ }
482
+ .order-image {
483
+ max-height: 270px;
484
+ }
485
+ .order-item-name {
486
+ font-size: 1.25rem;
487
+ padding: 6px 12px;
488
+ }
489
+ .grid {
490
+ grid-template-columns: repeat(2, 1fr);
491
+ }
492
+ }
493
+ @media (max-width: 480px) {
494
+ .custom-class {
495
+ max-width: 336px;
496
+ }
497
+ .order-image {
498
+ max-height: 225px;
499
+ }
500
+ .order-item-name {
501
+ font-size: 1.125rem;
502
+ }
503
+ }
504
+ @media (max-width: 360px) {
505
+ .custom-class {
506
+ max-width: 296px;
507
+ }
508
+ .order-image {
509
+ max-height: 195px;
510
+ }
511
+ .order-item-name {
512
+ font-size: 1rem;
513
+ padding: 4px 10px;
514
+ }
515
+ }
516
+ @media (max-width: 640px) {
517
+ .back-to-menu {
518
+ padding: 12px 16px;
519
+ font-size: 1rem;
520
+ }
521
+ .container {
522
+ margin-top: 70px;
523
+ padding: 16px;
524
+ }
525
+ .history {
526
+ font-size: 1.5rem;
527
+ padding: 1rem;
528
+ }
529
+ .sector-image {
530
+ max-width: 120px;
531
+ max-height: 80px;
532
+ }
533
+ .sector-name {
534
+ max-width: 120px;
535
+ }
536
+ .sector-item {
537
+ padding: 6px;
538
+ }
539
+ .order-confirmed h1 {
540
+ font-size: 1.75rem;
541
+ }
542
+ .scroll-button {
543
+ width: 32px;
544
+ height: 32px;
545
+ font-size: 16px;
546
+ }
547
+ #popup-content {
548
+ width: 95%;
549
+ padding: 16px;
550
+ max-height: 80vh;
551
+ }
552
+ .ingredient-modal {
553
+ width: 95%;
554
+ max-height: 80vh;
555
+ }
556
+ .popup-close {
557
+ width: 40px;
558
+ height: 40px;
559
+ font-size: 24px;
560
+ }
561
+ .popup-close::before {
562
+ animation: lightMoveUp 1.2s infinite linear;
563
+ }
564
+ .ingredient-image {
565
+ max-height: 80px;
566
+ height: 80px;
567
+ }
568
+ .grid {
569
+ grid-template-columns: repeat(2, 1fr);
570
+ }
571
+ }
572
+ @media (min-width: 768px) {
573
+ .grid {
574
+ grid-template-columns: repeat(3, 1fr);
575
+ }
576
+ }
577
+ </style>
578
  </head>
579
+ <body class="bg-gray-50">
580
+ <a href="{{ url_for('menu.menu') }}" class="back-to-menu" aria-label="Go back to menu">
581
+ <svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 mr-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
582
+ <path d="M15 18l-6-6 6-6"></path>
583
+ </svg>
584
+ Back to Menu
585
+ </a>
586
 
587
+ <div class="container mx-auto p-6 pt-2">
588
+ <!-- Order Confirmation -->
589
+ <div class="section bg-white shadow-sm rounded-xl p-6 mb-6 order-confirmed" role="alert">
590
+ <h1 class="text-center text-2xl font-bold text-orange-500">Order Confirmed!</h1>
591
+ <p class="text-center text-gray-600 mt-2">Estimated delivery time: {{ delivery_time }} minutes</p>
592
+ </div>
593
 
594
+ <!-- Reward Status Section -->
595
+ <div class="section bg-white rounded-xl shadow-lg p-6 mb-6">
596
+ <div class="flex items-center justify-between mb-4 cursor-pointer" onclick="toggleTierDetails()" aria-expanded="false" aria-controls="tierDetails">
597
+ <div id="tierBadge" class="w-8 h-8 p-1 rounded-full flex items-center justify-center tier-badge">
598
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-white">
599
+ <path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"></path>
600
+ <path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"></path>
601
+ <path d="M4 22h16"></path>
602
+ <path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"></path>
603
+ <path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"></path>
604
+ <path d="M9 9c0 .97.64 1.79 1.5 2.05A2 2 0 0 1 12 13c.82 0 1.54-.39 2-1"></path>
605
+ <path d="M18 9H6a4 4 0 0 1 0-8h12a4 4 0 0 1 0 8Z"></path>
606
+ </svg>
607
+ </div>
608
+ <span class="ml-2 text-xl font-bold text-orange-500" id="currentTier">{{ current_tier }} Tier</span>
609
+ <svg id="arrowIcon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-gray-600">
610
+ <path id="arrowPath" d="M19 9l-7 7-7-7"></path>
611
+ </svg>
612
+ </div>
613
 
614
+ <!-- Collapsible Content Section -->
615
+ <div id="tierDetails" class="tier-details hidden">
616
+ <div class="text-center mb-6">
617
+ <p class="text-gray-600">Valid through December {{ validity_year }}</p>
618
+ <p class="text-lg font-semibold mt-2 text-yellow-600" id="pointsDisplay">{{ user_points }} points</p>
619
+ </div>
620
 
621
+ <!-- Progress Bar -->
622
+ <div class="relative h-4 bg-gray-200 rounded-full overflow-hidden mb-4">
623
+ <div id="progressBar" class="absolute left-0 top-0 h-full progress-bar" style="width: {{ progress_percentage }}%"></div>
624
+ </div>
625
+
626
+ <div class="flex justify-between text-sm text-gray-600 mb-4">
627
+ <span id="startPoint">{{ start_point }}</span>
628
+ <span id="endPoint">{{ end_point }}</span>
629
+ </div>
630
+
631
+ <p class="text-center text-gray-700">
632
+ You need <span class="font-semibold text-gray-800" id="pointsNeeded">{{ points_needed_for_next_tier }}</span> more
633
+ points to reach
634
+ <span class="font-semibold text-orange-500" id="nextTier">{{ next_tier }}</span>
635
+ </p>
636
+
637
+
638
+
639
+ <!-- Tier Benefits -->
640
+ <div class="mt-6 bg-gray-50 rounded-xl p-4">
641
+ <h3 class="text-lg font-semibold mb-4 text-gray-800" id="benefitsTitle">
642
+ Benefits of Reaching {{ next_tier }} Tier
643
+ </h3>
644
+ <ul class="space-y-3" id="benefitsList">
645
+ {% if next_tier == "Silver" %}
646
+ <li class="flex items-center">
647
+ <span class="text-2xl mr-3">🏷️</span>
648
+ <span class="text-gray-700">10% discount on next purchase</span>
649
+ </li>
650
+ <li class="flex items-center">
651
+ <span class="text-2xl mr-3">🍹</span>
652
+ <span class="text-gray-700">Free soft drink with your next order</span>
653
+ </li>
654
+ {% elif next_tier == "Gold" %}
655
+ <li class="flex items-center">
656
+ <span class="text-2xl mr-3">🏷️</span>
657
+ <span class="text-gray-700">15% discount on next purchase</span>
658
+ </li>
659
+ <li class="flex items-center">
660
+ <span class="text-2xl mr-3">🍰</span>
661
+ <span class="text-gray-700">Free dessert on next order</span>
662
+ </li>
663
+ {% elif next_tier == "Platinum" %}
664
+ <li class="flex items-center">
665
+ <span class="text-2xl mr-3">🏷️</span>
666
+ <span class="text-gray-700">20% discount on next purchase</span>
667
+ </li>
668
+ <li class="flex items-center">
669
+ <span class="text-2xl mr-3">🍴</span>
670
+ <span class="text-gray-700">Free entrée with your next order</span>
671
+ </li>
672
+ {% else %}
673
+ <li class="text-gray-700">You've reached the highest tier! Enjoy exclusive benefits.</li>
674
+ {% endif %}
675
+ </ul>
676
+ </div>
677
+ </div>
678
+ </div>
679
+
680
+ <!-- Ingredient History -->
681
+ <div class="history">
682
+ <h1 class="text-center text-2xl font-bold text-orange-500">Ingredient History</h1>
683
+ </div>
684
+ {% if sector_details %}
685
+ <div class="sector-images-container" role="region" aria-label="Ingredient History Carousel">
686
+ <button class="scroll-button left" onclick="scrollContainer('left')" aria-label="Scroll left">
687
+ <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
688
+ <path d="M15 18l-6-6 6-6"></path>
689
+ </svg>
690
+ </button>
691
+ {% for sector_name, sector in sector_details.items() %}
692
+ <div class="sector-item">
693
+ <img
694
+ src="{{ sector.image_url | default('/static/placeholder.jpg') }}"
695
+ alt="{{ sector_name }}"
696
+ class="sector-image lazyload"
697
+ loading="lazy"
698
+ onclick="showSectorDescription('{{ sector.description | escape }}')"
699
+ role="img"
700
+ aria-describedby="sector-name-{{ loop.index }}"
701
+ onerror="this.src='/static/placeholder.jpg'; this.alt='Placeholder image'"
702
+ >
703
+ <h3 id="sector-name-{{ loop.index }}" class="sector-name">{{ sector_name }}</h3>
704
  </div>
705
+ {% endfor %}
706
+ <button class="scroll-button right" onclick="scrollContainer('right')" aria-label="Scroll right">
707
+ <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
708
+ <path d="M9 18l6-6-6-6"></path>
709
+ </svg>
710
+ </button>
711
+ </div>
712
+ {% else %}
713
+ <div class="no-data">No sector details available.</div>
714
+ {% endif %}
715
+
716
+ <!-- Popup for Sector Description -->
717
+ <div id="sector-popup" class="popup" style="display:none;" role="dialog" aria-modal="true" aria-labelledby="sector-popup-title">
718
+ <div id="popup-content">
719
+ <div class="popup-header flex justify-between items-center">
720
+ <h3 id="sector-popup-title" class="text-xl font-semibold text-gray-800">Origin History</h3>
721
+ <button onclick="closePopup()" class="popup-close" aria-label="Close sector description popup"><span>×</span></button>
722
+ </div>
723
+ <p id="sector-description" class="text-gray-700 leading-relaxed"></p>
724
  </div>
725
+ </div>
726
+
727
+ <!-- Order Items Section -->
728
+ <div class="text-center text-2xl font-bold text-orange-500 mb-6">Previous Orders</div>
729
+ {% if order_items %}
730
+ {% for item in order_items %}
731
+ <div class="custom-class">
732
+ <div class="order-image-wrapper">
733
+ <img
734
+ src="{{ item.image_url | default('/static/placeholder.jpg') }}"
735
+ alt="{{ item.name | escape }}"
736
+ class="order-image lazyload"
737
+ loading="lazy"
738
+ decoding="async"
739
+ role="img"
740
+ aria-label="Image of {{ item.name | escape }}"
741
+ aria-describedby="order-price-{{ loop.index }}"
742
+ onerror="this.src='/static/placeholder.jpg'; this.alt='Placeholder image'"
743
+ />
744
+ <h3 class="order-item-name" id="order-name-{{ loop.index }}">{{ item.name | escape }}</h3>
745
  </div>
746
+ <p id="order-price-{{ loop.index }}" class="text-gray-600 mb-2 price-badge">${{ "%.2f"|format(item.price | default(0)) }}</p>
747
+
748
+ {% if item.category != 'Soft Drink' %}
749
+ <button
750
+ id="ingredientsToggleButton{{ loop.index }}"
751
+ class="ingredients-toggle-button text-green-600 text-sm font-semibold mt-2 ml-2 text-left pb-4 hover:text-green-700"
752
+ onclick="toggleIngredients({{ loop.index }})"
753
+ aria-expanded="false"
754
+ aria-controls="ingredientsSection{{ loop.index }}"
755
+ data-index="{{ loop.index }}"
756
+ >
757
+ Show Ingredients
758
+ </button>
759
+
760
+ <div id="ingredientsSection{{ loop.index }}" class="ingredients-section hidden mt-4" aria-hidden="true">
761
+ {% if item.ingredients and item.ingredients|length > 0 %}
762
+ <div class="grid grid-cols-2 gap-4 sm:grid-cols-3">
763
+ {% for ingredient in item.ingredients %}
764
+ <button
765
+ class="relative group ingredient-button focus:outline-none focus:ring-2 focus:ring-green-500"
766
+ aria-label="View details for {{ ingredient.name | escape }}"
767
+ data-ingredient='{
768
+ "index": "{{ loop.index }}",
769
+ "name": "{{ ingredient.name | escape }}",
770
+ "image": "{{ ingredient.image | default('/static/placeholder.jpg') | escape }}",
771
+ "health_benefits": "{{ ingredient.health_benefits | escape }}",
772
+ "fun_facts": "{{ ingredient.fun_facts | escape }}"
773
+ }'
774
+ onclick="showIngredientDetails(this)"
775
+ >
776
+ <div class="overflow-hidden rounded-lg">
777
+ <img
778
+ src="{{ ingredient.image | default('/static/placeholder.jpg') }}"
779
+ alt="{{ ingredient.name | escape }}"
780
+ class="ingredient-image lazyload"
781
+ loading="lazy"
782
+ decoding="async"
783
+ onerror="this.src='/static/placeholder.jpg'; this.alt='Placeholder image'"
784
+ />
785
+ </div>
786
+ <p class="mt-2 text-center text-sm font-medium text-gray-800">{{ ingredient.name | escape }}</p>
787
+ </button>
788
+ {% endfor %}
789
+ </div>
790
+ {% else %}
791
+ <p class="text-gray-600 text-center">No ingredients available for this item.</p>
792
+ {% endif %}
793
  </div>
794
+ {% endif %}
795
+ </div>
796
+
797
+ <!-- Modal for Ingredients -->
798
+ {% if item.category != 'Soft Drink' %}
799
+ <div id="ingredientModal{{ loop.index }}" class="ingredient-modal-container hidden modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle{{ loop.index }}">
800
+ <div class="ingredient-modal">
801
+ <div class="p-6">
802
+ <div class="popup-header flex justify-between items-center mb-4">
803
+ <h3 id="modalTitle{{ loop.index }}" class="text-xl font-semibold text-gray-800"></h3>
804
+ <button onclick="closeModal({{ loop.index }})" class="popup-close" aria-label="Close ingredient details modal"><span>×</span></button>
805
+ </div>
806
+
807
+ <img id="modalImage{{ loop.index }}" src="" alt="" class="w-full max-h-48 object-contain rounded-xl mb-4 border border-gray-200 lazyload" loading="lazy" decoding="async" />
808
 
809
+ <div class="space-y-4">
810
+ <div class="modal-section">
811
+ <h4 class="font-semibold mb-2 text-gray-800 flex items-center">
812
+ <svg class="w-5 h-5 mr-2 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
813
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
814
+ </svg>
815
+ Health Benefits
816
+ </h4>
817
+ <ul id="healthBenefits{{ loop.index }}" class="list-disc list-inside text-gray-700"></ul>
818
+ </div>
819
 
820
+ <div class="modal-section">
821
+ <h4 class="font-semibold mb-2 text-gray-800 flex items-center">
822
+ <svg class="w-5 h-5 mr-2 text-orange-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
823
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
824
+ </svg>
825
+ Fun Facts
826
+ </h4>
827
+ <ul id="funFacts{{ loop.index }}" class="list-disc list-inside text-gray-700"></ul>
828
+ </div>
829
+ </div>
830
+ </div>
831
+ </div>
832
+ </div>
833
+ {% endif %}
834
+ {% endfor %}
835
+ {% else %}
836
+ <div class="no-data">No previous orders found.</div>
837
+ {% endif %}
838
  </div>
839
 
840
+ <script>
841
+ // Debounce function for performance
842
+ function debounce(func, wait) {
843
+ let timeout;
844
+ return function executedFunction(...args) {
845
+ const later = () => {
846
+ clearTimeout(timeout);
847
+ func(...args);
848
+ };
849
+ clearTimeout(timeout);
850
+ timeout = setTimeout(later, wait);
851
+ };
852
+ }
853
+
854
+ // Scroll container function
855
+ function scrollContainer(direction) {
856
+ try {
857
+ const container = document.querySelector('.sector-images-container');
858
+ const scrollAmount = 200;
859
+ if (direction === 'left') {
860
+ container.scrollLeft -= scrollAmount;
861
+ } else {
862
+ container.scrollLeft += scrollAmount;
863
+ }
864
+ } catch (e) {
865
+ console.error('Error scrolling container:', e);
866
+ }
867
+ }
868
+
869
+ // Show sector description popup
870
+ function showSectorDescription(description) {
871
+ try {
872
+ document.getElementById('sector-description').innerText = description || 'No description available.';
873
+ document.getElementById('sector-popup').style.display = 'flex';
874
+ document.body.classList.add('modal-open');
875
+ } catch (e) {
876
+ console.error('Error showing sector description:', e);
877
+ }
878
+ }
879
+
880
+ // Close sector popup
881
+ function closePopup() {
882
+ try {
883
+ document.getElementById('sector-popup').style.display = 'none';
884
+ document.body.classList.remove('modal-open');
885
+ } catch (e) {
886
+ console.error('Error closing popup:', e);
887
+ }
888
+ }
889
+
890
+ // Toggle tier details with animation
891
+ function toggleTierDetails() {
892
+ try {
893
+ const tierDetails = document.getElementById('tierDetails');
894
+ const arrowPath = document.getElementById('arrowPath');
895
+ const toggleButton = tierDetails.parentElement.querySelector('[aria-controls="tierDetails"]');
896
+ const isExpanded = !tierDetails.classList.contains('hidden');
897
+ tierDetails.classList.toggle('hidden');
898
+ arrowPath.setAttribute('d', tierDetails.classList.contains('hidden') ? 'M19 9l-7 7-7-7' : 'M19 15l-7-7-7 7');
899
+ toggleButton.setAttribute('aria-expanded', !isExpanded);
900
+ } catch (e) {
901
+ console.error('Error toggling tier details:', e);
902
+ }
903
+ }
904
+
905
+ // Toggle ingredients section
906
+ function toggleIngredients(index) {
907
+ try {
908
+ const section = document.getElementById(`ingredientsSection${index}`);
909
+ const button = document.getElementById(`ingredientsToggleButton${index}`);
910
+
911
+ if (!section || !button) {
912
+ console.error(`Elements not found for index ${index}`);
913
+ return;
914
+ }
915
+
916
+ const isHidden = section.classList.contains('hidden');
917
+
918
+ // Close all other ingredient sections
919
+ document.querySelectorAll('.ingredients-section').forEach(s => {
920
+ s.classList.add('hidden');
921
+ s.setAttribute('aria-hidden', 'true');
922
+ });
923
+ document.querySelectorAll('[id^="ingredientsToggleButton"]').forEach(b => {
924
+ b.textContent = 'Show Ingredients';
925
+ b.setAttribute('aria-expanded', 'false');
926
+ });
927
+
928
+ // Toggle the current section
929
+ if (isHidden) {
930
+ section.classList.remove('hidden');
931
+ section.setAttribute('aria-hidden', 'false');
932
+ button.textContent = 'Hide Ingredients';
933
+ button.setAttribute('aria-expanded', 'true');
934
+ } else {
935
+ section.classList.add('hidden');
936
+ section.setAttribute('aria-hidden', 'true');
937
+ button.textContent = 'Show Ingredients';
938
+ button.setAttribute('aria-expanded', 'false');
939
+ }
940
+ } catch (e) {
941
+ console.error('Error toggling ingredients:', e);
942
+ }
943
+ }
944
+
945
+ // Show ingredient details modal
946
+ function showIngredientDetails(button) {
947
+ try {
948
+ const data = JSON.parse(button.getAttribute('data-ingredient'));
949
+ const { index, name, image, health_benefits, fun_facts } = data;
950
+
951
+ const healthBenefitsList = (health_benefits || '').split(',').filter(item => item.trim());
952
+ const funFactsList = (fun_facts || '').split(',').filter(item => item.trim());
953
+
954
+ const modal = document.getElementById(`ingredientModal${index}`);
955
+ if (!modal) {
956
+ console.error(`Modal not found for index ${index}`);
957
+ return;
958
+ }
959
+
960
+ document.getElementById(`modalTitle${index}`).textContent = name || 'Unknown Ingredient';
961
+ const modalImage = document.getElementById(`modalImage${index}`);
962
+ modalImage.src = image || '/static/placeholder.jpg';
963
+ modalImage.alt = name || 'Ingredient image';
964
+
965
+ const healthBenefitsUl = document.getElementById(`healthBenefits${index}`);
966
+ const funFactsUl = document.getElementById(`funFacts${index}`);
967
+ healthBenefitsUl.innerHTML = healthBenefitsList.length
968
+ ? healthBenefitsList.map(item => `<li>${item.trim()}</li>`).join('')
969
+ : '<li>No health benefits available.</li>';
970
+ funFactsUl.innerHTML = funFactsList.length
971
+ ? funFactsList.map(item => `<li>${item.trim()}</li>`).join('')
972
+ : '<li>No fun facts available.</li>';
973
+
974
+ modal.style.display = 'flex';
975
+ document.body.classList.add('modal-open');
976
+ } catch (e) {
977
+ console.error('Error showing ingredient details:', e);
978
+ }
979
+ }
980
+
981
+ // Close ingredient modal
982
+ function closeModal(index) {
983
+ try {
984
+ const modal = document.getElementById(`ingredientModal${index}`);
985
+ if (modal) {
986
+ modal.style.display = 'none';
987
+ document.body.classList.remove('modal-open');
988
+ }
989
+ } catch (e) {
990
+ console.error('Error closing modal:', e);
991
+ }
992
+ }
993
+
994
+ // Set progress bar color based on points
995
+ document.addEventListener('DOMContentLoaded', () => {
996
+ try {
997
+ const progressBar = document.getElementById('progressBar');
998
+ const pointsDisplay = document.getElementById('pointsDisplay');
999
+ const points = parseInt(pointsDisplay.textContent, 10) || 0;
1000
+
1001
+ if (points <= 100) {
1002
+ progressBar.classList.add('range-0-100');
1003
+ } else if (points <= 200) {
1004
+ progressBar.classList.add('range-100-200');
1005
+ } else {
1006
+ progressBar.classList.add('range-200-plus');
1007
+ }
1008
+ } catch (e) {
1009
+ console.error('Error setting progress bar color:', e);
1010
+ }
1011
+
1012
+ // Lazy load images with IntersectionObserver
1013
+ const images = document.querySelectorAll('img.lazyload');
1014
+ if ('IntersectionObserver' in window) {
1015
+ const observer = new IntersectionObserver((entries, observer) => {
1016
+ entries.forEach(entry => {
1017
+ if (entry.isIntersecting) {
1018
+ const img = entry.target;
1019
+ img.src = img.src || '/static/placeholder.jpg';
1020
+ img.classList.remove('lazyload');
1021
+ observer.unobserve(img);
1022
+ }
1023
+ });
1024
+ });
1025
+ images.forEach(img => observer.observe(img));
1026
+ } else {
1027
+ images.forEach(img => {
1028
+ img.src = img.src || '/static/placeholder.jpg';
1029
+ img.classList.remove('lazyload');
1030
+ });
1031
+ }
1032
+ });
1033
+
1034
+ // Close modals on outside click
1035
+ document.addEventListener('click', (e) => {
1036
+ try {
1037
+ if (e.target.id === 'sector-popup') {
1038
+ closePopup();
1039
+ }
1040
+ document.querySelectorAll('.ingredient-modal-container').forEach(modal => {
1041
+ if (e.target === modal) {
1042
+ const index = modal.id.replace('ingredientModal', '');
1043
+ closeModal(index);
1044
+ }
1045
+ });
1046
+ } catch (e) {
1047
+ console.error('Error handling outside click:', e);
1048
+ }
1049
+ });
1050
 
1051
+ // Keyboard navigation for scroll buttons
1052
+ document.querySelectorAll('.scroll-button').forEach(button => {
1053
+ button.addEventListener('keydown', function(e) {
1054
+ if (e.key === 'Enter' || e.key === ' ') {
1055
+ e.preventDefault();
1056
+ scrollContainer(button.classList.contains('left') ? 'left' : 'right');
1057
+ }
1058
+ });
1059
+ });
1060
 
1061
+ // Keyboard navigation for toggle buttons
1062
+ document.querySelectorAll('[id^="ingredientsToggleButton"]').forEach(button => {
1063
+ button.addEventListener('keydown', (e) => {
1064
+ if (e.key === 'Enter' || e.key === ' ') {
1065
+ e.preventDefault();
1066
+ const index = button.getAttribute('data-index');
1067
+ toggleIngredients(index);
1068
+ }
1069
+ });
1070
+ });
1071
+ </script>
1072
  </body>
1073
+ </html>