pantdipendra commited on
Commit
73d11b4
·
verified ·
1 Parent(s): ef6a55e
Files changed (1) hide show
  1. index.html +27 -37
index.html CHANGED
@@ -6,6 +6,17 @@
6
  <title>Secondary Use of Health Records Navigator</title>
7
  <link rel="stylesheet" href="style.css" />
8
  <script src="app.js" defer></script>
 
 
 
 
 
 
 
 
 
 
 
9
  </head>
10
  <body>
11
  <header>
@@ -108,7 +119,6 @@
108
  refs: [],
109
  },
110
  ];
111
-
112
  const STEPS = [
113
  {
114
  num: 1,
@@ -681,8 +691,6 @@
681
  ],
682
  },
683
  ];
684
-
685
-
686
  /* Flow questions derived from the flowchart */
687
  const FLOW = {
688
  1: {
@@ -712,7 +720,6 @@
712
  8: { q: "Any gaps found?", onYes: 4, onNo: 9 },
713
  9: { q: "Will you retain or reuse data beyond approved plan?", onYes: 1, onNo: "end" },
714
  };
715
-
716
  /* ------------ State ------------ */
717
  const STORAGE = "suhr_flow_v1";
718
  const $ = (s) => document.querySelector(s);
@@ -726,7 +733,6 @@
726
  subQ: 0,
727
  reachedEnd: false, // track if user ever reached the end screen
728
  };
729
-
730
  /* ------------ Purpose UI ------------ */
731
  function renderPurposes() {
732
  const host = $("#purposeList");
@@ -780,7 +786,6 @@
780
  $("#anonMsg").classList.toggle("hidden", state.purpose !== "anon");
781
  }
782
  }
783
-
784
  /* ------------ Timeline (accordion) ------------ */
785
  function renderTimeline() {
786
  const host = $("#timeline");
@@ -790,7 +795,6 @@
790
  for (let i = 0; i < v; i++) addStep(host, STEPS[i], i + 1);
791
  expandDetailsForStep(state.step);
792
  }
793
-
794
  function addStep(host, step, idx) {
795
  const done = isStepComplete(step);
796
  const sec = document.createElement("section");
@@ -819,13 +823,27 @@
819
  const li = document.createElement("li");
820
  li.className = "li";
821
  const id = `${step.key}_${it.k}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
822
  li.innerHTML = `
823
  <div class="letters">${it.k}</div>
824
  <label for="${id}">${it.label}${
825
  it.req
826
  ? ` <span class='req'>★</span>`
827
  : " <span class='opt'>(opt)</span>"
828
- }</label>
829
  <div style="display:flex;align-items:center;gap:8px">
830
  <input class="chk" type="checkbox" id="${id}" ${
831
  checked ? "checked" : ""
@@ -835,7 +853,6 @@
835
  li.querySelector(".chk").addEventListener("change", (e) => {
836
  (state.checks[step.key] ??= {})[it.k] = e.target.checked;
837
  save(true);
838
-
839
  const nowDone = isStepComplete(step);
840
  $("#badge_" + step.key).textContent = nowDone
841
  ? "Complete ✓"
@@ -846,10 +863,8 @@
846
  } else if (!nowDone) {
847
  sec.classList.remove("done");
848
  }
849
-
850
  renderDots(state.visible); // refresh top dots' done state
851
  updateProgress();
852
-
853
  // If the end screen is visible (or was reached before), update/show its message when all steps are complete.
854
  if ($("#finish").classList.contains("show")) {
855
  refreshFinishBanner();
@@ -859,16 +874,13 @@
859
  });
860
  ul.appendChild(li);
861
  });
862
-
863
  // "Details" toggle
864
  sec.querySelector(".toggle").addEventListener("click", () => {
865
  const pane = document.getElementById("fold_" + step.key);
866
  pane.classList.toggle("fold");
867
  });
868
-
869
  host.appendChild(sec);
870
  }
871
-
872
  /* Expand current step details and collapse others while asking each question */
873
  function expandDetailsForStep(stepNum) {
874
  if (!stepNum) return;
@@ -879,7 +891,6 @@
879
  const pane = document.getElementById("fold_" + current.key);
880
  if (pane) pane.classList.remove("fold");
881
  }
882
-
883
  /* ------------ Dots / progress ------------ */
884
  function renderDots(visible) {
885
  const d = $("#dots");
@@ -930,32 +941,26 @@
930
  { duration: 800 }
931
  );
932
  }
933
-
934
  /* ------------ Flow controller (Yes/No) ------------ */
