Upload 2 files
Browse files- static/js/patient.js +25 -4
- static/js/provider.js +19 -4
static/js/patient.js
CHANGED
|
@@ -56,7 +56,17 @@
|
|
| 56 |
|
| 57 |
function showStep(stepNumber) {
|
| 58 |
document.querySelectorAll(".step").forEach(function (section) {
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
});
|
| 61 |
}
|
| 62 |
|
|
@@ -423,9 +433,14 @@
|
|
| 423 |
const badgeClass = answered ? "answered" : "waiting";
|
| 424 |
const badgeLabel = answered ? "Answered" : "Waiting for reply";
|
| 425 |
const timeLabel = window.formatRelativeTime ? window.formatRelativeTime(item.timestamp) : "";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
row.innerHTML =
|
| 427 |
'<div class="result-label">#' + escapeHtml(item.id) +
|
| 428 |
-
' <span class="status-badge ' + badgeClass + '">' + badgeLabel + "</span>" +
|
| 429 |
' <span class="timestamp">' + escapeHtml(timeLabel) + "</span></div>" +
|
| 430 |
'<div class="result-text">' + escapeHtml(item.input_text) + "</div>";
|
| 431 |
row.addEventListener("click", function () {
|
|
@@ -593,13 +608,19 @@
|
|
| 593 |
renderFullHistoryList(historySearchInput.value);
|
| 594 |
});
|
| 595 |
|
| 596 |
-
// Status filter chips
|
|
|
|
|
|
|
|
|
|
|
|
|
| 597 |
document.getElementById("history-filter-chips").addEventListener("click", function (event) {
|
| 598 |
const chip = event.target.closest(".filter-chip");
|
| 599 |
if (!chip) return;
|
| 600 |
historyStatusFilter = chip.dataset.filter;
|
| 601 |
document.querySelectorAll("#history-filter-chips .filter-chip").forEach(function (c) {
|
| 602 |
-
|
|
|
|
|
|
|
| 603 |
});
|
| 604 |
renderFullHistoryList(historySearchInput.value);
|
| 605 |
});
|
|
|
|
| 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 |
|
|
|
|
| 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 () {
|
|
|
|
| 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 |
});
|
static/js/provider.js
CHANGED
|
@@ -146,14 +146,23 @@
|
|
| 146 |
const isActive = Boolean(activeItem) && activeItem.id === item.id;
|
| 147 |
const badgeClass = answered ? "answered" : "waiting";
|
| 148 |
const badgeLabel = answered ? "Answered" : (isActive ? "In progress" : "#" + item.id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
row.innerHTML =
|
| 150 |
-
'<span class="queue-avatar">' + escapeHtml(item.detected_language.charAt(0).toUpperCase()) + '</span>' +
|
| 151 |
'<span class="queue-body">' +
|
| 152 |
'<span class="queue-top-row">' +
|
| 153 |
'<span class="queue-lang">' + escapeHtml(item.detected_language) + '</span>' +
|
| 154 |
'<span class="queue-top-right">' +
|
| 155 |
'<span class="timestamp">' + escapeHtml(timeLabel) + '</span>' +
|
| 156 |
-
'<span class="status-badge ' + badgeClass + '">' + escapeHtml(badgeLabel) + '</span>' +
|
| 157 |
'</span>' +
|
| 158 |
'</span>' +
|
| 159 |
'<span class="queue-preview">' + escapeHtml(item.translated_text) + '</span>' +
|
|
@@ -272,13 +281,19 @@
|
|
| 272 |
renderQueueList();
|
| 273 |
});
|
| 274 |
|
| 275 |
-
// Language filter chips (completed tab only)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
document.getElementById("language-filter-chips").addEventListener("click", function (event) {
|
| 277 |
const chip = event.target.closest(".filter-chip");
|
| 278 |
if (!chip) return;
|
| 279 |
completedLanguageFilter = chip.dataset.filter;
|
| 280 |
document.querySelectorAll("#language-filter-chips .filter-chip").forEach(function (c) {
|
| 281 |
-
|
|
|
|
|
|
|
| 282 |
});
|
| 283 |
renderQueueList();
|
| 284 |
});
|
|
|
|
| 146 |
const isActive = Boolean(activeItem) && activeItem.id === item.id;
|
| 147 |
const badgeClass = answered ? "answered" : "waiting";
|
| 148 |
const badgeLabel = answered ? "Answered" : (isActive ? "In progress" : "#" + item.id);
|
| 149 |
+
// Descriptive aria-label so screen readers announce "Yoruba, just now,
|
| 150 |
+
// [preview text]" rather than the meaningless default "button".
|
| 151 |
+
const ariaLabel = [
|
| 152 |
+
capitalize(item.detected_language),
|
| 153 |
+
timeLabel,
|
| 154 |
+
answered ? "Answered" : "Waiting for reply",
|
| 155 |
+
item.translated_text
|
| 156 |
+
].filter(Boolean).join(", ");
|
| 157 |
+
row.setAttribute("aria-label", ariaLabel);
|
| 158 |
row.innerHTML =
|
| 159 |
+
'<span class="queue-avatar" aria-hidden="true">' + escapeHtml(item.detected_language.charAt(0).toUpperCase()) + '</span>' +
|
| 160 |
'<span class="queue-body">' +
|
| 161 |
'<span class="queue-top-row">' +
|
| 162 |
'<span class="queue-lang">' + escapeHtml(item.detected_language) + '</span>' +
|
| 163 |
'<span class="queue-top-right">' +
|
| 164 |
'<span class="timestamp">' + escapeHtml(timeLabel) + '</span>' +
|
| 165 |
+
'<span class="status-badge ' + badgeClass + '" aria-hidden="true">' + escapeHtml(badgeLabel) + '</span>' +
|
| 166 |
'</span>' +
|
| 167 |
'</span>' +
|
| 168 |
'<span class="queue-preview">' + escapeHtml(item.translated_text) + '</span>' +
|
|
|
|
| 281 |
renderQueueList();
|
| 282 |
});
|
| 283 |
|
| 284 |
+
// Language filter chips (completed tab only) — set initial aria-pressed
|
| 285 |
+
document.querySelectorAll("#language-filter-chips .filter-chip").forEach(function (c) {
|
| 286 |
+
c.setAttribute("aria-pressed", c.classList.contains("active") ? "true" : "false");
|
| 287 |
+
});
|
| 288 |
+
|
| 289 |
document.getElementById("language-filter-chips").addEventListener("click", function (event) {
|
| 290 |
const chip = event.target.closest(".filter-chip");
|
| 291 |
if (!chip) return;
|
| 292 |
completedLanguageFilter = chip.dataset.filter;
|
| 293 |
document.querySelectorAll("#language-filter-chips .filter-chip").forEach(function (c) {
|
| 294 |
+
const active = c === chip;
|
| 295 |
+
c.classList.toggle("active", active);
|
| 296 |
+
c.setAttribute("aria-pressed", active ? "true" : "false");
|
| 297 |
});
|
| 298 |
renderQueueList();
|
| 299 |
});
|