mohamedhassan22 commited on
Commit
15bebcf
·
verified ·
1 Parent(s): ef5aecf

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +172 -57
static/index.html CHANGED
@@ -21,13 +21,11 @@
21
  --border-color: #334155;
22
  --accent-gradient: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
23
  }
24
-
25
  * {
26
  box-sizing: border-box;
27
  margin: 0;
28
  padding: 0;
29
  }
30
-
31
  body {
32
  font-family: 'Outfit', sans-serif;
33
  background-color: var(--bg-dark);
@@ -38,7 +36,6 @@
38
  radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.1) 0%, transparent 20%),
39
  radial-gradient(circle at 90% 80%, rgba(139, 92, 246, 0.1) 0%, transparent 20%);
40
  }
41
-
42
  .container {
43
  max-width: 1200px;
44
  margin: 0 auto;
@@ -47,13 +44,11 @@
47
  flex-direction: column;
48
  gap: 2rem;
49
  }
50
-
51
  header {
52
  text-align: center;
53
  padding: 4rem 0 2rem;
54
  animation: fadeInDown 0.8s ease-out;
55
  }
56
-
57
  h1 {
58
  font-family: 'Space Grotesk', sans-serif;
59
  font-size: 3.5rem;
@@ -65,22 +60,18 @@
65
  margin-bottom: 0.5rem;
66
  letter-spacing: -0.02em;
67
  }
68
-
69
  .subtitle {
70
  color: var(--text-muted);
71
  font-size: 1.25rem;
72
  font-weight: 300;
73
  }
74
-
75
  .subtitle a {
76
  color: var(--primary);
77
  text-decoration: none;
78
  }
79
-
80
  .subtitle a:hover {
81
  text-decoration: underline;
82
  }
83
-
84
  /* Search Section */
85
  .search-container {
86
  max-width: 800px;
@@ -89,7 +80,6 @@
89
  position: relative;
90
  z-index: 10;
91
  }
92
-
93
  .input-group {
94
  position: relative;
95
  display: flex;
@@ -102,13 +92,11 @@
102
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
103
  transition: all 0.3s ease;
104
  }
105
-
106
  .input-group:focus-within {
107
  border-color: var(--primary);
108
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
109
  transform: translateY(-2px);
110
  }
111
-
112
  input[type="text"] {
113
  flex: 1;
114
  background: transparent;
@@ -119,15 +107,12 @@
119
  font-family: 'Outfit', sans-serif;
120
  width: 100%;
121
  }
122
-
123
  input[type="text"]:focus {
124
  outline: none;
125
  }
126
-
127
  input[type="text"]::placeholder {
128
  color: #64748b;
129
  }
130
-
131
  button#searchBtn {
132
  background: var(--accent-gradient);
133
  color: white;
@@ -142,23 +127,80 @@
142
  align-items: center;
143
  gap: 0.5rem;
144
  }
145
-
146
  button#searchBtn:hover {
147
  opacity: 0.9;
148
  }
149
-
150
  button#searchBtn:disabled {
151
  opacity: 0.5;
152
  cursor: not-allowed;
153
  }
154
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  /* Loading State */
156
  #loading {
157
  display: none;
158
  text-align: center;
159
  padding: 2rem;
160
  }
161
-
162
  .spinner {
163
  width: 40px;
164
  height: 40px;
@@ -168,13 +210,11 @@
168
  animation: spin 1s linear infinite;
169
  margin: 0 auto 1rem;
170
  }
171
-
172
  @keyframes spin {
173
  to {
174
  transform: rotate(360deg);
175
  }
176
  }
177
-
178
  /* Chat History */
179
  #chatHistory {
180
  max-width: 1000px;
@@ -183,7 +223,6 @@
183
  flex-direction: column;
184
  gap: 2rem;
185
  }
186
-
187
  .message-block {
188
  border: 1px solid var(--border-color);
189
  border-radius: 1rem;
@@ -191,25 +230,20 @@
191
  background: var(--bg-card);
192
  animation: fadeInUp 0.4s ease-out;
193
  }
194
-
195
  .user-question {
196
  margin-bottom: 1rem;
197
  color: var(--text-main);
198
  }
