vineelagampa TheFrogGod commited on
Commit
6a15a6c
·
verified ·
1 Parent(s): 1c61e4d

Profile now has Data from Measurements API (#56)

Browse files

- Profile now has Data from Measurements API (acd3bb8ced5bbfb0ef26cb12470c973ffc44952b)


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

Files changed (1) hide show
  1. web/profile.html +174 -148
web/profile.html CHANGED
@@ -6,6 +6,7 @@
6
  <title>Profile - CTRL + ALT + HEAL</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="style.css" />
 
9
  </head>
10
  <body class="bg-[#F7F8F9] min-h-screen">
11
  <!-- NAVBAR -->
@@ -224,22 +225,176 @@
224
  '#mobile-menu a[href="index.html"]'
225
  )?.parentElement;
226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  // ✅ Auth State Handling
228
  onAuthStateChanged(auth, async (user) => {
229
- const authNavItem = document.getElementById("authNavItem");
230
- if (user) {
231
- currentUser = user;
232
- await loadUserProfile();
233
- authNavItem.innerHTML = '<button onclick="logout()" style="color: red;">Logout</button>';
234
- if (homeNavDesktop) homeNavDesktop.style.display = "none";
235
- if (homeNavMobile) homeNavMobile.style.display = "none";
236
- } else {
237
- authNavItem.innerHTML = '<a href="login.html">Login</a>';
238
- if (homeNavDesktop) homeNavDesktop.style.display = "";
239
- if (homeNavMobile) homeNavMobile.style.display = "";
240
- window.location.href = "login.html";
241
- }
242
- });
 
 
 
 
 
 
 
 
 
 
243
 
244
  async function loadUserProfile() {
245
  try {
@@ -280,7 +435,7 @@
280
  }
281
  };
282
 
283
- document.addEventListener("DOMContentLoaded", () => {
284
  const profileView = document.getElementById("profileViewSection");
285
  const profileEdit = document.getElementById("profileEditSection");
286
  const editBtn = document.getElementById("editProfileBtn");
@@ -295,6 +450,8 @@
295
  profileView.classList.add("hidden");
296
  profileEdit.classList.remove("hidden");
297
  });
 
 
298
 
