higher5fh commited on
Commit
7e554d0
·
verified ·
1 Parent(s): ec83517

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +172 -114
index.html CHANGED
@@ -27,15 +27,13 @@
27
  box-sizing: border-box;
28
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
29
  }
30
-
31
- /* FIX 1: body fills viewport exactly, no overflow */
32
  body {
33
  background-color: var(--bg-light);
34
  color: var(--dark);
35
- height: 100vh;
36
  display: flex;
37
  flex-direction: column;
38
- overflow: hidden;
39
  }
40
 
41
  .container {
@@ -51,7 +49,8 @@
51
  color: white;
52
  padding: 1rem 0;
53
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
54
- flex-shrink: 0; /* FIX 2: header never shrinks */
 
55
  z-index: 100;
56
  }
57
 
@@ -93,29 +92,12 @@
93
  gap: 5px;
94
  }
95
 
96
- /* FIX 3: main area fills remaining height, scrolls internally */
97
- .main-wrapper {
98
- flex: 1;
99
- overflow: hidden;
100
- display: flex;
101
- flex-direction: column;
102
- }
103
-
104
- .main-wrapper > .container {
105
- flex: 1;
106
- overflow: hidden;
107
- display: flex;
108
- flex-direction: column;
109
- }
110
-
111
  /* Main Layout */
112
  .main-layout {
113
  display: flex;
114
  flex: 1;
115
  gap: 20px;
116
  padding: 20px 0;
117
- overflow: hidden;
118
- min-height: 0; /* critical — allows flex children to shrink below content size */
119
  }
120
 
121
  /* Chat Container */
@@ -127,7 +109,6 @@
127
  display: flex;
128
  flex-direction: column;
129
  overflow: hidden;
130
- min-height: 0;
131
  }
132
 
133
  .chat-header {
@@ -136,7 +117,6 @@
136
  display: flex;
137
  justify-content: space-between;
138
  align-items: center;
139
- flex-shrink: 0;
140
  }
141
 
142
  .chat-header h2 {
@@ -157,7 +137,6 @@
157
  border-radius: 50%;
158
  }
159
 
160
- /* Chat history scrolls, input stays pinned */
161
  .chat-history {
162
  flex: 1;
163
  padding: 20px;
@@ -166,7 +145,6 @@
166
  flex-direction: column;
167
  gap: 20px;
168
  background-color: #fafafa;
169
- min-height: 0;
170
  }
171
 
172
  .message {
@@ -241,12 +219,11 @@
241
  font-size: 0.85rem;
242
  }
243
 
244
- /* Input Area — always visible at bottom */
245
  .input-container {
246
  padding: 15px 20px;
247
  border-top: 1px solid var(--border);
248
  background: white;
249
- flex-shrink: 0;
250
  }
251
 