199
-
200
  .user-question strong {
201
  color: var(--primary);
202
  }
203
-
204
  .assistant-answer {
205
  margin-bottom: 1rem;
206
  line-height: 1.8;
207
  }
208
-
209
  .assistant-answer strong {
210
  color: #8b5cf6;
211
  }
212
-
213
  /* Image Grids */
214
  .images-grid {
215
  display: grid;
@@ -217,7 +251,6 @@
217
  gap: 1.5rem;
218
  margin-top: 1rem;
219
  }
220
-
221
  .image-card {
222
  background: rgba(30, 41, 59, 0.6);
223
  border-radius: 0.75rem;
@@ -225,35 +258,29 @@
225
  border: 1px solid var(--border-color);
226
  transition: all 0.3s ease;
227
  }
228
-
229
  .image-card:hover {
230
  transform: translateY(-5px);
231
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
232
  border-color: var(--primary);
233
  }
234
-
235
  .image-card a {
236
  display: block;
237
  overflow: hidden;
238
  height: 180px;
239
  }
240
-
241
  .image-card img {
242
  width: 100%;
243
  height: 100%;
244
  object-fit: cover;
245
  transition: transform 0.5s ease;
246
  }
247
-
248
  .image-card:hover img {
249
  transform: scale(1.1);
250
  }
251
-
252
  .image-meta {
253
  padding: 1rem;
254
  border-top: 1px solid var(--border-color);
255
  }
256
-
257
  .image-filename {
258
  font-weight: 600;
259
  color: #f1f5f9;
@@ -262,7 +289,6 @@
262
  overflow: hidden;
263
  text-overflow: ellipsis;
264
  }
265
-
266
  /* Text Sources */
267
  .source-card {
268
  background: rgba(30, 41, 59, 0.4);
@@ -272,19 +298,16 @@
272
  margin-top: 0.75rem;
273
  transition: background 0.2s;
274
  }
275
-
276
  .source-card:hover {
277
  background: rgba(30, 41, 59, 0.8);
278
  border-color: #475569;
279
  }
280
-
281
  .source-title {
282
  font-weight: 600;
283
  color: var(--primary);
284
  margin-bottom: 0.5rem;
285
  font-size: 0.95rem;
286
  }
287
-
288
  .source-excerpt {
289
  font-style: italic;
290
  color: #cbd5e1;
@@ -295,14 +318,12 @@
295
  border-left: 3px solid var(--primary);
296
  word-wrap: break-word;
297
  }
298
-
299
  .source-meta {
300
  margin-top: 0.75rem;
301
  font-size: 0.8rem;
302
  color: var(--text-muted);
303
  text-align: right;
304
  }
305
-
306
  /* Animations */
307
  @keyframes fadeInDown {
308
  from {
@@ -314,7 +335,6 @@
314
  transform: translateY(0);
315
  }
316
  }
317
-
318
  @keyframes fadeInUp {
319
  from {
320
  opacity: 0;
@@ -325,21 +345,17 @@
325
  transform: translateY(0);
326
  }
327
  }
328
-
329
  /* Scrollbar */
330
  ::-webkit-scrollbar {
331
  width: 8px;
332
  }
333
-
334
  ::-webkit-scrollbar-track {
335
  background: var(--bg-dark);
336
  }
337
-
338
  ::-webkit-scrollbar-thumb {
339
  background: var(--border-color);
340
  border-radius: 4px;
341
  }
342
-
343
  ::-webkit-scrollbar-thumb:hover {
344
  background: #475569;
345
  }
@@ -368,6 +384,24 @@
368
  </button>
369
  </div>
370
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
372
  <!-- CHAT HISTORY -->
373
  <div id="chatHistory"></div>
@@ -383,43 +417,60 @@
383
  const searchBtn = document.getElementById('searchBtn');
384
  const loading = document.getElementById('loading');
385
  const chatHistoryContainer = document.getElementById('chatHistory');
386
-
 
 
 
 
 
387
  // Allow Enter key to submit
388
  input.addEventListener('keypress', function (e) {
389
  if (e.key === 'Enter') {
390
  askQuestion();
391
  }
392
  });
393
-
394
  function escapeHtml(text) {
395
  const div = document.createElement('div');
396
  div.textContent = text;
397
  return div.innerHTML;
398
  }