935
  const flow = $("#flow"),
936
  qtxt = $("#qtxt"),
937
  yesBtn = $("#yesBtn"),
938
  noBtn = $("#noBtn");
939
-
940
  function showFlow() {
941
  flow.classList.remove("hidden");
942
  }
943
  function hideFlow() {
944
  flow.classList.add("hidden");
945
  }
946
-
947
  function askCurrent() {
948
  // Reset finish visibility text live region while navigating
949
  $("#finish").classList.remove("show");
950
-
951
  if (state.purpose === "anon" || !state.step) {
952
  hideFlow();
953
  return;
954
  }
955
-
956
  // Ensure the current step's checklist is expanded (and others collapsed)
957
  expandDetailsForStep(state.step);
958
-
959
  // Step 7 special sequence
960
  if (state.step === 7) {
961
  const seq = FLOW[7];
@@ -987,7 +992,6 @@
987
  };
988
  return;
989
  }
990
-
991
  // Regular step question
992
  const node = FLOW[state.step];
993
  if (!node) {
@@ -998,7 +1002,6 @@
998
  yesBtn.onclick = () => goto(node.onYes);
999
  noBtn.onclick = () => goto(node.onNo);
1000
  }
1001
-
1002
  function goto(dest) {
1003
  if (dest === "end") {
1004
  finish();
@@ -1014,7 +1017,6 @@
1014
  scrollToStep(state.step);
1015
  save(true);
1016
  }
1017
-
1018
  /* Called when step 1 completes to auto reveal step 2 */
1019
  function advanceToStep(n) {
1020
  if (state.visible < n) {
@@ -1028,7 +1030,6 @@
1028
  askCurrent();
1029
  save(true);
1030
  }
1031
-
1032
  /* ------------ Helpers ------------ */
1033
  function isStepComplete(step) {
1034
  const d = state.checks[step.key] || {};
@@ -1057,19 +1058,16 @@
1057
  const pct = total ? Math.round((100 * done) / total) : 0;
1058
  $("#pbar").style.width = pct + "%";
1059
  }
1060
-
1061
  /* ------------ Finish ------------ */
1062
  function finish() {
1063
  hideFlow();
1064
  state.reachedEnd = true;
1065
  save(true);
1066
-
1067
  const ok = allStepsComplete();
1068
  const finishEl = $("#finish");
1069
  const titleEl = $("#finishTitle");
1070
  const subEl = $("#finishSub");
1071
  const confettiHost = $("#confetti");
1072
-
1073
  if (ok) {
1074
  titleEl.textContent = "End 🎉";
1075
  subEl.textContent = "All flow checks passed.";
@@ -1082,14 +1080,12 @@
1082
  }
1083
  finishEl.classList.add("show");
1084
  }
1085
-
1086
  function refreshFinishBanner() {
1087
  // Update finish banner live without toggling visibility
1088
  const ok = allStepsComplete();
1089
  const titleEl = $("#finishTitle");
1090
  const subEl = $("#finishSub");
1091
  const confettiHost = $("#confetti");
1092
-
1093
  if (ok) {
1094
  titleEl.textContent = "End 🎉";
1095
  subEl.textContent = "All flow checks passed.";
@@ -1101,7 +1097,6 @@
1101
  confettiHost.innerHTML = "";
1102
  }
1103
  }
1104
-
1105
  function confetti(n) {
1106
  const host = $("#confetti");
1107
  host.innerHTML = "";
@@ -1114,7 +1109,6 @@
1114
  host.appendChild(piece);
1115
  }
1116
  }
1117
-
1118
  /* ------------ Save/Load ------------ */
1119
  function save(quiet = false) {
1120
  state.savedAt = Date.now();
@@ -1127,7 +1121,6 @@
1127
  if (raw) Object.assign(state, JSON.parse(raw));
1128
  } catch (e) {}
1129
  }
1130
-
1131
  /* ------------ Clear / Reset ------------ */
1132
  function clearAll() {
1133
  try {
@@ -1140,7 +1133,6 @@
1140
  state.step = 0;
1141
  state.subQ = 0;
1142
  state.reachedEnd = false;
1143
-
1144
  renderPurposes();
1145
  renderDots(0);
1146
  $("#timeline").innerHTML = "";
@@ -1149,7 +1141,6 @@
1149
  hideFlow();
1150
  updateProgress();
1151
  }
1152
-
1153
  /* ------------ Boot ------------ */
1154
  load();
1155
  renderPurposes();
@@ -1164,7 +1155,6 @@
1164
  hideFlow();
1165
  }