252
  .input-area {
@@ -298,11 +275,13 @@
298
  /* Sidebar */
299
  .sidebar {
300
  width: 300px;
 
 
 
 
301
  display: flex;
302
  flex-direction: column;
303
  gap: 20px;
304
- overflow-y: auto;
305
- min-height: 0;
306
  }
307
 
308
  .card {
@@ -310,7 +289,6 @@
310
  border-radius: 8px;
311
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
312
  overflow: hidden;
313
- flex-shrink: 0;
314
  }
315
 
316
  .card-header {
@@ -369,9 +347,17 @@
369
  animation: typing 1.4s infinite ease-in-out;
370
  }
371
 
372
- .typing-dot:nth-child(1) { animation-delay: 0s; }
373
- .typing-dot:nth-child(2) { animation-delay: 0.2s; }
374
- .typing-dot:nth-child(3) { animation-delay: 0.4s; }
 
 
 
 
 
 
 
 
375
 
376
  @keyframes typing {
377
  0%, 60%, 100% { transform: translateY(0); }
@@ -379,16 +365,25 @@
379
  }
380
 
381
  /* Status indicators */
382
- .connected { color: var(--success); }
383
- .disconnected { color: var(--danger); }
384
- .expiring-soon { color: var(--warning); font-weight: bold; }
 
 
 
 
 
 
 
 
 
385
 
386
  /* Footer */
387
  footer {
388
  background: var(--dark);
389
  color: white;
390
- padding: 12px 0;
391
- flex-shrink: 0;
392
  }
393
 
394
  .footer-content {
@@ -405,16 +400,17 @@
405
 
406
  /* Responsive Design */
407
  @media (max-width: 900px) {
408
- body { overflow: auto; height: auto; }
409
- .main-wrapper { overflow: visible; }
410
- .main-wrapper > .container { overflow: visible; }
411
  .main-layout {
412
  flex-direction: column;
413
- overflow: visible;
414
  }
415
- .sidebar { width: 100%; overflow: visible; }
416
- .chat-container { min-height: 500px; }
417
- .message { max-width: 90%; }
 
 
 
 
 
418
  }
419
 
420
  @media (max-width: 600px) {
@@ -423,13 +419,20 @@
423
  gap: 10px;
424
  align-items: flex-start;
425
  }
 
426
  .footer-content {
427
  flex-direction: column;
428
  gap: 15px;
429
  align-items: flex-start;
430
  }
431
- .input-area { flex-direction: column; }
432
- button { padding: 12px; }
 
 
 
 
 
 
433
  }
434
  </style>
435
  </head>
@@ -450,69 +453,65 @@
450
  </div>
451
  </div>
452
  </header>
453
-
454
- <!-- FIX: wrapped in main-wrapper so it fills remaining height -->
455
- <div class="main-wrapper">
456
- <div class="container">
457
- <div class="main-layout">
458
- <!-- Chat Interface -->
459
- <div class="chat-container">
460
- <div class="chat-header">
461
- <h2><i class="fas fa-comments"></i> Legal Consultation</h2>
462
- <div class="status-indicator">
463
- <div class="status-dot" id="statusDot"></div>
464
- <span id="connectionStatus">Connecting...</span>
465
- </div>
466
  </div>
467
-
468
- <div class="chat-history" id="chatHistory">
469
- <div class="message ai-message">
470
- <div class="message-header">
471
- <span><i class="fas fa-robot"></i> Legal Assistant</span>
472
- <span>Just now</span>
473
- </div>
474
- <div class="message-content">
475
- <p>Welcome to the Irish Legal AI Assistant! I'm here to help with your legal questions regarding Irish law.</p>
476
- <p>Please ask your question in the box below. I'll provide a concise answer with relevant legal sources.</p>
477
- </div>
478
  </div>
479
- </div>
480
-
481
- <!-- Input always pinned at bottom of chat-container -->
482
- <div class="input-container">
483
- <div class="input-area">
484
- <textarea id="userInput" placeholder="Ask a question about Irish law..." required></textarea>
485
- <button id="sendButton">
486
- <i class="fas fa-paper-plane"></i> Send
487
- </button>
488
  </div>
489
  </div>
490
  </div>
491
 
492
- <!-- Sidebar -->
493
- <div class="sidebar">
494
- <div class="card">
495
- <div class="card-header">
496
- <i class="fas fa-history"></i> Session History
497
- </div>
498
- <div class="card-body" id="historyList">
499
- <p style="color: var(--gray); text-align: center;">No history yet</p>
500
- </div>
501
  </div>
502
-
503
- <div class="card">
504
- <div class="card-header">
505
- <i class="fas fa-lightbulb"></i> Tips for Better Results
506
- </div>
507
- <div class="card-body">
508
- <ul style="padding-left: 20px; display: flex; flex-direction: column; gap: 10px;">
509
- <li>Be specific with your questions</li>
510
- <li>Include relevant context when possible</li>
511
- <li>Ask about recent legal changes</li>
512
- <li>Request practical implications</li>
513
- <li>Specify areas of law (employment, property, etc.)</li>
514
- </ul>
515
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
516
  </div>
517
  </div>
518
  </div>
@@ -538,17 +537,20 @@
538
  const connectionStatus = document.getElementById('connectionStatus');
539
  const statusDot = document.getElementById('statusDot');
540
 
 
541
  let sessionId = null;
542
  let sessionHistory = [];
543
  let sessionCheckInterval;
544
- const SESSION_CHECK_INTERVAL = 1000;
545
 
 
546
  function initializeSession() {
547
  updateConnectionStatus('connecting');
548
  checkSessionStatus();
549
  sessionCheckInterval = setInterval(checkSessionStatus, SESSION_CHECK_INTERVAL);
550
  }
551
 
 
552
  function updateConnectionStatus(status) {
553
  switch(status) {
554
  case 'connected':
@@ -569,17 +571,23 @@
569
  }
570
  }
571
 
 
572
  async function checkSessionStatus() {
573
  try {
574
  const response = await fetch('session/status', {
575
  method: 'GET',
576
  credentials: 'include'
577
  });
 
578
  if (!response.ok) throw new Error('Status check failed');
 
579
  const data = await response.json();
580
  updateConnectionStatus('connected');
581
  updateSessionDisplay(data);
582
- if (data.status === 'expired') handleSessionExpiry();
 
 
 
583
  } catch (error) {
584
  console.error('Session status check error:', error);
585
  updateConnectionStatus('disconnected');
@@ -587,6 +595,7 @@
587
  }
588
  }
589
 
 
590
  function updateSessionDisplay(sessionData) {
591
  switch (sessionData.status) {
592
  case 'new':
@@ -596,6 +605,7 @@
596
  sessionHistory = [];
597
  updateSessionHistory([]);
598
  break;
 
599
  case 'expired':
600
  sessionTimerElement.textContent = "Session Expired";
601
  sessionTimerElement.classList.remove('expiring-soon');
@@ -603,16 +613,22 @@
603
  sessionHistory = [];
604
  updateSessionHistory([]);
605
  break;
 
606
  case 'active':
607
  sessionId = sessionData.session_id;
608
  const minutes = Math.floor(sessionData.ttl / 60);
609
  const seconds = sessionData.ttl % 60;
610
- if (sessionData.ttl < 120) {
 
 
611
  sessionTimerElement.classList.add('expiring-soon');
612
  } else {
613
  sessionTimerElement.classList.remove('expiring-soon');
614
  }
 
615
  sessionTimerElement.textContent = `Expires in ${minutes}:${seconds.toString().padStart(2, '0')}`;
 
 
616
  if (sessionData.history_count !== sessionHistory.length) {
617
  fetchSessionHistory();
618
  }
@@ -620,13 +636,16 @@
620
  }
621
  }
622
 
 
623
  async function fetchSessionHistory() {
624
  try {
625
  const response = await fetch('session/history', {
626
  method: 'GET',
627
  credentials: 'include'
628
  });
 
629
  if (!response.ok) throw new Error('History fetch failed');
 
630
  const data = await response.json();
631
  sessionHistory = data.history || [];
632
  updateSessionHistory(sessionHistory);
@@ -636,48 +655,68 @@
636
  }
637
  }
638
 
 
639
  function updateSessionHistory(history) {
640
  historyList.innerHTML = '';
 
641
  if (history.length === 0) {
642
  historyList.innerHTML = '<p style="color: var(--gray); text-align: center;">No history yet</p>';
643
  return;
644
  }
645
- history.forEach((item) => {
 
646
  const historyItem = document.createElement('div');
647
  historyItem.className = 'history-item';
648
- historyItem.innerHTML = `<div class="history-question">${truncateText(item.q, 70)}</div>`;
649
- historyItem.addEventListener('click', () => scrollToMessage(item.q));
 
 
 
 
650
  historyList.appendChild(historyItem);
651
  });
652
  }
653
 
 
654
  function scrollToMessage(query) {
655
  const messages = document.querySelectorAll('.message');
656
  for (let msg of messages) {
657
  if (msg.textContent.includes(query)) {
658
  msg.scrollIntoView({ behavior: 'smooth', block: 'center' });
 
659
  msg.style.boxShadow = '0 0 0 2px var(--accent)';
660
- setTimeout(() => { msg.style.boxShadow = ''; }, 2000);
 
 
661
  break;
662
  }
663
  }
664
  }
665
 
 
666
  function truncateText(text, maxLength) {
667
  if (!text) return "";
668
  return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
669
  }
670
 
 
671
  function handleSessionExpiry() {
672
  sessionId = null;
673
  sessionHistory = [];
 
 
674
  while (chatHistory.children.length > 1) {
675
  chatHistory.removeChild(chatHistory.lastChild);
676
  }
677
- addMessage("Your session has expired due to inactivity. A new session will be created with your next question. Please be patient and retry if your request fails or you don't get a response—your new session will begin once the timer resets.", "ai");
 
 
 
 
678
  updateSessionHistory([]);
679
  }
680
 
 
681
  sendButton.addEventListener('click', sendMessage);
682
  userInput.addEventListener('keypress', function(e) {
683
  if (e.key === 'Enter' && !e.shiftKey) {
@@ -690,10 +729,12 @@
690
  const question = userInput.value.trim();
691
  if (!question) return;
692
 
 
693
  addMessage(question, 'user');
694
  userInput.value = '';
695
  sendButton.disabled = true;
696
 
 
697
  const typingIndicator = document.createElement('div');
698
  typingIndicator.className = 'typing-indicator';
699
  typingIndicator.innerHTML = `
@@ -705,23 +746,35 @@
705
  chatHistory.scrollTop = chatHistory.scrollHeight;
706
 
707
  try {
 
708
  const response = await fetch('query', {
709
  method: 'POST',
710
- headers: { 'Content-Type': 'application/json' },
 
 
711
  body: JSON.stringify({ query: question }),
712
  credentials: 'include'
713
  });
714
 
715
- if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
 
 
716
 
717
  const data = await response.json();
 
 
718
  chatHistory.removeChild(typingIndicator);
 
 
719
  addMessage(data.answer, 'ai', data.sources);
720
 
 
721
  if (data.session_id) {
722
  sessionId = data.session_id;
 
723
  fetchSessionHistory();
724
  }
 
725
  } catch (error) {
726
  console.error('Error sending message:', error);
727
  chatHistory.removeChild(typingIndicator);
@@ -734,8 +787,10 @@
734
  function addMessage(content, sender, sources = []) {
735
  const messageDiv = document.createElement('div');
736
  messageDiv.className = `message ${sender}-message`;
 
737
  const now = new Date();
738
  const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
 
739
  messageDiv.innerHTML = `
740
  <div class="message-header">
741
  <span><i class="${sender === 'ai' ? 'fas fa-robot' : 'fas fa-user'}"></i> ${sender === 'ai' ? 'Legal Assistant' : 'You'}</span>
@@ -751,16 +806,19 @@
751
  ` : ''}
752
  </div>
753
  `;
 
754
  chatHistory.appendChild(messageDiv);
755
  chatHistory.scrollTop = chatHistory.scrollHeight;
756
  }
757
 
758
  function formatMessageContent(content) {
759
  if (!content) return "";
 
760
  const paragraphs = content.split('\n\n');
761
  return paragraphs.map(p => `<p>${p}</p>`).join('');
762
  }
763
 
 
764
  initializeSession();
765
  });
766
  </script>
 
27
  box-sizing: border-box;
28
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
29
  }