399
-
400
  async function askQuestion() {
401
  const question = input.value.trim();
402
  if (!question) return;
403
-
404
  // UI State updates
405
  searchBtn.disabled = true;
406
  searchBtn.innerHTML = '<span style="font-size: 0.9em">Processing...</span>';
407
  input.disabled = true;
408
  loading.style.display = 'block';
409
-
410
  try {
411
  const response = await fetch('/query', {
412
  method: 'POST',
413
  headers: { 'Content-Type': 'application/json' },
414
  body: JSON.stringify({ question: question })
415
  });
416
-
417
  if (!response.ok) {
418
  throw new Error(`Server error: ${response.status}`);
419
  }
420
-
421
  const data = await response.json();
422
-
 
 
 
 
 
 
 
 
 
 
 
 
423
  // Create a chat message container
424
  const messageBlock = document.createElement('div');
425
  messageBlock.className = 'message-block';
@@ -435,7 +486,7 @@
435
  assistantAnswer.className = 'assistant-answer';
436
  assistantAnswer.innerHTML = `<strong>Assistant:</strong><br>${escapeHtml(data.answer).replace(/\n/g, '<br>')}`;
437
  messageBlock.appendChild(assistantAnswer);
438
-
439
  // Display Images
440
  if (data.images && data.images.length > 0) {
441
  const relevantImages = data.images.filter(img => (img.score || 0) >= 0.3).slice(0, 3);
@@ -461,7 +512,7 @@
461
  messageBlock.appendChild(imagesWrapper);
462
  }
463
  }
464
-
465
  // Display Texts
466
  if (data.texts && data.texts.length > 0) {
467
  const topTexts = data.texts.slice(0, 3);
@@ -480,14 +531,14 @@
480
  messageBlock.appendChild(div);
481
  });
482
  }
483
-
484
  chatHistoryContainer.appendChild(messageBlock);
485
 
486
  // Scroll to the new message
487
  setTimeout(() => {
488
  messageBlock.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
489
  }, 100);
490
-
491
  } catch (error) {
492
  alert('Error querying system. Please try again.');
493
  console.error('Query error:', error);
@@ -505,6 +556,70 @@
505
  input.value = '';
506
  }
507
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  </script>
509
  </body>
510
 
 
21
  --border-color: #334155;
22
  --accent-gradient: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
23
  }
 
24
  * {
25
  box-sizing: border-box;
26
  margin: 0;
27
  padding: 0;
28
  }
 
29
  body {
30
  font-family: 'Outfit', sans-serif;
31
  background-color: var(--bg-dark);
 
36
  radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.1) 0%, transparent 20%),
37
  radial-gradient(circle at 90% 80%, rgba(139, 92, 246, 0.1) 0%, transparent 20%);
38
  }
 
39
  .container {
40
  max-width: 1200px;
41
  margin: 0 auto;
 
44
  flex-direction: column;
45
  gap: 2rem;
46
  }
 
47
  header {
48
  text-align: center;
49
  padding: 4rem 0 2rem;
50
  animation: fadeInDown 0.8s ease-out;
51
  }
 
52
  h1 {
53
  font-family: 'Space Grotesk', sans-serif;
54
  font-size: 3.5rem;
 
60
  margin-bottom: 0.5rem;
61
  letter-spacing: -0.02em;
62
  }
 
63
  .subtitle {
64
  color: var(--text-muted);
65
  font-size: 1.25rem;
66
  font-weight: 300;
67
  }
 
68
  .subtitle a {
69
  color: var(--primary);
70
  text-decoration: none;
71
  }
 
72
  .subtitle a:hover {
73
  text-decoration: underline;
74
  }
 
75
  /* Search Section */
76
  .search-container {
77
  max-width: 800px;
 
80
  position: relative;
81
  z-index: 10;
82
  }
 
83
  .input-group {
84
  position: relative;
85
  display: flex;
 
92
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
93
  transition: all 0.3s ease;
94
  }
 
95
  .input-group:focus-within {
96
  border-color: var(--primary);
97
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
98
  transform: translateY(-2px);
99
  }
 