1166
  updateProgress();
1167
-
1168
  // Clear button handler
1169
  document.getElementById("clearBtn").addEventListener("click", () => {
1170
  const ok = confirm(
@@ -1174,4 +1164,4 @@
1174
  });
1175
  </script>
1176
  </body>
1177
- </html>
 
6
  <title>Secondary Use of Health Records Navigator</title>
7
  <link rel="stylesheet" href="style.css" />
8
  <script src="app.js" defer></script>
9
+
10
+ <!-- Added tiny style for inline refs -->
11
+ <style>
12
+ .refs {
13
+ font-size: 0.85em;
14
+ opacity: 0.9;
15
+ margin-left: 4px;
16
+ display: inline;
17
+ }
18
+ .refs a { text-decoration: underline; }
19
+ </style>
20
  </head>
21
  <body>
22
  <header>
 
119
  refs: [],
120
  },
121
  ];
 
122
  const STEPS = [
123
  {
124
  num: 1,
 
691
  ],
692
  },
693
  ];
 
 
694
  /* Flow questions derived from the flowchart */
695
  const FLOW = {
696
  1: {
 
720
  8: { q: "Any gaps found?", onYes: 4, onNo: 9 },
721
  9: { q: "Will you retain or reuse data beyond approved plan?", onYes: 1, onNo: "end" },
722
  };
 
723
  /* ------------ State ------------ */
724
  const STORAGE = "suhr_flow_v1";
725
  const $ = (s) => document.querySelector(s);
 
733
  subQ: 0,
734
  reachedEnd: false, // track if user ever reached the end screen
735
  };
 
736
  /* ------------ Purpose UI ------------ */
737
  function renderPurposes() {
738
  const host = $("#purposeList");
 
786
  $("#anonMsg").classList.toggle("hidden", state.purpose !== "anon");
787
  }
788
  }
 
789
  /* ------------ Timeline (accordion) ------------ */
790
  function renderTimeline() {
791
  const host = $("#timeline");
 
795
  for (let i = 0; i < v; i++) addStep(host, STEPS[i], i + 1);
796
  expandDetailsForStep(state.step);
797
  }
 