299
  saveBtn.addEventListener("click", async () => {
300
  const nameVal = inputName.value.trim();
@@ -320,139 +477,8 @@
320
  // RANGE BARS LOGIC
321
  const tabs = document.querySelectorAll(".tab");
322
  const contents = document.querySelectorAll(".tab-content");
323
- const measurements = [
324
- {
325
- name: "Blood Sugar",
326
- min: 70,
327
- max: 110,
328
- value: 95,
329
- tab: "in-range",
330
- impacts: ["Pancreas"],
331
- },
332
- {
333
- name: "Cholesterol",
334
- min: 120,
335
- max: 200,
336
- value: 180,
337
- tab: "in-range",
338
- impacts: ["Heart", "Arteries"],
339
- },
340
- {
341
- name: "Triglycerides",
342
- min: 50,
343
- max: 150,
344
- value: 180,
345
- tab: "out-range",
346
- impacts: ["Heart"],
347
- },
348
- {
349
- name: "Blood Pressure",
350
- min: 90,
351
- max: 120,
352
- value: 130,
353
- tab: "out-range",
354
- impacts: ["Heart", "Kidneys"],
355
- },
356
- ];
357
-
358
- const counts = { "in-range": 0, "out-range": 0 };
359
-
360
- measurements.forEach((m) => {
361
- counts[m.tab]++;
362
- const container = document.getElementById(m.tab);
363
- const card = document.createElement("div");
364
- card.className = "range-card";
365
- const title = document.createElement("h3");
366
- title.textContent = m.name;
367
- card.appendChild(title);
368
- if (m.impacts) {
369
- const impactLabel = document.createElement("div");
370
- impactLabel.className = "impact-label";
371
- impactLabel.textContent = "Impacts: " + m.impacts.join(", ");
372
- card.appendChild(impactLabel);
373
- }
374
- const barContainer = document.createElement("div");
375
- barContainer.className = "range-bar-container";
376
- const bar = document.createElement("div");
377
- bar.className = "range-bar";
378
-
379
- let normalPercent = 100;
380
- let overflowPercent = 0;
381
- if (m.tab === "out-range" && m.value > m.max) {
382
- normalPercent = ((m.max - m.min) / (m.value - m.min)) * 100;
383
- overflowPercent = 100 - normalPercent;
384
- }
385
-
386
- const normalDiv = document.createElement("div");
387
- normalDiv.className = "normal-range";
388
- normalDiv.style.width = normalPercent + "%";
389
- bar.appendChild(normalDiv);
390
- if (overflowPercent > 0) {
391
- const overflowDiv = document.createElement("div");
392
- overflowDiv.className = "overflow-range";
393
- overflowDiv.style.left = normalPercent + "%";
394
- overflowDiv.style.width = overflowPercent + "%";
395
- bar.appendChild(overflowDiv);
396
- }
397
-
398
- let valuePercent = ((m.value - m.min) / (m.max - m.min)) * 100;
399
- valuePercent = Math.min(Math.max(valuePercent, 0), 100);
400
- const marker = document.createElement("div");
401
- marker.className = "marker";
402
- marker.style.left = valuePercent + "%";
403
- bar.appendChild(marker);
404
- const valueLabel = document.createElement("div");
405
- valueLabel.className = "value-label";
406
- valueLabel.style.left = valuePercent + "%";
407
- valueLabel.textContent = m.value;
408
- bar.appendChild(valueLabel);
409
-
410
- barContainer.appendChild(bar);
411
-
412
- const minMaxDiv = document.createElement("div");
413
- minMaxDiv.className = "min-max-labels relative w-full";
414
-
415
- const minLabel = document.createElement("span");
416
- minLabel.textContent = "Min: " + m.min;
417
- minLabel.style.position = "absolute";
418
- minLabel.style.left = "0";
419
-
420
- const maxLabel = document.createElement("span");
421
- maxLabel.textContent = "Max: " + m.max;
422
- maxLabel.style.position = "absolute";
423
-
424
- // put the max label at the end of the green section
425
- let maxPercent = 100;
426
- if (m.value > m.max) {
427
- maxPercent = ((m.max - m.min) / (m.value - m.min)) * 100;
428
- }
429
- maxLabel.style.left = maxPercent + "%";
430
- maxLabel.style.transform = "translateX(-100%)"; // anchor it properly
431
-
432
- minMaxDiv.appendChild(minLabel);
433
- minMaxDiv.appendChild(maxLabel);
434
- barContainer.appendChild(minMaxDiv);
435
-
436
-
437
- card.appendChild(barContainer);
438
- container.appendChild(card);
439
- });
440
-
441
- tabs.forEach((tab) => {
442
- const t = tab.dataset.tab;
443
- const badge = tab.querySelector(".count-badge");
444
- badge.textContent = counts[t];
445
- tab.addEventListener("click", () => {
446
- tabs.forEach((t) => t.classList.remove("active"));
447
- tab.classList.add("active");
448
- contents.forEach((c) =>
449
- c.id === t
450
- ? c.classList.add("active")
451
- : c.classList.remove("active")
452
- );
453
- });
454
- });
455
  });
456
  </script>
457
  </body>
458
- </html>
 
6
  <title>Profile - CTRL + ALT + HEAL</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="style.css" />
9
+ <script src="script.js"></script>
10
  </head>
11
  <body class="bg-[#F7F8F9] min-h-screen">
12
  <!-- NAVBAR -->
 
225
  '#mobile-menu a[href="index.html"]'
226
  )?.parentElement;
227
 
