WebashalarForML commited on
Commit
9808fe5
·
verified ·
1 Parent(s): 4fd5a44

Update static/frontend.html

Browse files
Files changed (1) hide show
  1. static/frontend.html +127 -129
static/frontend.html CHANGED
@@ -2,154 +2,152 @@
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>Health Reports Processor</title>
7
  <style>
8
- body {
9
- font-family: Arial, sans-serif;
10
- margin: 2rem;
11
- max-width: 800px;
12
- }
13
- label {
14
- display: block;
15
- margin-top: 1rem;
16
- font-weight: bold;
17
- }
18
- input, textarea, button {
19
- width: 100%;
20
- padding: 0.5rem;
21
- margin-top: 0.25rem;
22
- box-sizing: border-box;
23
- font-size: 1rem;
24
- }
25
- button {
26
- margin-top: 1rem;
27
- cursor: pointer;
28
- }
29
- pre {
30
- background: #f4f4f4;
31
- padding: 1rem;
32
- overflow-x: auto;
33
- white-space: pre-wrap;
34
- word-wrap: break-word;
35
- border: 1px solid #ccc;
36
- margin-top: 1rem;
37
- }
38
- .error {
39
- color: red;
40
- margin-top: 1rem;
41
- }
42
  </style>
43
  </head>
44
  <body>
45
- <h1>Health Reports Processor</h1>
46
-
47
- <!-- Upload form -->
48
- <form id="uploadForm" enctype="multipart/form-data">
49
- <label for="uploadPatientId">Patient ID:</label>
50
- <input type="text" id="uploadPatientId" name="patient_id" required />
51
-
52
- <label for="files">Upload Reports:</label>
53
- <input type="file" id="files" name="files" multiple required />
54
-
55
- <button type="submit">Upload Reports</button>
56
- </form>
57
-
58
- <div id="uploadResult"></div>
59
-
60
- <hr />
61
-
62
- <!-- Existing process reports form -->
63
- <form id="reportForm">
64
- <label for="patientId">Patient ID:</label>
65
- <input type="text" id="patientId" name="patientId" required />
66
-
67
- <label for="filenames">Filenames (comma-separated):</label>
68
- <input type="text" id="filenames" name="filenames" placeholder="e.g. cbc.pdf, thyroid.pdf" required />
69
-
70
- <button type="submit">Process Reports</button>
71
- </form>
72
-
73
- <div id="result"></div>
 
 
74
 
75
  <script>
76
- // Upload form
77
- const uploadForm = document.getElementById('uploadForm');
78
- const uploadResult = document.getElementById('uploadResult');
79
-
80
- uploadForm.addEventListener('submit', async (e) => {
81
- e.preventDefault();
82
- uploadResult.innerHTML = '';
83
-
84
- const patientId = document.getElementById('uploadPatientId').value.trim();
85
- const filesInput = document.getElementById('files');
86
-
87
- if (!patientId || filesInput.files.length === 0) {
88
- uploadResult.innerHTML = '<p class="error">Please enter a Patient ID and select at least one file.</p>';
89
- return;
90
- }
91
-
92
- const formData = new FormData();
93
- formData.append('patient_id', patientId);
94
- for (let f of filesInput.files) {
95
- formData.append('files', f);
96
- }
97
-
98
- try {
99
- const response = await fetch('/upload_reports', {
100
- method: 'POST',
101
- body: formData
102
- });
103
-
104
- if (!response.ok) {
105
- const errData = await response.json();
106
- uploadResult.innerHTML = `<p class="error">Error: ${errData.error || response.statusText}</p>`;
107
- return;
108
- }
109
-
110
- const data = await response.json();
111
- uploadResult.innerHTML = `<h2>Upload Result</h2><pre>${JSON.stringify(data, null, 2)}</pre>`;
112
- } catch (err) {
113
- uploadResult.innerHTML = `<p class="error">Upload failed: ${err.message}</p>`;
114
- }
115
  });
116
 
117
- // Process form
118
- const form = document.getElementById('reportForm');
119
- const resultDiv = document.getElementById('result');
120
 