30
+
 
31
  body {
32
  background-color: var(--bg-light);
33
  color: var(--dark);
34
+ min-height: 100vh;
35
  display: flex;
36
  flex-direction: column;
 
37
  }
38
 
39
  .container {
 
49
  color: white;
50
  padding: 1rem 0;
51
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
52
+ position: sticky;
53
+ top: 0;
54
  z-index: 100;
55
  }
56
 
 
92
  gap: 5px;
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  /* Main Layout */
96
  .main-layout {
97
  display: flex;
98
  flex: 1;
99
  gap: 20px;
100
  padding: 20px 0;
 
 
101
  }
102
 
103
  /* Chat Container */
 
109
  display: flex;
110
  flex-direction: column;
111
  overflow: hidden;
 
112
  }
113
 
114
  .chat-header {
 
117
  display: flex;
118
  justify-content: space-between;
119
  align-items: center;
 
120
  }
121
 
122
  .chat-header h2 {
 
137
  border-radius: 50%;
138
  }
139
 
 
140
  .chat-history {
141
  flex: 1;
142
  padding: 20px;
 
145
  flex-direction: column;
146
  gap: 20px;
147
  background-color: #fafafa;
 
148
  }
149
 
150
  .message {
 
219
  font-size: 0.85rem;
220
  }