100
  input[type="text"] {
101
  flex: 1;
102
  background: transparent;
 
107
  font-family: 'Outfit', sans-serif;
108
  width: 100%;
109
  }
 
110
  input[type="text"]:focus {
111
  outline: none;
112
  }
 
113
  input[type="text"]::placeholder {
114
  color: #64748b;
115
  }
 
116
  button#searchBtn {
117
  background: var(--accent-gradient);
118
  color: white;
 
127
  align-items: center;
128
  gap: 0.5rem;
129
  }
 
130
  button#searchBtn:hover {
131
  opacity: 0.9;
132
  }
 
133
  button#searchBtn:disabled {
134
  opacity: 0.5;
135
  cursor: not-allowed;
136
  }
137
+
138
+ /* Action Buttons */
139
+ .action-buttons {
140
+ max-width: 800px;
141
+ margin: 0 auto;
142
+ width: 100%;
143
+ display: flex;
144
+ gap: 1rem;
145
+ justify-content: flex-end;
146
+ }
147
+
148
+ button#downloadBtn {
149
+ background: rgba(139, 92, 246, 0.2);
150
+ color: #c4b5fd;
151
+ border: 1px solid #8b5cf6;
152
+ padding: 0.75rem 1.5rem;
153
+ border-radius: 0.75rem;
154
+ font-weight: 600;
155
+ font-size: 0.95rem;
156
+ cursor: pointer;
157
+ transition: all 0.2s;
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 0.5rem;
161
+ }
162
+
163
+ button#downloadBtn:hover:not(:disabled) {
164
+ background: rgba(139, 92, 246, 0.3);
165
+ border-color: #a78bfa;
166
+ }
167
+
168
+ button#downloadBtn:disabled {
169
+ opacity: 0.5;
170
+ cursor: not-allowed;
171
+ }
172
+
173
+ button#clearBtn {
174
+ background: rgba(239, 68, 68, 0.2);
175
+ color: #fca5a5;
176
+ border: 1px solid #ef4444;
177
+ padding: 0.75rem 1.5rem;
178
+ border-radius: 0.75rem;
179
+ font-weight: 600;
180
+ font-size: 0.95rem;
181
+ cursor: pointer;
182
+ transition: all 0.2s;
183
+ display: flex;
184
+ align-items: center;
185
+ gap: 0.5rem;
186
+ }
187
+
188
+ button#clearBtn:hover {
189
+ background: rgba(239, 68, 68, 0.3);
190
+ border-color: #f87171;
191
+ }
192
+
193
+ button#clearBtn:disabled {
194
+ opacity: 0.5;
195
+ cursor: not-allowed;
196
+ }
197
+
198
  /* Loading State */
199
  #loading {
200
  display: none;
201
  text-align: center;
202
  padding: 2rem;
203
  }
 
204
  .spinner {
205
  width: 40px;
206
  height: 40px;
 
210
  animation: spin 1s linear infinite;
211
  margin: 0 auto 1rem;
212
  }
 
213
  @keyframes spin {
214
  to {
215
  transform: rotate(360deg);
216
  }
217
  }
 
218
  /* Chat History */
219
  #chatHistory {
220
  max-width: 1000px;
 
223
  flex-direction: column;
224
  gap: 2rem;
225
  }
 
226
  .message-block {
227
  border: 1px solid var(--border-color);
228
  border-radius: 1rem;
 
230
  background: var(--bg-card);
231
  animation: fadeInUp 0.4s ease-out;
232
  }
 
233
  .user-question {
234
  margin-bottom: 1rem;
235
  color: var(--text-main);
236
  }
 
237
  .user-question strong {
238
  color: var(--primary);
239
  }
 
240
  .assistant-answer {
241
  margin-bottom: 1rem;
242
  line-height: 1.8;
243
  }
 
244
  .assistant-answer strong {
245
  color: #8b5cf6;
246
  }
 
247
  /* Image Grids */
248
  .images-grid {
249
  display: grid;
 
251
  gap: 1.5rem;
252
  margin-top: 1rem;
253
  }
 
254
  .image-card {
255
  background: rgba(30, 41, 59, 0.6);
256
  border-radius: 0.75rem;
 
258
  border: 1px solid var(--border-color);
259
  transition: all 0.3s ease;
260
  }
 
