vineelagampa TheFrogGod commited on
Commit
c095422
·
verified ·
1 Parent(s): 2d2d166

The Fixes Should Work Now. (#24)

Browse files

- The Fixes Should Work Now. (ee3681cc76075051130e7b38d9a97e6013cc6283)


Co-authored-by: Aanya Choudhary <TheFrogGod@users.noreply.huggingface.co>

Files changed (1) hide show
  1. web/past_data.html +271 -279
web/past_data.html CHANGED
@@ -1,310 +1,302 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>Past Analyzes - CTRL + ALT + HEAL</title>
6
- <script src="https://cdn.tailwindcss.com"></script>
7
- <script src="script.js"></script>
8
- </head>
9
- <body class="bg-[#F7F8F9] min-h-screen">
10
- <nav class="bg-white border border-gray-200 px-6 py-4 mb-8">
11
- <div class="container mx-auto flex justify-between items-center">
12
- <a href="index.html" class="text-2xl font-bold text-[#6B9080]">CTRL + ALT + HEAL</a>
 
 
 
 
 
 
13
  <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
14
  <li><a href="index.html" class="nav-link">Home</a></li>
 
15
  <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
16
  <li><a href="past_data.html" class="nav-link">Past Reports</a></li>
17
- <li><a href="profile.html" class="nav-link">Profile</a></li>
18
- <li id="authNavItem"><a href="login.html" class="nav-link">Login</a></li>
 
19
  </ul>
20
- </div>
21
- </nav>
22
-
23
- <main class="max-w-4xl mx-auto px-4">
24
- <h1 class="text-2xl font-bold text-green-700 mb-4">Your Past Analyzes</h1>
25
- <p id="auth-status" class="text-sm text-gray-500 mb-6">Checking sign-in status…</p>
26
-
27
- <div id="recs-container" class="space-y-4">
28
- <p class="text-sm text-gray-500">Sign in to view your saved analyzes.</p>
29
- </div>
30
- <div
31
- class="bg-[var(--latte-cream)] border border-[var(--wisteria)] rounded-lg p-6 mb-8"
32
- >
33
- <h3 class="text-lg font-semibold mb-3">Ask Chatbot</h3>
34
- <div
35
- id="chat-output"
36
- class="space-y-2 h-48 overflow-auto text-sm rounded p-4"
37
  >
38
- <p><strong>Chatbot:</strong> Ask me something about your report</p>
39
- </div>
40
- <div class="flex mt-4 gap-2">
41
- <input
42
- type="text"
43
- id="user-question"
44
- placeholder="Ask a question..."
45
- class="flex-1 rounded px-3 py-2 focus:outline-none"
46
- />
47
- <button id="ask-btn" class="btn-primary px-4 py-2 rounded">
48
- Ask
49
- </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  </div>
51
  </div>
52
- </main>
53
 
54
- <script type="module">
55
- import { getFirestore, collection, query, orderBy, getDocs } from 'https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js';
56
- import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js';
57
- import { getAuth, onAuthStateChanged, signOut } from 'https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js';
 
 
 
58
 
59
- const firebaseConfig = {
60
- apiKey: "AIzaSyAKWstCc7HqMgV8DmH2Sy6QwUP3JvZxu9g",
61
- authDomain: "appchallenge-c8fe3.firebaseapp.com",
62
- projectId: "appchallenge-c8fe3",
63
- storageBucket: "appchallenge-c8fe3.firebasestorage.app",
64
- messagingSenderId: "943791692455",
65
- appId: "1:943791692455:web:ae04d06bf09669b6bdd982",
66
- measurementId: "G-HJ7EHW8V4N"
67
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
- const app = initializeApp(firebaseConfig);
70
- const auth = getAuth(app);
71
- const db = getFirestore(app);
72
- window.currentUser = null;
73
- window.chatContext = null;
74
- window.setChatContextFromId = function (id) {
75
- const pre = document.querySelector(`#content-${id} .ocr-pre`);
76
- window.chatContext = pre ? pre.textContent.trim() : null;
77
- const chatOutput = document.getElementById('chat-output');
78
- if (chatOutput) {
79
- chatOutput.innerHTML += `<p class="text-xs text-gray-500"><em>Context set from selected report.</em></p>`;
80
- chatOutput.scrollTop = chatOutput.scrollHeight;
81
- }
82
- };
83
- onAuthStateChanged(auth, (user) => {
84
- const authNavItem = document.getElementById('authNavItem');
85
- if (user) {
86
- authNavItem.innerHTML = '<button onclick="logout()" class="hover:text-[#6B9080] text-red-600">Logout</button>';
87
- } else {
88
- authNavItem.innerHTML = '<a href="login.html" class="hover:text-[#6B9080]">Login</a>';
89
- }
90
- });
91
 
92
- window.logout = async () => {
93
- try {
94
- await signOut(auth);
95
- localStorage.clear();
96
- window.location.href = 'login.html';
97
- } catch (error) {
98
- console.error("Error signing out:", error);
99
- }
100
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
- const statusEl = document.getElementById("auth-status");
103
- const recsEl = document.getElementById("recs-container");
104
- async function sendReportToBackend(report, userId) {
105
- try {
106
- const response = await fetch('http://localhost:9000/save_report/', {
107
- method: 'POST',
108
- headers: {
109
- 'Content-Type': 'application/json',
110
- },
111
- body: JSON.stringify({
112
- ...report,
113
- user_id: userId,
114
- sync_timestamp: new Date().toISOString()
115
- }),
116
- });
117
-
118
- if (!response.ok) {
119
- console.warn(`Failed to sync report to backend: ${response.status}`);
 
 
 
 
 
 
120
  } else {
121
- console.log('Report successfully synced to backend');
 
122
  }
123
- } catch (error) {
124
- console.warn('Error syncing report to backend (continuing anyway):', error);
125
  }
126
- }
127
 
128
- function renderAnalysisWithCustomToggle(item) {
129
- const d = item.createdAt && item.createdAt.toDate ? item.createdAt.toDate().toLocaleString() : "";
130
- const uniqueId = `ocr-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; // Generate unique ID
131
-
132
- return `
133
- <div class="bg-white border border-gray-200 rounded-lg p-4 shadow">
134
- <div class="flex justify-between mb-2">
135
- <div class="text-xs text-gray-500">${d}</div>
136
- </div>
137
-
138
- <!-- Collapsible OCR Text Section with Custom Toggle -->
139
- <div class="mb-4">
140
- <div class="font-semibold text-green-700 cursor-pointer hover:text-green-800 py-2 flex justify-between items-center"
141
- onclick="toggleOCR('${uniqueId}')">
142
- <span>Report ${item.reportDate || "N/A"}</span>
143
- <span class="arrow transition-transform duration-300" id="arrow-${uniqueId}">▶</span>
 
 
 
 
 
 
144
  </div>
145
- <div class="ocr-content overflow-hidden transition-all duration-300 max-h-0" id="content-${uniqueId}">
146
- <div class="mt-2 p-3 bg-gray-50 rounded border">
147
- <pre class="whitespace-pre-wrap text-sm text-gray-700">${item.ocr_text || ""}</pre>
 
 
 
 
 
 
 
 
148
  </div>
149
  </div>
150
- </div>
151
-
152
- <!-- Findings Section -->
153
- ${(Array.isArray(item.Detected_Anomolies) ? item.Detected_Anomolies : []).map((r,i) => `
154
- <div class="border-t border-gray-200 pt-2 mt-2">
155
- <div class="font-medium">Finding ${i+1}: ${r.findings || ""}</div>
156
- <div class="text-sm text-gray-600">Severity: ${r.severity || ""}</div>
157
- <div class="text-sm text-gray-600">Recommendations: ${(r.recommendations || []).join(", ")}</div>
158
- </div>
159
- `).join("")}
160
- </div>
161
- `;
162
- }
163
 
164
- function toggleOCR(id) {
165
- const content = document.getElementById(`content-${id}`);
166
- const arrow = document.getElementById(`arrow-${id}`);
167
-
168
- if (content.style.maxHeight && content.style.maxHeight !== '0px') {
169
- content.style.maxHeight = '0px';
170
- arrow.style.transform = 'rotate(0deg)';
171
- } else {
172
- content.style.maxHeight = content.scrollHeight + 'px';
173
- arrow.style.transform = 'rotate(90deg)';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
175
- }
176
-
177
- onAuthStateChanged(auth, async (user) => {
178
- if (user) {
179
- statusEl.textContent = `Signed in as ${user.email || user.uid}`;
180
 
181
- async function getPastReports() {
182
- try {
183
- const url = api('reports/', { user_id: user.email });
184
- const response = await fetch(url, {
185
- method: 'GET',
186
- headers: {
187
- 'Content-Type': 'application/json',
188
- },
189
- });
190
- if (!response.ok) {
191
- throw new Error(`HTTP error! status: ${response.status}`);
192
- }
193
- const data = await response.json();
194
- console.log('Report successfully sent to backend:', data);
195
- recsEl.innerHTML = data.map(doc => renderAnalysisWithCustomToggle(doc)).join("");
196
- } catch (error) {
197
- console.error('Error sending report to backend:', error);
198
- recsEl.innerHTML = '<p class="text-sm text-gray-500">No saved analyses yet.</p>';
199
- }
200
- }
201
- getPastReports();
202
-
203
-
204
- /* try {
205
- const q = query(
206
- collection(db, "users", user.uid, "analyses"),
207
- orderBy("createdAt", "desc")
208
- );
209
- const snap = await getDocs(q);
210
-
211
- if (snap.empty) {
212
- recsEl.innerHTML = '<p class="text-sm text-gray-500">No saved analyses yet.</p>';
213
- } else {
214
- const analyses = [];
215
 
216
- snap.forEach(doc => {
217
- const data = { id: doc.id, ...doc.data() };
218
- analyses.push(data);
 
 
 
219
 
220
- sendReportToBackend(data, user.uid);
221
- });
222
-
223
- recsEl.innerHTML = analyses.map(doc => renderAnalysis(doc)).join("");
224
-
225
- const syncStatus = document.createElement('p');
226
- syncStatus.className = 'text-xs text-blue-500 mt-2';
227
- syncStatus.textContent = `Syncing ${analyses.length} reports to backend...`;
228
- recsEl.appendChild(syncStatus);
229
-
230
- setTimeout(() => {
231
- if (syncStatus.parentNode) {
232
- syncStatus.remove();
233
- }
234
- }, 3000);
235
- }
236
- } catch (error) {
237
- console.error('Error fetching analyses:', error);
238
- recsEl.innerHTML = '<p class="text-sm text-red-500">Error loading analyses.</p>';
239
- }*/
240
-
241
- } else {
242
- statusEl.textContent = "Not signed in.";
243
- recsEl.innerHTML = '<p class="text-sm text-gray-500">Please sign in to see your analyses.</p>';
244
- }
245
- document.getElementById("ask-btn").onclick = async () => {
246
- const q = document.getElementById("user-question").value.trim();
247
- if (!q) return;
248
 
249
- // require a selected report as context
250
- if (!window.chatContext) {
251
- alert("Please click 'Chat about this report' on a saved report first to set context.");
252
- return;
 
 
 
253
  }
 
 
 
 
 
 
 
 
254
 
255
- document.getElementById("ask-btn").onclick = async () => {
256
- const q = document.getElementById("user-question").value.trim();
257
- if (!q) return;
258
-
259
- // require a selected report as context
260
- if (!window.chatContext) {
261
- alert("Please click 'Chat about this report' on a saved report first to set context.");
262
- return;
263
- }
264
-
265
- const chat = document.getElementById("chat-output");
266
- chat.innerHTML += `<p><strong>You:</strong> ${q}</p>`;
267
- chat.scrollTop = chat.scrollHeight;
268
-
269
- chat.innerHTML += `<p><strong>Chatbot:</strong> <em>Thinking...</em></p>`;
270
- chat.scrollTop = chat.scrollHeight;
271
-
272
- try {
273
- const response = await fetch(api('chat/'), {
274
- method: "POST",
275
- headers: {
276
- "Content-Type": "application/json",
277
- },
278
- body: JSON.stringify({
279
- question: q,
280
- user_id: auth && auth.currentUser ? (auth.currentUser.uid || auth.currentUser.email) : "anonymous",
281
- context: window.chatContext
282
- }),
283
- });
284
-
285
- if (!response.ok) {
286
- throw new Error(`HTTP error! status: ${response.status}`);
287
- }
288
-
289
- const data = await response.json();
290
-
291
- //now addign acctual reposnse
292
- const messages = chat.querySelectorAll('p');
293
- const lastMessage = messages[messages.length - 1];
294
- lastMessage.innerHTML = `<strong>Chatbot:</strong> ${data.answer}`;
295
-
296
- } catch (error) {
297
- console.error("Error:", error);
298
- const messages = chat.querySelectorAll('p');
299
- const lastMessage = messages[messages.length - 1];
300
- lastMessage.innerHTML = `<strong>Chatbot:</strong> Sorry, I encountered an error: ${error.message}`;
301
- }
302
-
303
- document.getElementById("user-question").value = "";
304
- chat.scrollTop = chat.scrollHeight;
305
- };
306
  };
307
- });
308
- </script>
309
- </body>
310
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Past Analyzes - CTRL + ALT + HEAL</title>
6
+ <script src="https://cdn.tailwindcss.com"></script>
7
+ <link rel="stylesheet" href="style.css" />
8
+ </head>
9
+ <body class="bg-[#F7F8F9] min-h-screen">
10
+ <nav
11
+ class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
12
+ >
13
+ <div class="flex justify-between items-center w-full px-6 py-4">
14
+ <a
15
+ href="index.html"
16
+ class="text-2xl font-bold text-black hover:text-[var(--tropical-indigo)] transition"
17
+ >CTRL + ALT + HEAL</a
18
+ >
19
  <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
20
  <li><a href="index.html" class="nav-link">Home</a></li>
21
+ <li><a href="profile.html" class="nav-link">Profile</a></li>
22
  <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
23
  <li><a href="past_data.html" class="nav-link">Past Reports</a></li>
24
+ <li id="authNavItem">
25
+ <a href="login.html" class="nav-link">Login</a>
26
+ </li>
27
  </ul>
28
+ <button
29
+ id="hamburger"
30
+ class="md:hidden text-[var(--latte-cream)] text-2xl"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  >
32
+
33
+ </button>
34
+ </div>
35
+ <ul
36
+ id="mobile-menu"
37
+ 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"
38
+ >
39
+ <li>
40
+ <a
41
+ href="index.html"
42
+ class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
43
+ >Home</a
44
+ >
45
+ </li>
46
+ <li>
47
+ <a
48
+ href="analyzer.html"
49
+ class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
50
+ >Analyzer</a
51
+ >
52
+ </li>
53
+ <li>
54
+ <a
55
+ href="past_data.html"
56
+ class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
57
+ >Past Reports</a
58
+ >
59
+ </li>
60
+ <li>
61
+ <a
62
+ href="profile.html"
63
+ class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
64
+ >Profile</a
65
+ >
66
+ </li>
67
+ <li>
68
+ <a
69
+ href="login.html"
70
+ class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
71
+ >Login</a
72
+ >
73
+ </li>
74
+ </ul>
75
+ </nav>
76
+
77
+ <main class="max-w-4xl mx-auto px-4 pt-24 text-gray-800">
78
+ <div class="bg-white border border-gray-200 rounded-lg p-6 shadow mb-6">
79
+ <h2 class="text-xl font-semibold mb-4">Your Past Analyzes</h2>
80
+ <p id="auth-status" class="text-sm text-gray-500 mb-6">
81
+ Checking sign-in status…
82
+ </p>
83
+ <div id="recs-container" class="space-y-4">
84
+ <p class="text-sm text-gray-500">
85
+ Sign in to view your saved analyzes.
86
+ </p>
87
  </div>
88
  </div>
89
+ </main>
90
 
91
+ <!-- Floating Chat Button -->
92
+ <button
93
+ id="chat-toggle"
94
+ class="fixed bottom-6 right-6 bg-[var(--tropical-indigo)] text-white px-5 py-3 rounded-full shadow-lg hover:scale-105 transition"
95
+ >
96
+ 💬 Chat
97
+ </button>
98
 
99
+ <!-- Chatbot Drawer -->
100
+ <div
101
+ id="chat-drawer"
102
+ 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"
103
+ >
104
+ <div class="flex justify-between items-center p-4 border-b">
105
+ <h3 class="text-lg font-semibold">Ask Chatbot</h3>
106
+ <button id="chat-close" class="text-gray-600 hover:text-black text-xl">
107
+
108
+ </button>
109
+ </div>
110
+ <div id="chat-output" class="flex-1 overflow-auto p-4 space-y-2 text-sm">
111
+ <p><strong>Chatbot:</strong> Ask me something about your report</p>
112
+ </div>
113
+ <div class="flex gap-2 p-4 border-t">
114
+ <input
115
+ type="text"
116
+ id="user-question"
117
+ placeholder="Ask a question..."
118
+ class="flex-1 rounded px-3 py-2 focus:outline-none border"
119
+ />
120
+ <button id="ask-btn" class="btn-primary px-4 py-2 rounded">Ask</button>
121
+ </div>
122
+ </div>
123
 
124
+ <script>
125
+ const chatDrawer = document.getElementById("chat-drawer");
126
+ const chatToggle = document.getElementById("chat-toggle");
127
+ const chatClose = document.getElementById("chat-close");
128
+ chatToggle.addEventListener("click", () =>
129
+ chatDrawer.classList.toggle("translate-x-full")
130
+ );
131
+ chatClose.addEventListener("click", () =>
132
+ chatDrawer.classList.add("translate-x-full")
133
+ );
134
+ </script>
 
 
 
 
 
 
 
 
 
 
 
135
 
136
+ <script type="module">
137
+ import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
138
+ import {
139
+ getAuth,
140
+ onAuthStateChanged,
141
+ signOut,
142
+ } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js";
143
+ import {
144
+ getFirestore,
145
+ collection,
146
+ query,
147
+ orderBy,
148
+ getDocs,
149
+ } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
150
+
151
+ const firebaseConfig = {
152
+ apiKey: "AIzaSyDNXm6ewXWMdIIAyC0q83ZspBfwmP30UJQ",
153
+ authDomain: "appchallenge-c8fe3.firebaseapp.com",
154
+ projectId: "appchallenge-c8fe3",
155
+ storageBucket: "appchallenge-c8fe3.firebasestorage.app",
156
+ messagingSenderId: "943791692455",
157
+ appId: "1:943791692455:web:ae04d06bf09669b6bdd982",
158
+ measurementId: "G-HJ7EHW8V4N",
159
+ };
160
 
161
+ const app = initializeApp(firebaseConfig);
162
+ const auth = getAuth(app);
163
+ const db = getFirestore(app);
164
+
165
+ const statusEl = document.getElementById("auth-status");
166
+ const recsEl = document.getElementById("recs-container");
167
+
168
+ window.chatContext = null;
169
+ window.setChatContextFromId = function (id) {
170
+ const pre = document.querySelector(`#content-${id} pre`);
171
+ window.chatContext = pre ? pre.textContent.trim() : null;
172
+ const chatOutput = document.getElementById("chat-output");
173
+ if (chatOutput) {
174
+ chatOutput.innerHTML += `<p class="text-xs text-gray-500"><em>Context set from selected report.</em></p>`;
175
+ chatOutput.scrollTop = chatOutput.scrollHeight;
176
+ }
177
+ };
178
+
179
+ function toggleOCR(id) {
180
+ const content = document.getElementById(`content-${id}`);
181
+ const arrow = document.getElementById(`arrow-${id}`);
182
+ if (content.style.maxHeight && content.style.maxHeight !== "0px") {
183
+ content.style.maxHeight = "0px";
184
+ arrow.style.transform = "rotate(0deg)";
185
  } else {
186
+ content.style.maxHeight = content.scrollHeight + "px";
187
+ arrow.style.transform = "rotate(90deg)";
188
  }
 
 
189
  }
 
190
 
191
+ function renderAnalysisSafe(item) {
192
+ console.log("Rendering report:", item);
193
+
194
+ const createdAt =
195
+ item.createdAt && item.createdAt.toDate
196
+ ? item.createdAt.toDate().toLocaleString()
197
+ : "Date unknown";
198
+
199
+ const uniqueId = `ocr-${Date.now()}-${Math.random()
200
+ .toString(36)
201
+ .substr(2, 9)}`;
202
+ const ocrText = item.ocr_text || "No OCR text available.";
203
+ const reportDate = item.reportDate || "N/A";
204
+
205
+ const anomalies = Array.isArray(item.Detected_Anomalies)
206
+ ? item.Detected_Anomalies
207
+ : [];
208
+
209
+ return `
210
+ <div class="bg-white border border-gray-200 rounded-lg p-4 shadow">
211
+ <div class="flex justify-between mb-2">
212
+ <div class="text-xs text-gray-500">${createdAt}</div>
213
  </div>
214
+
215
+ <div class="mb-4">
216
+ <div class="font-semibold text-green-700 cursor-pointer hover:text-green-800 py-2 flex justify-between items-center"
217
+ onclick="toggleOCR('${uniqueId}')">
218
+ <span>Report: ${reportDate}</span>
219
+ <span class="arrow transition-transform duration-300" id="arrow-${uniqueId}">▶</span>
220
+ </div>
221
+ <div class="ocr-content overflow-hidden transition-all duration-300 max-h-0" id="content-${uniqueId}">
222
+ <div class="mt-2 p-3 bg-gray-50 rounded border">
223
+ <pre class="whitespace-pre-wrap text-sm text-gray-700">${ocrText}</pre>
224
+ </div>
225
  </div>
226
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
227
 
228
+ ${anomalies
229
+ .map(
230
+ (r, i) => `
231
+ <div class="border-t border-gray-200 pt-2 mt-2">
232
+ <div class="font-medium">Finding ${i + 1}: ${
233
+ r.findings || "N/A"
234
+ }</div>
235
+ <div class="text-sm text-gray-600">Severity: ${
236
+ r.severity || "N/A"
237
+ }</div>
238
+ <div class="text-sm text-gray-600">Recommendations: ${(
239
+ r.recommendations || []
240
+ ).join(", ")}</div>
241
+ </div>
242
+ `
243
+ )
244
+ .join("")}
245
+
246
+ <button onclick="setChatContextFromId('${uniqueId}')"
247
+ class="mt-3 px-4 py-2 bg-[var(--tropical-indigo)] text-white rounded hover:bg-indigo-600">
248
+ Chat about this report
249
+ </button>
250
+ </div>
251
+ `;
252
  }
 
 
 
 
 
253
 
254
+ onAuthStateChanged(auth, async (user) => {
255
+ const authNavItem = document.getElementById("authNavItem");
256
+ if (user) {
257
+ authNavItem.innerHTML =
258
+ '<button onclick="logout()" class="hover:text-[#6B9080] text-red-600">Logout</button>';
259
+ statusEl.textContent = `Signed in as ${user.email || user.uid}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
 
261
+ try {
262
+ const q = query(
263
+ collection(db, "users", user.uid, "analyses"),
264
+ orderBy("createdAt", "desc")
265
+ );
266
+ const snap = await getDocs(q);
267
 
268
+ if (snap.empty) {
269
+ recsEl.innerHTML =
270
+ '<p class="text-sm text-gray-500">No saved analyses yet.</p>';
271
+ return;
272
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
274
+ const analyses = [];
275
+ snap.forEach((doc) => analyses.push({ id: doc.id, ...doc.data() }));
276
+ recsEl.innerHTML = analyses.map(renderAnalysisSafe).join("");
277
+ } catch (err) {
278
+ console.error("Error fetching reports:", err);
279
+ recsEl.innerHTML =
280
+ '<p class="text-sm text-red-500">Error loading analyses.</p>';
281
  }
282
+ } else {
283
+ authNavItem.innerHTML =
284
+ '<a href="login.html" class="hover:text-[#6B9080]">Login</a>';
285
+ statusEl.textContent = "Not signed in.";
286
+ recsEl.innerHTML =
287
+ '<p class="text-sm text-gray-500">Please sign in to see your analyses.</p>';
288
+ }
289
+ });
290
 
291
+ window.logout = async () => {
292
+ try {
293
+ await signOut(auth);
294
+ localStorage.clear();
295
+ window.location.href = "login.html";
296
+ } catch (err) {
297
+ console.error("Error signing out:", err);
298
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  };
300
+ </script>
301
+ </body>
302
+ </html>