goctests0 commited on
Commit
1d69108
·
verified ·
1 Parent(s): f49470f

Upload patient.js

Browse files
Files changed (1) hide show
  1. static/js/patient.js +19 -82
static/js/patient.js CHANGED
@@ -34,6 +34,7 @@
34
  const openHistoryBtn = document.getElementById("open-history-btn");
35
  const historyBackBtn = document.getElementById("history-back-btn");
36
  const historyFullList = document.getElementById("history-full-list");
 
37
  const historySearchInput = document.getElementById("history-search");
38
  const chatThread = document.getElementById("chat-thread");
39
  const waitingCard = document.getElementById("waiting-card");
@@ -56,17 +57,7 @@
56
 
57
  function showStep(stepNumber) {
58
  document.querySelectorAll(".step").forEach(function (section) {
59
- const isActive = section.dataset.step === String(stepNumber);
60
- section.classList.toggle("active", isActive);
61
- // Move focus to the first heading or focusable element in the
62
- // newly shown step so keyboard users don't get stranded at
63
- // wherever the trigger element was.
64
- if (isActive) {
65
- requestAnimationFrame(function () {
66
- const target = section.querySelector("h2, h3, [tabindex='0'], button, a, input");
67
- if (target) target.focus({ preventScroll: false });
68
- });
69
- }
70
  });
71
  }
72
 
@@ -420,8 +411,6 @@
420
 
421
  // Past messages for this session.
422
  let cachedHistoryItems = [];
423
- let historyStatusFilter = "all"; // "all" | "waiting" | "answered"
424
- let historyScrollY = 0; // remembered scroll offset for Back navigation
425
 
426
  function buildHistoryRow(item, index) {
427
  const row = document.createElement("div");
@@ -433,14 +422,9 @@
433
  const badgeClass = answered ? "answered" : "waiting";
434
  const badgeLabel = answered ? "Answered" : "Waiting for reply";
435
  const timeLabel = window.formatRelativeTime ? window.formatRelativeTime(item.timestamp) : "";
436
- // Descriptive aria-label so the row is announced meaningfully,
437
- // e.g. "Answered, 2 hours ago: I have a fever..." rather than
438
- // a string of badge text + visual metadata read in random order.
439
- const ariaLabel = [badgeLabel, timeLabel, item.input_text].filter(Boolean).join(": ");
440
- row.setAttribute("aria-label", ariaLabel);
441
  row.innerHTML =
442
  '<div class="result-label">#' + escapeHtml(item.id) +
443
- ' <span class="status-badge ' + badgeClass + '" aria-hidden="true">' + badgeLabel + "</span>" +
444
  ' <span class="timestamp">' + escapeHtml(timeLabel) + "</span></div>" +
445
  '<div class="result-text">' + escapeHtml(item.input_text) + "</div>";
446
  row.addEventListener("click", function () {
@@ -481,62 +465,34 @@
481
  cachedHistoryItems = [];
482
  }
483
 
484
- // If the full history view is currently visible (step === "history"),
485
- // re-render it in place so status badges update immediately when a
486
- // reply arrives via polling, without requiring the patient to close
487
- // and reopen the view.
488
- const historyStep = document.querySelector(".step[data-step='history']");
489
- if (historyStep && historyStep.classList.contains("active")) {
490
- renderFullHistoryList(historySearchInput.value);
491
- } else {
492
- renderFullHistoryList(historySearchInput.value);
493
- }
494
  }
495
 
496
  // Dedicated history view: renders from the cache above (instant), so
497
  // opening it never flashes empty while a fresh fetch is in flight.
498
- // Applies both the active status filter and the text search query.
499
  function renderFullHistoryList(filterText) {
500
  const query = (filterText || "").trim().toLowerCase();
501
-
502
- let filtered = cachedHistoryItems;
503
-
504
- if (historyStatusFilter === "waiting") {
505
- filtered = filtered.filter(function (item) { return !item.translated_response; });
506
- } else if (historyStatusFilter === "answered") {
507
- filtered = filtered.filter(function (item) { return Boolean(item.translated_response); });
508
- }
509
-
510
- if (query) {
511
- filtered = filtered.filter(function (item) {
512
- return (item.input_text || "").toLowerCase().indexOf(query) !== -1;
513
- });
514
- }
515
 
516
  historyFullList.innerHTML = "";
517
- const emptyState = document.getElementById("history-empty-state");
518
- const emptyTitle = document.getElementById("history-empty-title");
519
- const emptyBody = document.getElementById("history-empty-body");
520
 
521
  if (!cachedHistoryItems.length) {
522
- emptyTitle.textContent = "No messages yet";
523
- emptyBody.textContent = "Your consultations will appear here once you've sent one.";
524
- emptyState.style.display = "block";
525
  return;
526
  }
527
 
528
  if (!filtered.length) {
529
- emptyTitle.textContent = query ? "No matches" : "Nothing here";
530
- emptyBody.textContent = query
531
- ? "No messages match that search."
532
- : historyStatusFilter === "waiting"
533
- ? "No consultations are still waiting for a reply."
534
- : "No answered consultations yet.";
535
- emptyState.style.display = "block";
536
  return;
537
  }
538
 
539
- emptyState.style.display = "none";
540
  filtered.forEach(function (item, index) {
541
  historyFullList.appendChild(buildHistoryRow(item, index));
542
  });
@@ -590,17 +546,11 @@
590
 
591
  openHistoryBtn.addEventListener("click", function () {
592
  clearBanner();
593
- historySearchInput.value = "";
594
  showStep("history");
595
  loadHistory();
596
- // Restore scroll position from the last visit to this view
597
- requestAnimationFrame(function () {
598
- window.scrollTo(0, historyScrollY);
599
- });
600
  });
601
 
602
  historyBackBtn.addEventListener("click", function () {
603
- historyScrollY = window.scrollY;
604
  showStep(1);
605
  });
606
 
@@ -608,23 +558,6 @@
608
  renderFullHistoryList(historySearchInput.value);
609
  });