261
  .image-card:hover {
262
  transform: translateY(-5px);
263
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
264
  border-color: var(--primary);
265
  }
 
266
  .image-card a {
267
  display: block;
268
  overflow: hidden;
269
  height: 180px;
270
  }
 
271
  .image-card img {
272
  width: 100%;
273
  height: 100%;
274
  object-fit: cover;
275
  transition: transform 0.5s ease;
276
  }
 
277
  .image-card:hover img {
278
  transform: scale(1.1);
279
  }
 
280
  .image-meta {
281
  padding: 1rem;
282
  border-top: 1px solid var(--border-color);
283
  }
 
284
  .image-filename {
285
  font-weight: 600;
286
  color: #f1f5f9;
 
289
  overflow: hidden;
290
  text-overflow: ellipsis;
291
  }
 
292
  /* Text Sources */
293
  .source-card {
294
  background: rgba(30, 41, 59, 0.4);
 
298
  margin-top: 0.75rem;
299
  transition: background 0.2s;
300
  }
 
301
  .source-card:hover {
302
  background: rgba(30, 41, 59, 0.8);
303
  border-color: #475569;
304
  }
 
305
  .source-title {
306
  font-weight: 600;
307
  color: var(--primary);
308
  margin-bottom: 0.5rem;
309
  font-size: 0.95rem;
310
  }
 
311
  .source-excerpt {
312
  font-style: italic;
313
  color: #cbd5e1;
 
318
  border-left: 3px solid var(--primary);
319
  word-wrap: break-word;
320
  }
 
321
  .source-meta {
322
  margin-top: 0.75rem;
323
  font-size: 0.8rem;
324
  color: var(--text-muted);
325
  text-align: right;
326
  }
 
327
  /* Animations */
328
  @keyframes fadeInDown {
329
  from {
 
335
  transform: translateY(0);
336
  }
337
  }
 
338
  @keyframes fadeInUp {
339
  from {
340
  opacity: 0;
 
345
  transform: translateY(0);
346
  }
347
  }
 
348
  /* Scrollbar */
349
  ::-webkit-scrollbar {
350
  width: 8px;
351
  }
 
352
  ::-webkit-scrollbar-track {
353
  background: var(--bg-dark);
354
  }
 
355
  ::-webkit-scrollbar-thumb {
356
  background: var(--border-color);
357
  border-radius: 4px;
358
  }
 
359
  ::-webkit-scrollbar-thumb:hover {
360
  background: #475569;
361
  }
 
384
  </button>
385
  </div>
386
  </div>
387
+
388
+ <!-- Action Buttons -->
389
+ <div class="action-buttons" id="actionButtons" style="display: none;">
390
+ <button id="downloadBtn" onclick="downloadPDFReport()">
391
+ <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
392
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
393
+ d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
394
+ </svg>
395
+ Download PDF Report
396
+ </button>
397
+ <button id="clearBtn" onclick="clearHistory()">
398
+ <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
399
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
400
+ d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
401
+ </svg>
402
+ Clear Chat
403
+ </button>
404
+ </div>
405
 
406
  <!-- CHAT HISTORY -->
407
  <div id="chatHistory"></div>
 
417
  const searchBtn = document.getElementById('searchBtn');
418
  const loading = document.getElementById('loading');
419
  const chatHistoryContainer = document.getElementById('chatHistory');
420
+ const actionButtons = document.getElementById('actionButtons');
421
+ const downloadBtn = document.getElementById('downloadBtn');
422
+
423
+ // Store conversation data for report generation
424
+ let conversationData = [];
425
+
426
  // Allow Enter key to submit
427
  input.addEventListener('keypress', function (e) {
428
  if (e.key === 'Enter') {
429
  askQuestion();
430
  }
431
  });
432
+
433
  function escapeHtml(text) {
434
  const div = document.createElement('div');
435
  div.textContent = text;
436
  return div.innerHTML;
437
  }
