WebashalarForML commited on
Commit
798ece2
·
verified ·
1 Parent(s): 47c5ad7

Update static/frontend.html

Browse files
Files changed (1) hide show
  1. static/frontend.html +133 -138
static/frontend.html CHANGED
@@ -1,153 +1,148 @@
1
  <!DOCTYPE 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>
 
1
  <!DOCTYPE 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>
43
+
44
+ <div id="chat" class="chat"></div>
45
+
46
+ <div class="composer">
47
+ <input id="message" type="text" placeholder="Type your message…" />
48
+ <button id="send">Send</button>
49
+ </div>
50
+
51
+ <div class="state">
52
+ <details>
53
+ <summary>Agent State (from backend)</summary>
54
+ <pre id="stateView">{}</pre>
55
+ </details>
56
+ </div>
57
  </div>
 
58
 
59
+ <p class="small" style="margin-top:10px; opacity:.8">
60
+ This version allows the agent to ask for your Patient ID (PID) during the conversation.
61
+ </p>
 
 
 
 
 
 
 
 
 
 
62
  </div>
63
 
64
+ <script>
65
+ const NODE_CHAT_ENDPOINT = "/chat";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ const chatEl = document.getElementById("chat");
68
+ const msgEl = document.getElementById("message");
69
+ const sendBtn = document.getElementById("send");
70
+ const stateView = document.getElementById("stateView");
71
 
72
+ let chatHistory = JSON.parse(localStorage.getItem("chatHistory")) || [];
73
+ let patientState = JSON.parse(localStorage.getItem("patientState")) || {};
74
+
75
+ sendBtn.addEventListener("click", onSend);
76
+ msgEl.addEventListener("keydown", (e) => {
77
+ if (e.key === "Enter") onSend();
78
+ });
79
 
80
+ function saveState() {
81
+ localStorage.setItem("chatHistory", JSON.stringify(chatHistory));
82
+ localStorage.setItem("patientState", JSON.stringify(patientState));
83
+ }
84
+
85
+ function renderChat() {
86
+ chatEl.innerHTML = "";
87
+ for (const m of chatHistory) {
88
+ const div = document.createElement("div");
89
+ div.className = `msg ${m.role === "user" ? "user" : "assist"}`;
90
+ div.textContent = `${m.role === "user" ? "You" : "Assistant"}: ${m.content}`;
91
+ chatEl.appendChild(div);
92
+ }
93
+ chatEl.scrollTop = chatEl.scrollHeight;
94
+ }
95
+
96
+ async function onSend() {
97
+ const message = (msgEl.value || "").trim();
98
+ if (!message) return;
99
+
100
+ // Clear the input and disable the button while we wait for the response
101
+ msgEl.value = "";
102
+ sendBtn.disabled = true;
103
+
104
+ // Add the user's message to the chat history
105
+ chatHistory.push({ role: "user", content: message });
106
+ renderChat();
107
+ saveState();
108
+
109
+ try {
110
+ // Send the chat history and patient state to the backend
111
+ const res = await fetch(NODE_CHAT_ENDPOINT, {
112
+ method: "POST",
113
+ headers: { "Content-Type": "application/json" },
114
+ body: JSON.stringify({ chat_history: chatHistory, patient_state: patientState })
115
+ });
116
+
117
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
118
+ const data = await res.json();
119
+
120
+ const reply = data.assistant_reply || "(no reply)";
121
+ patientState = data.updated_state || patientState;
122
+
123
+ // Add the assistant's reply to the chat history
124
+ chatHistory.push({ role: "assistant", content: reply });
125
+ renderChat();
126
+ saveState();
127
+
128
+ // Display the raw agent state for debugging
129
+ stateView.textContent = JSON.stringify(patientState, null, 2);
130
+ } catch (err) {
131
+ // Handle any errors and display them in the chat
132
+ chatHistory.push({ role: "assistant", content: `Error: ${err.message}` });
133
+ renderChat();
134
+ saveState();
135
+ } finally {
136
+ sendBtn.disabled = false;
137
+ }
138
+ }
139
+
140
+ // Initial greeting
141
+ if (chatHistory.length === 0) {
142
+ chatHistory.push({ role: "assistant", content: "Hello! I am your patient assistant. Please tell me your Patient ID to get started." });
143
+ saveState();
144
+ }
145
  renderChat();
146
+ </script>
 
 
 
 
 
 
 
 
147
  </body>
148
  </html>