610
 
611
- // Status filter chips — set initial aria-pressed state
612
- document.querySelectorAll("#history-filter-chips .filter-chip").forEach(function (c) {
613
- c.setAttribute("aria-pressed", c.classList.contains("active") ? "true" : "false");
614
- });
615
-
616
- document.getElementById("history-filter-chips").addEventListener("click", function (event) {
617
- const chip = event.target.closest(".filter-chip");
618
- if (!chip) return;
619
- historyStatusFilter = chip.dataset.filter;
620
- document.querySelectorAll("#history-filter-chips .filter-chip").forEach(function (c) {
621
- const active = c === chip;
622
- c.classList.toggle("active", active);
623
- c.setAttribute("aria-pressed", active ? "true" : "false");
624
- });
625
- renderFullHistoryList(historySearchInput.value);
626
- });
627
-
628
  // Start a new conversation: ends the current session server-side and
629
  // resets the page back to language selection.
630
  newConversationBtn.addEventListener("click", async function () {
@@ -639,6 +572,7 @@
639
  selectedLanguage = null;
640
  recordedBlob = null;
641
  currentInteractionId = null;
 
642
  document.getElementById("patient-text").value = "";
643
  document.getElementById("response-card").style.display = "none";
644
  waitingCard.style.display = "block";
@@ -648,6 +582,7 @@
648
  transcribingPanel.style.display = "none";
649
  listeningPanel.style.display = "none";
650
  inputPanel.style.display = "block";
 
651
  setSubmitLabel("Send to provider");
652
  languageGrid.querySelectorAll(".language-option").forEach(function (el) {
653
  el.setAttribute("aria-pressed", "false");
@@ -655,7 +590,9 @@
655
  toStep2Btn.disabled = true;
656
  clearBanner();
657
  showStep(1);
658
- loadHistory();
 
 
659
  showToast("New conversation started");
660
  });
661
 
 
34
  const openHistoryBtn = document.getElementById("open-history-btn");
35
  const historyBackBtn = document.getElementById("history-back-btn");
36
  const historyFullList = document.getElementById("history-full-list");
37
+ const historyEmptyText = document.getElementById("history-empty-text");
38
  const historySearchInput = document.getElementById("history-search");
39
  const chatThread = document.getElementById("chat-thread");
40
  const waitingCard = document.getElementById("waiting-card");
 
57
 
58
  function showStep(stepNumber) {
59
  document.querySelectorAll(".step").forEach(function (section) {
60
+ section.classList.toggle("active", section.dataset.step === String(stepNumber));
 
 
 
 
 
 
 
 
 
 
61
  });
62
  }
63
 
 
411
 
412
  // Past messages for this session.
413
  let cachedHistoryItems = [];
 
 
414
 
415
  function buildHistoryRow(item, index) {
416
  const row = document.createElement("div");
 
422
  const badgeClass = answered ? "answered" : "waiting";
423
  const badgeLabel = answered ? "Answered" : "Waiting for reply";
424
  const timeLabel = window.formatRelativeTime ? window.formatRelativeTime(item.timestamp) : "";
 
 
 
 
 
425
  row.innerHTML =
426
  '<div class="result-label">#' + escapeHtml(item.id) +
427
+ ' <span class="status-badge ' + badgeClass + '">' + badgeLabel + "</span>" +
428
  ' <span class="timestamp">' + escapeHtml(timeLabel) + "</span></div>" +
429
  '<div class="result-text">' + escapeHtml(item.input_text) + "</div>";
430
  row.addEventListener("click", function () {
 
465
  cachedHistoryItems = [];
466
  }
467
 
468
+ renderFullHistoryList(historySearchInput.value);
 
 
 
 
 
 
 
 
 
469
  }
470
 
471
  // Dedicated history view: renders from the cache above (instant), so
472
  // opening it never flashes empty while a fresh fetch is in flight.
 
473
  function renderFullHistoryList(filterText) {
474
  const query = (filterText || "").trim().toLowerCase();
475
+ const filtered = query
476
+ ? cachedHistoryItems.filter(function (item) {
477
+ return (item.input_text || "").toLowerCase().indexOf(query) !== -1;
478
+ })
479
+ : cachedHistoryItems;
 
 
 
 
 
 
 
 
 
480
 
481
  historyFullList.innerHTML = "";
 
 
 
482
 
483
  if (!cachedHistoryItems.length) {
484
+ historyEmptyText.textContent = "You haven't sent any messages yet.";
485
+ historyEmptyText.style.display = "block";
 
486
  return;
487
  }
488
 
489
  if (!filtered.length) {
490
+ historyEmptyText.textContent = "No messages match your search.";
491
+ historyEmptyText.style.display = "block";
 
 
 
 
 
492
  return;
493
  }
494
 
495
+ historyEmptyText.style.display = "none";
496
  filtered.forEach(function (item, index) {
497
  historyFullList.appendChild(buildHistoryRow(item, index));
498
  });
 
546
 
547
  openHistoryBtn.addEventListener("click", function () {
548
  clearBanner();
 
549
  showStep("history");
550
  loadHistory();
 
 
 
 
551
  });
552
 
553
  historyBackBtn.addEventListener("click", function () {
 
554
  showStep(1);
555
  });
556
 
 
558
  renderFullHistoryList(historySearchInput.value);
559
  });
560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  // Start a new conversation: ends the current session server-side and
562
  // resets the page back to language selection.
563
  newConversationBtn.addEventListener("click", async function () {
 
572
  selectedLanguage = null;
573
  recordedBlob = null;
574
  currentInteractionId = null;
575
+ cachedHistoryItems = [];
576
  document.getElementById("patient-text").value = "";
577
  document.getElementById("response-card").style.display = "none";
578
  waitingCard.style.display = "block";
 
582
  transcribingPanel.style.display = "none";
583
  listeningPanel.style.display = "none";
584
  inputPanel.style.display = "block";
585
+ historyCard.style.display = "none";
586
  setSubmitLabel("Send to provider");
587
  languageGrid.querySelectorAll(".language-option").forEach(function (el) {
588
  el.setAttribute("aria-pressed", "false");
 
590
  toStep2Btn.disabled = true;
591
  clearBanner();
592
  showStep(1);
593
+ // Do not call loadHistory() here. end-session clears the server-side
594
+ // session so a /history fetch immediately after always returns empty.
595
+ // History reloads naturally after the next message is submitted.
596
  showToast("New conversation started");
597
  });
598