798
  function addStep(host, step, idx) {
799
  const done = isStepComplete(step);
800
  const sec = document.createElement("section");
 
823
  const li = document.createElement("li");
824
  li.className = "li";
825
  const id = `${step.key}_${it.k}`;
826
+
827
+ /* Build inline, lowercase, clickable refs */
828
+ const refsHtml =
829
+ it.refs && it.refs.length
830
+ ? ` <small class="refs">` +
831
+ it.refs
832
+ .map(
833
+ (r) =>
834
+ `<a href="${r.url}" target="_blank" rel="noreferrer noopener">${(r.title || r.url).toLowerCase()}</a>`
835
+ )
836
+ .join(" • ") +
837
+ `</small>`
838
+ : "";
839
+
840
  li.innerHTML = `
841
  <div class="letters">${it.k}</div>
842
  <label for="${id}">${it.label}${
843
  it.req
844
  ? ` <span class='req'>★</span>`
845
  : " <span class='opt'>(opt)</span>"
846
+ }${refsHtml}</label>
847
  <div style="display:flex;align-items:center;gap:8px">
848
  <input class="chk" type="checkbox" id="${id}" ${
849
  checked ? "checked" : ""
 
853
  li.querySelector(".chk").addEventListener("change", (e) => {
854
  (state.checks[step.key] ??= {})[it.k] = e.target.checked;
855
  save(true);
 
856
  const nowDone = isStepComplete(step);
857
  $("#badge_" + step.key).textContent = nowDone
858
  ? "Complete ✓"
 
863
  } else if (!nowDone) {
864
  sec.classList.remove("done");
865
  }
 
866
  renderDots(state.visible); // refresh top dots' done state
867
  updateProgress();
 
868
  // If the end screen is visible (or was reached before), update/show its message when all steps are complete.
869
  if ($("#finish").classList.contains("show")) {
870
  refreshFinishBanner();
 
874
  });
875
  ul.appendChild(li);
876
  });
 
877
  // "Details" toggle
878
  sec.querySelector(".toggle").addEventListener("click", () => {
879
  const pane = document.getElementById("fold_" + step.key);
880
  pane.classList.toggle("fold");
881
  });
 
882
  host.appendChild(sec);
883
  }
 
884
  /* Expand current step details and collapse others while asking each question */
885
  function expandDetailsForStep(stepNum) {
886
  if (!stepNum) return;
 
891
  const pane = document.getElementById("fold_" + current.key);
892
  if (pane) pane.classList.remove("fold");
893
  }
 
894
  /* ------------ Dots / progress ------------ */
895
  function renderDots(visible) {
896
  const d = $("#dots");
 
941
  { duration: 800 }
942
  );
943
  }
 
944
  /* ------------ Flow controller (Yes/No) ------------ */
945
  const flow = $("#flow"),
946
  qtxt = $("#qtxt"),
947
  yesBtn = $("#yesBtn"),
948
  noBtn = $("#noBtn");
 
949
  function showFlow() {
950
  flow.classList.remove("hidden");
951
  }
952
  function hideFlow() {
953
  flow.classList.add("hidden");
954
  }
 
955
  function askCurrent() {
956
  // Reset finish visibility text live region while navigating
957
  $("#finish").classList.remove("show");
 
958
  if (state.purpose === "anon" || !state.step) {
959
  hideFlow();
960
  return;
961
  }
 
962
  // Ensure the current step's checklist is expanded (and others collapsed)
963
  expandDetailsForStep(state.step);
 
964
  // Step 7 special sequence
965
  if (state.step === 7) {
966
  const seq = FLOW[7];
 
992
  };
993
  return;
994
  }
 
995
  // Regular step question
996
  const node = FLOW[state.step];
997
  if (!node) {
 
1002
  yesBtn.onclick = () => goto(node.onYes);
1003
  noBtn.onclick = () => goto(node.onNo);
1004
  }
 
1005
  function goto(dest) {
1006
  if (dest === "end") {
1007
  finish();
 
1017
  scrollToStep(state.step);
1018
  save(true);
1019
  }
 
1020
  /* Called when step 1 completes to auto reveal step 2 */
1021
  function advanceToStep(n) {
1022
  if (state.visible < n) {
 
1030
  askCurrent();
1031
  save(true);
1032
  }
 
1033
  /* ------------ Helpers ------------ */
1034
  function isStepComplete(step) {
1035
  const d = state.checks[step.key] || {};
 
1058
  const pct = total ? Math.round((100 * done) / total) : 0;
1059
  $("#pbar").style.width = pct + "%";
1060
  }
 
1061
  /* ------------ Finish ------------ */
1062
  function finish() {
1063
  hideFlow();
1064
  state.reachedEnd = true;
1065
  save(true);
 
1066
  const ok = allStepsComplete();
1067
  const finishEl = $("#finish");
1068
  const titleEl = $("#finishTitle");
1069
  const subEl = $("#finishSub");
1070
  const confettiHost = $("#confetti");
 
1071
  if (ok) {
1072
  titleEl.textContent = "End 🎉";
1073
  subEl.textContent = "All flow checks passed.";
 
1080
  }
1081
  finishEl.classList.add("show");
1082
  }
 
1083
  function refreshFinishBanner() {
1084
  // Update finish banner live without toggling visibility
1085
  const ok = allStepsComplete();
1086
  const titleEl = $("#finishTitle");
1087
  const subEl = $("#finishSub");
1088
  const confettiHost = $("#confetti");
 
1089
  if (ok) {
1090
  titleEl.textContent = "End 🎉";
1091
  subEl.textContent = "All flow checks passed.";
 
1097
  confettiHost.innerHTML = "";
1098
  }
1099
  }
 
1100
  function confetti(n) {
1101
  const host = $("#confetti");
1102
  host.innerHTML = "";
 
1109
  host.appendChild(piece);
1110
  }
1111
  }
 
1112
  /* ------------ Save/Load ------------ */
1113
  function save(quiet = false) {
1114
  state.savedAt = Date.now();
 
1121
  if (raw) Object.assign(state, JSON.parse(raw));
1122
  } catch (e) {}
1123
  }
 
1124
  /* ------------ Clear / Reset ------------ */
1125
  function clearAll() {
1126
  try {
 
1133
  state.step = 0;
1134
  state.subQ = 0;
1135
  state.reachedEnd = false;
 
1136
  renderPurposes();
1137
  renderDots(0);
1138
  $("#timeline").innerHTML = "";
 
1141
  hideFlow();
1142
  updateProgress();
1143
  }
 
1144
  /* ------------ Boot ------------ */
1145
  load();
1146
  renderPurposes();
 
1155
  hideFlow();
1156
  }
1157
  updateProgress();
 
1158
  // Clear button handler
1159
  document.getElementById("clearBtn").addEventListener("click", () => {
1160
  const ok = confirm(
 
1164
  });
1165
  </script>
1166
  </body>
1167
+ </html>