121
- form.addEventListener('submit', async (e) => {
122
- e.preventDefault();
123
- resultDiv.innerHTML = '';
 
124
 
125
- const patientId = form.patientId.value.trim();
126
- const filenamesRaw = form.filenames.value.trim();
127
- if (!patientId || !filenamesRaw) {
128
- resultDiv.innerHTML = '<p class="error">Please enter both Patient ID and filenames.</p>';
129
- return;
 
 
130
  }
 
 
 
 
 
 
 
 
131
 
132
- const filenames = filenamesRaw.split(',').map(f => f.trim()).filter(f => f.length > 0);
 
 
 
133
 
134
  try {
135
- const response = await fetch('/process_reports', {
136
- method: 'POST',
137
- headers: { 'Content-Type': 'application/json' },
138
- body: JSON.stringify({ patient_id: patientId, filenames: filenames })
139
  });
 
 
140
 
141
- if (!response.ok) {
142
- const errorData = await response.json();
143
- resultDiv.innerHTML = `<p class="error">Error: ${errorData.error || response.statusText}</p>`;
144
- return;
145
- }
146
 
147
- const data = await response.json();
148
- resultDiv.innerHTML = `<h2>Processed Result</h2><pre>${JSON.stringify(data, null, 2)}</pre>`;
 
 
149
  } catch (err) {
150
- resultDiv.innerHTML = `<p class="error">Request failed: ${err.message}</p>`;
 
 
 
151
  }
152
- });
 
 
 
 
153
  </script>
154
  </body>
155
  </html>
 
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Patient Assistant Chat</title>
7
  <style>