228
+ // Fetch measurements from backend API
229
+ async function getUserMeasurements(userId) {
230
+ try {
231
+ const url = api("user_measurements/", { user_id: userId });
232
+ const res = await fetch(url);
233
+ if (!res.ok) throw new Error("Failed to fetch measurements");
234
+
235
+ const data = await res.json();
236
+
237
+ return (data.measurements || []).map((m) => ({
238
+ name: m.measurement_type,
239
+ value: Number(m.value),
240
+ min: Number(m.min),
241
+ max: Number(m.max),
242
+ tab: m.status === "HIGH" || m.status === "LOW" ? "out-range" : "in-range",
243
+ impacts: m.impacts || [],
244
+ }));
245
+ } catch (e) {
246
+ console.error("Error fetching user measurements:", e);
247
+ return [];
248
+ }
249
+ }
250
+ function getLatestByType(measurements) {
251
+ const latest = {};
252
+
253
+ measurements.forEach(m => {
254
+ if (!latest[m.name] || new Date(m.timestamp) > new Date(latest[m.name].timestamp)) {
255
+ latest[m.name] = m;
256
+ }
257
+ });
258
+
259
+ return Object.values(latest);
260
+ }
261
+
262
+
263
+ // Render bars in the UI based on measurement array
264
+ function renderBars(measurements) {
265
+ console.log("measurements",measurements);
266
+ const counts = { "in-range": 0, "out-range": 0 };
267
+ const tabs = document.querySelectorAll(".tab");
268
+ const contents = document.querySelectorAll(".tab-content");
269
+
270
+ // Clear existing content
271
+ contents.forEach((c) => (c.innerHTML = ""));
272
+
273
+ measurements.forEach((m) => {
274
+ counts[m.tab]++;
275
+ const container = document.getElementById(m.tab);
276
+ const card = document.createElement("div");
277
+ card.className = "range-card";
278
+
279
+ const title = document.createElement("h3");
280
+ title.className = "measurement-title";
281
+ title.textContent = m.name;
282
+ card.appendChild(title);
283
+
284
+ if (m.impacts?.length) {
285
+ const impactLabel = document.createElement("div");
286
+ impactLabel.className = "impact-label";
287
+ impactLabel.textContent = "Impacts: " + m.impacts.join(", ");
288
+ card.appendChild(impactLabel);
289
+ }
290
+
291
+ const barContainer = document.createElement("div");
292
+ barContainer.className = "range-bar-container";
293
+ const bar = document.createElement("div");
294
+ bar.className = "range-bar";
295
+
296
+ let normalPercent = 100;
297
+ let overflowPercent = 0;
298
+ if (m.tab === "out-range" && m.value > m.max) {
299
+ normalPercent = ((m.max - m.min) / (m.value - m.min)) * 100;
300
+ overflowPercent = 100 - normalPercent;
301
+ }
302
+
303
+ const normalDiv = document.createElement("div");
304
+ normalDiv.className = "normal-range";
305
+ normalDiv.style.width = normalPercent + "%";
306
+ bar.appendChild(normalDiv);
307
+
308
+ if (overflowPercent > 0) {
309
+ const overflowDiv = document.createElement("div");
310
+ overflowDiv.className = "overflow-range";
311
+ overflowDiv.style.left = normalPercent + "%";
312
+ overflowDiv.style.width = overflowPercent + "%";
313
+ bar.appendChild(overflowDiv);
314
+ }
315
+
316
+ let valuePercent = ((m.value - m.min) / (m.max - m.min)) * 100;
317
+ valuePercent = Math.min(Math.max(valuePercent, 0), 100);
318
+
319
+ const marker = document.createElement("div");
320
+ marker.className = "marker";
321
+ marker.style.left = valuePercent + "%";
322
+ bar.appendChild(marker);
323
+
324
+ const valueLabel = document.createElement("div");
325
+ valueLabel.className = "value-label";
326
+ valueLabel.style.left = valuePercent + "%";
327
+ valueLabel.textContent = m.value;
328
+ bar.appendChild(valueLabel);
329
+
330
+ barContainer.appendChild(bar);
331
+
332
+ const minMaxDiv = document.createElement("div");
333
+ minMaxDiv.className = "min-max-labels relative w-full";
334
+
335
+ const minLabel = document.createElement("span");
336
+ minLabel.textContent = "Min: " + m.min;
337
+ minLabel.style.position = "absolute";
338
+ minLabel.style.left = "0";
339
+
340
+ const maxLabel = document.createElement("span");
341
+ maxLabel.textContent = "Max: " + m.max;
342
+ maxLabel.style.position = "absolute";
343
+
344
+ let maxPercent = 100;
345
+ if (m.value > m.max) maxPercent = ((m.max - m.min) / (m.value - m.min)) * 100;
346
+ maxLabel.style.left = maxPercent + "%";
347
+ maxLabel.style.transform = "translateX(-100%)";
348
+
349
+ minMaxDiv.appendChild(minLabel);
350
+ minMaxDiv.appendChild(maxLabel);
351
+ barContainer.appendChild(minMaxDiv);
352
+
353
+ card.appendChild(barContainer);
354
+ container.appendChild(card);
355
+ });
356
+
357
+ // Update tab badges
358
+ tabs.forEach((tab) => {
359
+ const t = tab.dataset.tab;
360
+ const badge = tab.querySelector(".count-badge");
361
+ badge.textContent = counts[t];
362
+ tab.addEventListener("click", () => {
363
+ tabs.forEach((t) => t.classList.remove("active"));
364
+ tab.classList.add("active");
365
+ contents.forEach((c) =>
366
+ c.id === t ? c.classList.add("active") : c.classList.remove("active")
367
+ );
368
+ });
369
+ });
370
+ }
371
+
372
  // ✅ Auth State Handling
