TheFrogGod commited on
Commit
a1dc880
·
verified ·
1 Parent(s): f181a51

Create analyzer_update.html

Browse files
Files changed (1) hide show
  1. web/analyzer_update.html +472 -0
web/analyzer_update.html ADDED
@@ -0,0 +1,472 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Document Analyzer | CTRL + ALT + HEAL</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="style.css" />
9
+ </head>
10
+ <body class="bg-[var(--latte-cream)] font-sans text-gray-800 min-h-screen">
11
+ <!-- NAVBAR -->
12
+ <nav
13
+ class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
14
+ >
15
+ <div class="flex items-center px-6 py-4 max-w-7xl mx-auto">
16
+ <a
17
+ href="index.html"
18
+ class="text-2xl font-bold text-black hover:text-[var(--tropical-indigo)] transition"
19
+ >
20
+ CTRL + ALT + HEAL
21
+ </a>
22
+
23
+ <!-- Desktop Links -->
24
+ <ul class="hidden md:flex space-x-6 font-medium text-gray-800 ml-auto">
25
+ <li><a href="index.html" class="nav-link">Home</a></li>
26
+ <li><a href="profile.html" class="nav-link">Profile</a></li>
27
+ <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
28
+ <li><a href="past_data.html" class="nav-link">Past Reports</a></li>
29
+ <li id="authNavItem">
30
+ <a href="login.html" class="nav-link">Login</a>
31
+ </li>
32
+ </ul>
33
+
34
+ <!-- Hamburger Menu -->
35
+ <button
36
+ id="hamburger"
37
+ class="md:hidden text-[var(--latte-cream)] text-2xl ml-auto"
38
+ >
39
+
40
+ </button>
41
+ </div>
42
+
43
+ <!-- Mobile Menu -->
44
+ <ul
45
+ id="mobile-menu"
46
+ class="hidden flex-col space-y-4 bg-white/30 backdrop-blur-lg border border-white/20 rounded-xl shadow-lg mt-2 p-4 mx-6 md:hidden"
47
+ >
48
+ <li><a href="index.html" class="block nav-link">Home</a></li>
49
+ <li><a href="analyzer.html" class="block nav-link">Analyzer</a></li>
50
+ <li><a href="profile.html" class="block nav-link">Profile</a></li>
51
+ <li><a href="login.html" class="block nav-link">Login</a></li>
52
+ <li><a href="about.html" class="block nav-link">About</a></li>
53
+ </ul>
54
+ </nav>
55
+
56
+ <script src="script.js"></script>
57
+ <script>
58
+ const hamburger = document.getElementById("hamburger");
59
+ const mobileMenu = document.getElementById("mobile-menu");
60
+ hamburger.addEventListener("click", () =>
61
+ mobileMenu.classList.toggle("hidden")
62
+ );
63
+
64
+ const currentPath = window.location.pathname.split("/").pop();
65
+ document.querySelectorAll(".nav-link").forEach((link) => {
66
+ if (link.getAttribute("href") === currentPath)
67
+ link.classList.add("active-page");
68
+ });
69
+ </script>
70
+
71
+ <main class="max-w-5xl mx-auto px-4 mb-16 pt-24">
72
+ <div class="bg-white border border-gray-200 rounded-lg p-6 shadow mb-6">
73
+ <h2 class="text-xl font-semibold mb-4">
74
+ Upload & Analyze Your Medical PDF or Image
75
+ </h2>
76
+ <input
77
+ type="file"
78
+ id="pdf-upload"
79
+ accept=".pdf, image/*"
80
+ class="w-full mb-4 rounded px-3 py-2"
81
+ />
82
+ <button id="analyze-btn" class="btn-primary px-4 py-2 rounded">
83
+ Analyze with AI
84
+ </button>
85
+ <p id="loading" class="text-gray-600 mt-2">No file uploaded yet.</p>
86
+ <p id="auth-status" class="text-sm text-gray-500 mt-1">
87
+ Sign in to save and view past analyses.
88
+ </p>
89
+ </div>
90
+
91
+ <div
92
+ class="bg-[var(--latte-cream)] border border-[var(--wisteria)] rounded-lg p-6 mb-8"
93
+ >
94
+ <h3 class="text-lg font-semibold mb-3">Extracted Text</h3>
95
+ <div
96
+ id="text-output"
97
+ class="whitespace-pre-wrap h-60 overflow-auto bg-[#FAFBFC] text-sm border border-[var(--wisteria)] rounded p-4"
98
+ >
99
+ OCR results will appear here.
100
+ </div>
101
+ </div>
102
+
103
+ <div
104
+ class="bg-[var(--latte-cream)] border border-[var(--wisteria)] rounded-lg p-6 mb-8"
105
+ >
106
+ <h3 class="text-lg font-semibold mb-3">AI Findings</h3>
107
+ <div
108
+ id="recommendations-output"
109
+ class="bg-[#F9FAFB] text-sm border border-[var(--wisteria)] rounded p-4 space-y-4"
110
+ >
111
+ Findings and Recommendations will appear here.
112
+ </div>
113
+ </div>
114
+ </main>
115
+
116
+ <button
117
+ id="chat-toggle"
118
+ class="fixed bottom-6 right-6 bg-[var(--tropical-indigo)] text-white px-5 py-3 rounded-full shadow-lg hover:scale-105 transition"
119
+ >
120
+ 💬 Chat
121
+ </button>
122
+
123
+ <div
124
+ id="chat-drawer"
125
+ class="fixed top-16 right-0 w-96 max-w-full h-[calc(100%-4rem)] bg-white shadow-lg border-l border-gray-200 transform translate-x-full transition-transform duration-300 ease-in-out z-40 flex flex-col"
126
+ >
127
+ <div class="flex justify-between items-center p-4 border-b">
128
+ <h3 class="text-lg font-semibold">Ask Chatbot</h3>
129
+ <button id="chat-close" class="text-gray-600 hover:text-black text-xl">
130
+
131
+ </button>
132
+ </div>
133
+ <div id="chat-output" class="flex-1 overflow-auto p-4 space-y-2 text-sm">
134
+ <p><strong>Chatbot:</strong> Ask me something about your report</p>
135
+ </div>
136
+ <div class="flex gap-2 p-4 border-t">
137
+ <input
138
+ type="text"
139
+ id="user-question"
140
+ placeholder="Ask a question..."
141
+ class="flex-1 rounded px-3 py-2 focus:outline-none border"
142
+ />
143
+ <button id="ask-btn" class="btn-primary px-4 py-2 rounded">Ask</button>
144
+ </div>
145
+ </div>
146
+
147
+ <script>
148
+ const chatDrawer = document.getElementById("chat-drawer");
149
+ const chatToggle = document.getElementById("chat-toggle");
150
+ const chatClose = document.getElementById("chat-close");
151
+ chatToggle.addEventListener("click", () =>
152
+ chatDrawer.classList.toggle("translate-x-full")
153
+ );
154
+ chatClose.addEventListener("click", () =>
155
+ chatDrawer.classList.add("translate-x-full")
156
+ );
157
+ </script>
158
+
159
+ <script type="module">
160
+ import {
161
+ getFirestore,
162
+ collection,
163
+ doc,
164
+ addDoc,
165
+ setDoc,
166
+ getDoc,
167
+ serverTimestamp,
168
+ } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
169
+ import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
170
+ import {
171
+ getAuth,
172
+ onAuthStateChanged,
173
+ signOut,
174
+ } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js";
175
+
176
+ const firebaseConfig = {
177
+ apiKey: "AIzaSyAKWstCc7HqMgV8DmH2Sy6QwUP3JvZxu9g",
178
+ authDomain: "appchallenge-c8fe3.firebaseapp.com",
179
+ projectId: "appchallenge-c8fe3",
180
+ storageBucket: "appchallenge-c8fe3.firebasestorage.app",
181
+ messagingSenderId: "943791692455",
182
+ appId: "1:943791692455:web:ae04d06bf09669b6bdd982",
183
+ };
184
+
185
+ const app = initializeApp(firebaseConfig);
186
+ const auth = getAuth(app);
187
+ const db = getFirestore(app);
188
+ window.firebaseAuth = auth;
189
+ window.firestoreDb = db;
190
+ window.firestoreHelpers = {
191
+ collection,
192
+ doc,
193
+ addDoc,
194
+ setDoc,
195
+ getDoc,
196
+ serverTimestamp,
197
+ };
198
+
199
+ let currentUser = null;
200
+
201
+ window.onAuthStateChanged(auth, (user) => {
202
+ currentUser = user;
203
+ const authNavItem = document.getElementById("authNavItem");
204
+ const profileNavDesktop = document.querySelector(
205
+ 'ul.md\\:flex li a[href="profile.html"]'
206
+ )?.parentElement;
207
+ const pastNavDesktop = document.querySelector(
208
+ 'ul.md\\:flex li a[href="past_data.html"]'
209
+ )?.parentElement;
210
+ const profileNavMobile = document.querySelector(
211
+ '#mobile-menu a[href="profile.html"]'
212
+ )?.parentElement;
213
+ const pastNavMobile = document.querySelector(
214
+ '#mobile-menu a[href="past_data.html"]'
215
+ )?.parentElement;
216
+
217
+ if (authNavItem) {
218
+ if (user) {
219
+ authNavItem.innerHTML =
220
+ '<button onclick="logout()" class="hover:text-[#6B9080] text-red-600">Logout</button>';
221
+ if (profileNavDesktop) profileNavDesktop.style.display = "block";
222
+ if (pastNavDesktop) pastNavDesktop.style.display = "block";
223
+ if (profileNavMobile) profileNavMobile.style.display = "block";
224
+ if (pastNavMobile) pastNavMobile.style.display = "block";
225
+ } else {
226
+ authNavItem.innerHTML =
227
+ '<a href="login.html" class="hover:text-[#6B9080]">Login</a>';
228
+ if (profileNavDesktop) profileNavDesktop.style.display = "none";
229
+ if (pastNavDesktop) pastNavDesktop.style.display = "none";
230
+ if (profileNavMobile) profileNavMobile.style.display = "none";
231
+ if (pastNavMobile) pastNavMobile.style.display = "none";
232
+ }
233
+ }
234
+ });
235
+
236
+ window.logout = async () => {
237
+ try {
238
+ await signOut(auth);
239
+ localStorage.clear();
240
+ window.location.href = "login.html";
241
+ } catch (error) {
242
+ console.error("Error signing out:", error);
243
+ }
244
+ };
245
+
246
+ // ---------------------- Analyzer ----------------------
247
+ const loadingEl = document.getElementById("loading");
248
+ const textOutput = document.getElementById("text-output");
249
+ const recsOutput = document.getElementById("recommendations-output");
250
+ const chat = document.getElementById("chat-output");
251
+ const authStatus = document.getElementById("auth-status");
252
+ let extractedText = "";
253
+
254
+ function renderRecCard(rec, idx) {
255
+ const sev = (rec.severity || "").toLowerCase();
256
+ const sevClass = sev.includes("severe")
257
+ ? "badge-high"
258
+ : sev.includes("moderate")
259
+ ? "badge-medium"
260
+ : "badge-low";
261
+ return `
262
+ <div class="rec-card">
263
+ <div class="flex items-center justify-between">
264
+ <h4 class="rec-title">Finding ${idx + 1}: ${
265
+ rec.findings || "N/A"
266
+ }</h4>
267
+ <span class="rec-badge ${sevClass}">${rec.severity || "—"}</span>
268
+ </div>
269
+ <ul class="rec-content space-y-1">
270
+ <li><em>Recommendations:</em>
271
+ <ul class="list-disc list-inside ml-6">${(
272
+ rec.recommendations || []
273
+ )
274
+ .map((r) => `<li>${r}</li>`)
275
+ .join("")}</ul>
276
+ </li>
277
+ <li><em>Treatment:</em> ${
278
+ rec.treatment_suggestions || "Not available"
279
+ }</li>
280
+ <li><em>Home Care:</em>
281
+ <ul class="list-disc list-inside ml-6">${(
282
+ rec.home_care_guidance || []
283
+ )
284
+ .map((r) => `<li>${r}</li>`)
285
+ .join("")}</ul>
286
+ </li>
287
+ ${
288
+ rec.info_link
289
+ ? `<li><a href="${rec.info_link}" target="_blank" class="rec-link">Learn more</a></li>`
290
+ : ""
291
+ }
292
+ </ul>
293
+ </div>`;
294
+ }
295
+
296
+ window.onAuthStateChanged(auth, (user) => {
297
+ currentUser = user;
298
+ authStatus.textContent = user
299
+ ? `Signed in as ${user.email || user.uid}`
300
+ : "Not signed in. Sign in to save and view past analyses.";
301
+ });
302
+
303
+ document
304
+ .getElementById("pdf-upload")
305
+ .addEventListener("change", function () {
306
+ loadingEl.textContent = this.files.length
307
+ ? `File selected: ${this.files[0].name}`
308
+ : "No file uploaded yet.";
309
+ });
310
+
311
+ async function postReportToBackend(report) {
312
+ try {
313
+ const response = await fetch(api("save_report/"), {
314
+ method: "POST",
315
+ headers: { "Content-Type": "application/json" },
316
+ body: JSON.stringify(report),
317
+ });
318
+ if (!response.ok)
319
+ throw new Error(`HTTP error! status: ${response.status}`);
320
+ const data = await response.json();
321
+ console.log("Report sent to backend:", data);
322
+ } catch (error) {
323
+ console.error("Error sending report:", error);
324
+ }
325
+ }
326
+
327
+ // -------- New: Save Latest Test Results with Smart Update --------
328
+ async function saveLatestResults(csvData) {
329
+ if (!currentUser) return;
330
+
331
+ try {
332
+ const docRef = doc(db, "latest_test_results", currentUser.email);
333
+ const docSnap = await getDoc(docRef);
334
+ let results = [];
335
+
336
+ if (docSnap.exists()) {
337
+ results = docSnap.data().results || [];
338
+ }
339
+
340
+ csvData.forEach((row) => {
341
+ const idx = results.findIndex((r) => r.condition === row.Condition);
342
+ if (idx >= 0) {
343
+ results[idx].test_result = row["Test Result"];
344
+ results[idx].unit = row.Unit;
345
+ } else {
346
+ results.push({
347
+ condition: row.Condition,
348
+ test_result: row["Test Result"],
349
+ unit: row.Unit,
350
+ });
351
+ }
352
+ });
353
+
354
+ await setDoc(docRef, {
355
+ user_id: currentUser.email,
356
+ report_date: serverTimestamp(),
357
+ results: results,
358
+ });
359
+
360
+ console.log("Latest test results updated with smart merge!");
361
+ } catch (err) {
362
+ console.error("Error saving latest results:", err);
363
+ }
364
+ }
365
+
366
+ document
367
+ .getElementById("analyze-btn")
368
+ .addEventListener("click", async () => {
369
+ const file = document.getElementById("pdf-upload").files[0];
370
+ if (!file) {
371
+ loadingEl.textContent = "Please upload a file first.";
372
+ return;
373
+ }
374
+
375
+ loadingEl.textContent = "Processing with AI...";
376
+ textOutput.textContent = "";
377
+ recsOutput.textContent = "";
378
+
379
+ const formData = new FormData();
380
+ formData.append("file", file);
381
+ formData.append("model", "bert");
382
+
383
+ let data;
384
+ try {
385
+ const res = await fetch(api("analyze/"), {
386
+ method: "POST",
387
+ body: formData,
388
+ });
389
+ if (!res.ok) throw new Error(await res.text());
390
+ data = await res.json();
391
+ } catch (err) {
392
+ console.error(err);
393
+ loadingEl.textContent = "Error during analysis: " + err.message;
394
+ return;
395
+ }
396
+
397
+ extractedText = data.ocr_text || "";
398
+ textOutput.textContent = extractedText;
399
+
400
+ const recs = Array.isArray(data.Detected_Anomolies)
401
+ ? data.Detected_Anomolies
402
+ : data.Detected_Anomolies
403
+ ? [data.Detected_Anomolies]
404
+ : [];
405
+
406
+ recsOutput.innerHTML = recs.length
407
+ ? recs.map(renderRecCard).join("")
408
+ : "No recommendations found.";
409
+
410
+ if (currentUser) {
411
+ await postReportToBackend({
412
+ user_id: currentUser.email,
413
+ report_date: new Date(),
414
+ ocr_text: extractedText,
415
+ anomalies: JSON.stringify(recs),
416
+ });
417
+ }
418
+
419
+ if (currentUser && recs.length) {
420
+ const csvData = recs.map((rec) => ({
421
+ User: currentUser.email,
422
+ Condition: rec.findings || "N/A",
423
+ "Test Result": rec.test_result || "N/A",
424
+ Unit: rec.unit || "",
425
+ }));
426
+ saveLatestResults(csvData);
427
+ }
428
+
429
+ loadingEl.textContent = "Analysis complete.";
430
+ });
431
+
432
+ // ---------------------- Chatbot ----------------------
433
+ document.getElementById("ask-btn").onclick = async () => {
434
+ const q = document.getElementById("user-question").value.trim();
435
+ if (!q) return;
436
+ if (!extractedText) {
437
+ alert("Please analyze a document first.");
438
+ return;
439
+ }
440
+ chat.innerHTML += `<p><strong>You:</strong> ${q}</p>`;
441
+ chat.innerHTML += `<p><strong>Chatbot:</strong> <em>Thinking...</em></p>`;
442
+ chat.scrollTop = chat.scrollHeight;
443
+
444
+ try {
445
+ const res = await fetch(api("chat/"), {
446
+ method: "POST",
447
+ headers: { "Content-Type": "application/json" },
448
+ body: JSON.stringify({
449
+ question: q,
450
+ user_id: currentUser ? currentUser.uid : "anonymous",
451
+ }),
452
+ });
453
+ if (!res.ok) throw new Error(await res.text());
454
+ const data = await res.json();
455
+ const last = chat.querySelectorAll("p");
456
+ last[
457
+ last.length - 1
458
+ ].innerHTML = `<strong>Chatbot:</strong> ${data.answer}`;
459
+ } catch (err) {
460
+ console.error("Error:", err);
461
+ const last = chat.querySelectorAll("p");
462
+ last[
463
+ last.length - 1
464
+ ].innerHTML = `<strong>Chatbot:</strong> Sorry, error: ${err.message}`;
465
+ }
466
+
467
+ document.getElementById("user-question").value = "";
468
+ chat.scrollTop = chat.scrollHeight;
469
+ };
470
+ </script>
471
+ </body>
472
+ </html>