438
+
439
  async function askQuestion() {
440
  const question = input.value.trim();
441
  if (!question) return;
442
+
443
  // UI State updates
444
  searchBtn.disabled = true;
445
  searchBtn.innerHTML = '<span style="font-size: 0.9em">Processing...</span>';
446
  input.disabled = true;
447
  loading.style.display = 'block';
448
+
449
  try {
450
  const response = await fetch('/query', {
451
  method: 'POST',
452
  headers: { 'Content-Type': 'application/json' },
453
  body: JSON.stringify({ question: question })
454
  });
455
+
456
  if (!response.ok) {
457
  throw new Error(`Server error: ${response.status}`);
458
  }
459
+
460
  const data = await response.json();
461
+
462
+ // Store conversation data for report
463
+ conversationData.push({
464
+ question: question,
465
+ answer: data.answer,
466
+ images: data.images || [],
467
+ texts: data.texts || [],
468
+ timestamp: new Date().toISOString()
469
+ });
470
+
471
+ // Show action buttons once we have content
472
+ actionButtons.style.display = 'flex';
473
+
474
  // Create a chat message container
475
  const messageBlock = document.createElement('div');
476
  messageBlock.className = 'message-block';
 
486
  assistantAnswer.className = 'assistant-answer';
487
  assistantAnswer.innerHTML = `<strong>Assistant:</strong><br>${escapeHtml(data.answer).replace(/\n/g, '<br>')}`;
488
  messageBlock.appendChild(assistantAnswer);
489
+
490
  // Display Images
491
  if (data.images && data.images.length > 0) {
492
  const relevantImages = data.images.filter(img => (img.score || 0) >= 0.3).slice(0, 3);
 
512
  messageBlock.appendChild(imagesWrapper);
513
  }
514
  }
515
+
516
  // Display Texts
517
  if (data.texts && data.texts.length > 0) {
518
  const topTexts = data.texts.slice(0, 3);
 
531
  messageBlock.appendChild(div);
532
  });
533
  }
534
+
535
  chatHistoryContainer.appendChild(messageBlock);
536
 
537
  // Scroll to the new message
538
  setTimeout(() => {
539
  messageBlock.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
540
  }, 100);
541
+
542
  } catch (error) {
543
  alert('Error querying system. Please try again.');
544
  console.error('Query error:', error);
 
556
  input.value = '';
557
  }
558
  }
559
+
560
+ async function downloadPDFReport() {
561
+ if (conversationData.length === 0) {
562
+ alert('No conversation to download');
563
+ return;
564
+ }
565
+
566
+ // Disable button and show loading state
567
+ downloadBtn.disabled = true;
568
+ downloadBtn.innerHTML = '<span style="font-size: 0.9em">Generating PDF...</span>';
569
+
570
+ try {
571
+ const response = await fetch('/generate-report', {
572
+ method: 'POST',
573
+ headers: { 'Content-Type': 'application/json' },
574
+ body: JSON.stringify({ conversations: conversationData })
575
+ });
576
+
577
+ if (!response.ok) {
578
+ throw new Error(`Server error: ${response.status}`);
579
+ }
580
+
581
+ // Get the PDF blob
582
+ const blob = await response.blob();
583
+
584
+ // Create download link
585
+ const url = URL.createObjectURL(blob);
586
+ const a = document.createElement('a');
587
+ a.href = url;
588
+ a.download = `WHEC_Report_${new Date().toISOString().split('T')[0]}.pdf`;
589
+ document.body.appendChild(a);
590
+ a.click();
591
+ document.body.removeChild(a);
592
+ URL.revokeObjectURL(url);
593
+
594
+ } catch (error) {
595
+ alert('Error generating PDF report. Please try again.');
596
+ console.error('PDF generation error:', error);
597
+ } finally {
598
+ // Re-enable button
599
+ downloadBtn.disabled = false;
600
+ downloadBtn.innerHTML = `
601
+ <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
602
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
603
+ d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
604
+ </svg>
605
+ Download PDF Report
606
+ `;
607
+ }
608
+ }
609
+
610
+ function clearHistory() {
611
+ if (conversationData.length === 0) {
612
+ return;
613
+ }
614
+
615
+ if (!confirm('Are you sure you want to clear the conversation history? This cannot be undone.')) {
616
+ return;
617
+ }
618
+
619
+ conversationData = [];
620
+ chatHistoryContainer.innerHTML = '';
621
+ actionButtons.style.display = 'none';
622
+ }
623
  </script>
624
  </body>
625