373
  onAuthStateChanged(auth, async (user) => {
374
+ const authNavItem = document.getElementById("authNavItem");
375
+ if (user) {
376
+ currentUser = user;
377
+ await loadUserProfile();
378
+
379
+ // fetch and render bars after user is ready
380
+ console.log("currentuser data",currentUser);
381
+ // const measurements = await getUserMeasurements(currentUser.uid);
382
+ let measurements = await getUserMeasurements(currentUser.email);
383
+ measurements = getLatestByType(measurements);
384
+
385
+ renderBars(measurements);
386
+
387
+ authNavItem.innerHTML = '<button onclick="logout()" style="color:red">Logout</button>';
388
+ if (homeNavDesktop) homeNavDesktop.style.display = "none";
389
+ if (homeNavMobile) homeNavMobile.style.display = "none";
390
+ } else {
391
+ authNavItem.innerHTML = '<a href="login.html">Login</a>';
392
+ if (homeNavDesktop) homeNavDesktop.style.display = "";
393
+ if (homeNavMobile) homeNavMobile.style.display = "";
394
+ window.location.href = "login.html";
395
+ }
396
+ });
397
+
398
 
399
  async function loadUserProfile() {
400
  try {
 
435
  }
436
  };
437
 
438
+ document.addEventListener("DOMContentLoaded", async () => {
439
  const profileView = document.getElementById("profileViewSection");
440
  const profileEdit = document.getElementById("profileEditSection");
441
  const editBtn = document.getElementById("editProfileBtn");
 
450
  profileView.classList.add("hidden");
451
  profileEdit.classList.remove("hidden");
452
  });
453
+
454
+
455
 
456
  saveBtn.addEventListener("click", async () => {
457
  const nameVal = inputName.value.trim();
 
477
  // RANGE BARS LOGIC
478
  const tabs = document.querySelectorAll(".tab");
479
  const contents = document.querySelectorAll(".tab-content");
480
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  });
482
  </script>
483
  </body>
484
+ </html>