221
 
222
+ /* Input Area */
223
  .input-container {
224
  padding: 15px 20px;
225
  border-top: 1px solid var(--border);
226
  background: white;
 
227
  }
228
 
229
  .input-area {
 
275
  /* Sidebar */
276
  .sidebar {
277
  width: 300px;
278
+ background: white;
279
+ border-radius: 10px;
280
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
281
+ padding: 20px;
282
  display: flex;
283
  flex-direction: column;
284
  gap: 20px;
 
 
285
  }
286
 
287
  .card {
 
289
  border-radius: 8px;
290
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
291
  overflow: hidden;
 
292
  }
293
 
294
  .card-header {
 
347
  animation: typing 1.4s infinite ease-in-out;
348
  }
349
 
350
+ .typing-dot:nth-child(1) {
351
+ animation-delay: 0s;
352
+ }
353
+
354
+ .typing-dot:nth-child(2) {
355
+ animation-delay: 0.2s;
356
+ }
357
+
358
+ .typing-dot:nth-child(3) {
359
+ animation-delay: 0.4s;
360
+ }
361
 
362
  @keyframes typing {
363
  0%, 60%, 100% { transform: translateY(0); }
 
365
  }
366
 
367
  /* Status indicators */
368
+ .connected {
369
+ color: var(--success);
370
+ }
371
+
372
+ .disconnected {
373
+ color: var(--danger);
374
+ }
375
+
376
+ .expiring-soon {
377
+ color: var(--warning);
378
+ font-weight: bold;
379
+ }
380
 
381
  /* Footer */
382
  footer {
383
  background: var(--dark);
384
  color: white;
385
+ padding: 20px 0;
386
+ margin-top: auto;
387
  }
388
 
389
  .footer-content {
 
400
 
401
  /* Responsive Design */
402
  @media (max-width: 900px) {
 
 
 
403
  .main-layout {
404
  flex-direction: column;
 
405
  }
406
+
407
+ .sidebar {
408
+ width: 100%;
409
+ }
410
+
411
+ .message {
412
+ max-width: 90%;
413
+ }
414
  }
415
 
416
  @media (max-width: 600px) {
 
419
  gap: 10px;
420
  align-items: flex-start;
421
  }
422
+
423
  .footer-content {
424
  flex-direction: column;
425
  gap: 15px;
426
  align-items: flex-start;
427
  }
428
+
429
+ .input-area {
430
+ flex-direction: column;
431
+ }
432
+
433
+ button {
434
+ padding: 12px;
435
+ }
436
  }
437
  </style>
438
  </head>
 
453
  </div>
454
  </div>
455
  </header>
456
+
457
+ <div class="container">
458
+ <div class="main-layout">
459
+ <!-- Chat Interface -->
460
+ <div class="chat-container">
461
+ <div class="chat-header">
462
+ <h2><i class="fas fa-comments"></i> Legal Consultation</h2>
463
+ <div class="status-indicator">
464
+ <div class="status-dot" id="statusDot"></div>
465
+ <span id="connectionStatus">Connecting...</span>
 
 
 
466
  </div>
467
+ </div>
468
+
469
+ <div class="chat-history" id="chatHistory">
470
+ <div class="message ai-message">
471
+ <div class="message-header">
472
+ <span><i class="fas fa-robot"></i> Legal Assistant</span>
473
+ <span>Just now</span>
 
 
 
 
474
  </div>
475
+ <div class="message-content">
476
+ <p>Welcome to the Irish Legal AI Assistant! I'm here to help with your legal questions regarding Irish law.</p>
477
+ <p>Please ask your question in the box below. I'll provide a concise answer with relevant legal sources.</p>
 
 
 
 
 
 
478
  </div>
479
  </div>
480
  </div>
481
 
482
+ <div class="input-container">
483
+ <div class="input-area">
484
+ <textarea id="userInput" placeholder="Ask a question about Irish law..." required></textarea>
485
+ <button id="sendButton">
486
+ <i class="fas fa-paper-plane"></i> Send
487
+ </button>
 
 
 
488
  </div>
489
+ </div>
490
+ </div>
491
+
492
+ <!-- Sidebar -->
493
+ <div class="sidebar">
494
+ <div class="card">
495
+ <div class="card-header">
496
+ <i class="fas fa-history"></i> Session History
497
+ </div>
498
+ <div class="card-body" id="historyList">
499
+ <p style="color: var(--gray); text-align: center;">No history yet</p>
500
+ </div>
501
+ </div>
502
+
503
+ <div class="card">
504
+ <div class="card-header">
505
+ <i class="fas fa-lightbulb"></i> Tips for Better Results
506
+ </div>
507
+ <div class="card-body">
508
+ <ul style="padding-left: 20px; display: flex; flex-direction: column; gap: 10px;">
509
+ <li>Be specific with your questions</li>
510
+ <li>Include relevant context when possible</li>
511
+ <li>Ask about recent legal changes</li>
512
+ <li>Request practical implications</li>
513
+ <li>Specify areas of law (employment, property, etc.)</li>
514
+ </ul>
515
  </div>
516
  </div>
517
  </div>
 
537
  const connectionStatus = document.getElementById('connectionStatus');
538
  const statusDot = document.getElementById('statusDot');
539
 
540
+ // Session management
541
  let sessionId = null;
542
  let sessionHistory = [];
543
  let sessionCheckInterval;
544
+ const SESSION_CHECK_INTERVAL = 1000; // Check every second
545
 
546
+ // Initialize session
547
  function initializeSession() {
548
  updateConnectionStatus('connecting');
549
  checkSessionStatus();
550
  sessionCheckInterval = setInterval(checkSessionStatus, SESSION_CHECK_INTERVAL);
551
  }
552
 
553
+ // Update connection status UI
554
  function updateConnectionStatus(status) {
555
  switch(status) {
556
  case 'connected':
 
571
  }
572
  }
573
 
574
+ // Check session status with backend
575
  async function checkSessionStatus() {
576
  try {
577
  const response = await fetch('session/status', {
578
  method: 'GET',
579
  credentials: 'include'
580
  });
581
+
582
  if (!response.ok) throw new Error('Status check failed');
583
+
584
  const data = await response.json();
585
  updateConnectionStatus('connected');
586
  updateSessionDisplay(data);
587
+
588
+ if (data.status === 'expired') {
589
+ handleSessionExpiry();
590
+ }
591
  } catch (error) {
592
  console.error('Session status check error:', error);
593
  updateConnectionStatus('disconnected');
 
595
  }
596
  }
597
 
598
+ // Update session timer display
599
  function updateSessionDisplay(sessionData) {
600
  switch (sessionData.status) {
601
  case 'new':
 
605
  sessionHistory = [];
606
  updateSessionHistory([]);
607
  break;
608
+
609
  case 'expired':
610
  sessionTimerElement.textContent = "Session Expired";
611
  sessionTimerElement.classList.remove('expiring-soon');
 
613
  sessionHistory = [];
614
  updateSessionHistory([]);
615
  break;
616
+
617
  case 'active':
618
  sessionId = sessionData.session_id;
619
  const minutes = Math.floor(sessionData.ttl / 60);
620
  const seconds = sessionData.ttl % 60;
621
+
622
+ // Add warning when session is about to expire
623
+ if (sessionData.ttl < 120) { // 2 minutes left
624
  sessionTimerElement.classList.add('expiring-soon');
625
  } else {
626
  sessionTimerElement.classList.remove('expiring-soon');
627
  }
628
+
629
  sessionTimerElement.textContent = `Expires in ${minutes}:${seconds.toString().padStart(2, '0')}`;
630
+
631
+ // Update history if count changed
632
  if (sessionData.history_count !== sessionHistory.length) {
633
  fetchSessionHistory();
634
  }
 
636
  }
637
  }
638
 
639
+ // Fetch full session history
640
  async function fetchSessionHistory() {
641
  try {
642
  const response = await fetch('session/history', {
643
  method: 'GET',
644
  credentials: 'include'
645
  });
646
+
647
  if (!response.ok) throw new Error('History fetch failed');
648
+
649
  const data = await response.json();
650
  sessionHistory = data.history || [];
651
  updateSessionHistory(sessionHistory);
 
655
  }
656
  }
657
 
658
+ // Update session history display
659
  function updateSessionHistory(history) {
660
  historyList.innerHTML = '';
661
+
662
  if (history.length === 0) {
663
  historyList.innerHTML = '<p style="color: var(--gray); text-align: center;">No history yet</p>';
664
  return;
665
  }
666
+
667
+ history.forEach((item, index) => {
668
  const historyItem = document.createElement('div');
669
  historyItem.className = 'history-item';
670
+ historyItem.innerHTML = `
671
+ <div class="history-question">${truncateText(item.q, 70)}</div>
672
+ `;
673
+ historyItem.addEventListener('click', () => {
674
+ scrollToMessage(item.q);
675
+ });
676
  historyList.appendChild(historyItem);
677
  });
678
  }
679
 
680
+ // Scroll to message in chat
681
  function scrollToMessage(query) {
682
  const messages = document.querySelectorAll('.message');
683
  for (let msg of messages) {
684
  if (msg.textContent.includes(query)) {
685
  msg.scrollIntoView({ behavior: 'smooth', block: 'center' });
686
+ // Highlight briefly
687
  msg.style.boxShadow = '0 0 0 2px var(--accent)';
688
+ setTimeout(() => {
689
+ msg.style.boxShadow = '';
690
+ }, 2000);
691
  break;
692
  }
693
  }
694
  }
695
 
696
+ // Truncate text for history display
697
  function truncateText(text, maxLength) {
698
  if (!text) return "";
699
  return text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
700
  }
701
 
702
+ // Handle session expiry
703
  function handleSessionExpiry() {
704
  sessionId = null;
705
  sessionHistory = [];
706
+
707
+ // Clear chat except initial message
708
  while (chatHistory.children.length > 1) {
709
  chatHistory.removeChild(chatHistory.lastChild);
710
  }
711
+
712
+ // Add expiry notification
713
+ addMessage("Your session has expired due to inactivity. A new session will be created with your next question. Please be patient and retry if your request fails or you don’t get a response—your new session will begin once the timer resets.","ai");
714
+
715
+ // Update history display
716
  updateSessionHistory([]);
717
  }
718
 
719
+ // Handle sending messages
720
  sendButton.addEventListener('click', sendMessage);
721
  userInput.addEventListener('keypress', function(e) {
722
  if (e.key === 'Enter' && !e.shiftKey) {
 
729
  const question = userInput.value.trim();
730
  if (!question) return;
731
 
732
+ // Add user message to chat
733
  addMessage(question, 'user');
734
  userInput.value = '';
735
  sendButton.disabled = true;
736
 
737
+ // Show typing indicator
738
  const typingIndicator = document.createElement('div');
739
  typingIndicator.className = 'typing-indicator';
740
  typingIndicator.innerHTML = `
 
746
  chatHistory.scrollTop = chatHistory.scrollHeight;
747
 
748
  try {
749
+ // Send query to backend
750
  const response = await fetch('query', {
751
  method: 'POST',
752
+ headers: {
753
+ 'Content-Type': 'application/json',
754
+ },
755
  body: JSON.stringify({ query: question }),
756
  credentials: 'include'
757
  });
758
 
759
+ if (!response.ok) {
760
+ throw new Error(`HTTP error! status: ${response.status}`);
761
+ }
762
 
763
  const data = await response.json();
764
+
765
+ // Remove typing indicator
766
  chatHistory.removeChild(typingIndicator);
767
+
768
+ // Add AI response
769
  addMessage(data.answer, 'ai', data.sources);
770
 
771
+ // Update session info
772
  if (data.session_id) {
773
  sessionId = data.session_id;
774
+ // Refresh history display
775
  fetchSessionHistory();
776
  }
777
+
778
  } catch (error) {
779
  console.error('Error sending message:', error);
780
  chatHistory.removeChild(typingIndicator);
 
787
  function addMessage(content, sender, sources = []) {
788
  const messageDiv = document.createElement('div');
789
  messageDiv.className = `message ${sender}-message`;
790
+
791
  const now = new Date();
792
  const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
793
+
794
  messageDiv.innerHTML = `
795
  <div class="message-header">
796
  <span><i class="${sender === 'ai' ? 'fas fa-robot' : 'fas fa-user'}"></i> ${sender === 'ai' ? 'Legal Assistant' : 'You'}</span>
 
806
  ` : ''}
807
  </div>
808
  `;
809
+
810
  chatHistory.appendChild(messageDiv);
811
  chatHistory.scrollTop = chatHistory.scrollHeight;
812
  }
813
 
814
  function formatMessageContent(content) {
815
  if (!content) return "";
816
+ // Convert line breaks to paragraphs
817
  const paragraphs = content.split('\n\n');
818
  return paragraphs.map(p => `<p>${p}</p>`).join('');
819
  }
820
 
821
+ // Initialize the session
822
  initializeSession();
823
  });
824
  </script>