8
+ /* your existing styles here */
9
+ :root { --bg:#0f172a; --panel:#111827; --soft:#1f2937; --text:#e5e7eb; --muted:#9ca3af; --accent:#22c55e; }
10
+ * { box-sizing: border-box; }
11
+ body { margin:0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; background: var(--bg); color: var(--text); }
12
+ .app { max-width: 900px; margin: 0 auto; padding: 20px; }
13
+ .card { background: var(--panel); border: 1px solid #242b3a; border-radius: 16px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,.25); }
14
+ .header { padding: 16px 20px; border-bottom: 1px solid #242b3a; display: flex; align-items: center; gap: 12px; }
15
+ .badge { background: #0b3b26; color: #8bf2c0; padding: 6px 10px; border-radius: 999px; font-weight: 600; font-size: 12px; letter-spacing: .3px; }
16
+ .row { display:flex; gap:12px; align-items:center; flex-wrap: wrap; }
17
+ label { font-size: 13px; color: var(--muted); }
18
+ input[type="text"] { background: var(--soft); color: var(--text); border: 1px solid #2b3346; padding: 10px 12px; border-radius: 10px; min-width: 200px; outline: none; }
19
+ input[type="text"]:focus { border-color: #374462; box-shadow: 0 0 0 3px rgba(59,130,246,.15); }
20
+ button { background: var(--accent); color: #052e19; border: none; padding: 10px 14px; border-radius: 10px; font-weight: 700; cursor: pointer; }
21
+ button.secondary { background: #334155; color: #dbeafe; }
22
+ button:disabled { opacity: .6; cursor: not-allowed; }
23
+
24
+ .chat { height: 420px; overflow-y: auto; padding: 18px; display: flex; flex-direction: column; gap: 10px; background: #0b1220; }
25
+ .msg { max-width: 80%; padding: 10px 12px; border-radius: 12px; border: 1px solid #1f2937; white-space: pre-wrap; word-break: break-word; }
26
+ .user { align-self: flex-end; background: #0b3b26; border-color: #14532d; }
27
+ .assist { align-self: flex-start; background: #111827; border-color: #1f2937; }
28
+
29
+ .composer { display: grid; grid-template-columns: 1fr auto; gap: 10px; padding: 14px; border-top: 1px solid #242b3a; background: #0b1220; }
30
+ .composer input { width: 100%; }
31
+
32
+ .state { padding: 12px 16px; border-top: 1px dashed #243044; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 12px; color: #cbd5e1; background: #0b1220; }
33
+ details > summary { cursor: pointer; }
34
+ .small { font-size: 12px; color: var(--muted); }
 
 
 
 
 
 
 
35
  </style>
36
  </head>
37
  <body>
38
+ <div class="app">
39
+ <div class="card">
40
+ <div class="header">
41
+ <span class="badge">Patient Assistant</span>
42
+ <div class="row" style="gap:8px;">
43
+ <label for="pid">Patient ID</label>
44
+ <input id="pid" type="text" placeholder="e.g. 1234" />
45
+ <button id="savePid">Save</button>
46
+ <span id="status" class="small">Disconnected</span>
47
+ </div>
48
+ </div>
49
+
50
+ <div id="chat" class="chat"></div>
51
+
52
+ <div class="composer">
53
+ <input id="message" type="text" placeholder="Type your message…" />
54
+ <button id="send">Send</button>
55
+ </div>
56
+
57
+ <div class="state">
58
+ <details>
59
+ <summary>Agent State (from backend)</summary>
60
+ <pre id="stateView">{}</pre>
61
+ </details>
62
+ </div>
63
+ </div>
64
+
65
+ <p class="small" style="margin-top:10px; opacity:.8">
66
+ Configure your Node API URL in the script below (defaults to <code>/chat</code> on the same origin).
67
+ </p>
68
+ </div>
69
 
70
  <script>
71
+ const NODE_CHAT_ENDPOINT = "/chat";
72
+
73
+ const chatEl = document.getElementById("chat");
74
+ const pidEl = document.getElementById("pid");
75
+ const savePidBtn = document.getElementById("savePid");
76
+ const msgEl = document.getElementById("message");
77
+ const sendBtn = document.getElementById("send");
78
+ const statusEl = document.getElementById("status");
79
+ const stateView = document.getElementById("stateView");
80
+
81
+ let chatHistory = [];
82
+ let patientState = {};
83
+
84
+ // Load saved patient id from localStorage
85
+ pidEl.value = localStorage.getItem("patient_id") || "";
86
+ updateStatus();
87
+
88
+ savePidBtn.addEventListener("click", () => {
89
+ localStorage.setItem("patient_id", pidEl.value.trim());
90
+ updateStatus();
91
+ msgEl.focus();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  });
93
 
94
+ sendBtn.addEventListener("click", onSend);
95
+ msgEl.addEventListener("keydown", (e) => { if (e.key === "Enter") onSend(); });
 
96
 
97
+ function updateStatus() {
98
+ const pid = (pidEl.value || "").trim();
99
+ statusEl.textContent = pid ? `Patient ${pid}` : "No patient selected";
100
+ }
101
 
102
+ function renderChat() {
103
+ chatEl.innerHTML = "";
104
+ for (const m of chatHistory) {
105
+ const div = document.createElement("div");
106
+ div.className = `msg ${m.role === "user" ? "user" : "assist"}`;
107
+ div.textContent = `${m.role === "user" ? "You" : "Assistant"}: ${m.content}`;
108
+ chatEl.appendChild(div);
109
  }
110
+ chatEl.scrollTop = chatEl.scrollHeight;
111
+ }
112
+
113
+ async function onSend() {
114
+ const patient_id = (pidEl.value || "").trim();
115
+ const message = (msgEl.value || "").trim();
116
+ if (!patient_id) { alert("Please enter Patient ID"); return; }
117
+ if (!message) return;
118
 
119
+ chatHistory.push({ role: "user", content: message });
120
+ renderChat();
121
+ msgEl.value = "";
122
+ sendBtn.disabled = true;
123
 
124
  try {
125
+ const res = await fetch(NODE_CHAT_ENDPOINT, {
126
+ method: "POST",
127
+ headers: { "Content-Type": "application/json" },
128
+ body: JSON.stringify({ patient_id, chat_history: chatHistory, patient_state: patientState })
129
  });
130
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
131
+ const data = await res.json();
132
 
133
+ const reply = data.assistant_reply || "(no reply)";
134
+ patientState = data.updated_state || patientState;
 
 
 
135
 
136
+ chatHistory.push({ role: "assistant", content: reply });
137
+ renderChat();
138
+
139
+ stateView.textContent = JSON.stringify(patientState, null, 2);
140
  } catch (err) {
141
+ chatHistory.push({ role: "assistant", content: `Error: ${err.message}` });
142
+ renderChat();
143
+ } finally {
144
+ sendBtn.disabled = false;
145
  }
146
+ }
147
+
148
+ // Initial greeting
149
+ chatHistory.push({ role: "assistant", content: "Hello! I am your patient assistant. Set your Patient ID and ask your question." });
150
+ renderChat();
151
  </script>
152
  </body>
153
  </html>