PRMSChallenge / web /profile.html
vineelagampa's picture
Update web/profile.html (#16)
8f7467e verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Profile - CTRL + ALT + HEAL</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body class="bg-[#F7F8F9] min-h-screen">
<!-- NAVBAR -->
<nav
class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
>
<div class="flex justify-between items-center w-full px-6 py-4">
<!-- Logo -->
<a
href="index.html"
class="text-2xl font-bold text-black hover:text-[var(--tropical-indigo)] transition"
>
CTRL + ALT + HEAL
</a>
<ul class="hidden md:flex space-x-6 font-medium text-gray-800">
<li><a href="index.html" class="nav-link" style="display:none;">Home</a></li>
<li><a href="profile.html" class="nav-link">Profile</a></li>
<li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
<li><a href="past_data.html" class="nav-link">Past Reports</a></li>
<li id="authNavItem"><a href="login.html" class="nav-link">Login</a></li>
</ul>
<!-- Hamburger Menu -->
<button
id="hamburger"
class="md:hidden text-[var(--latte-cream)] text-2xl"
>
</button>
</div>
<!-- Changes added for change marker for style change-->
<!-- Mobile Menu -->
<ul
id="mobile-menu"
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"
>
<li>
<a
href="index.html"
class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
>Home</a
>
</li>
<li>
<a
href="analyzer.html"
class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
>Analyzer</a
>
</li>
<li>
<a
href="profile.html"
class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
>Profile</a
>
</li>
<li>
<a
href="login.html"
class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
>Login</a
>
</li>
<li>
<a
href="about.html"
class="block text-gray-800 hover:text-[var(--tropical-indigo)]"
>About</a
>
</li>
>
</li>
</ul>
</nav>
<script>
const hamburger = document.getElementById("hamburger");
const mobileMenu = document.getElementById("mobile-menu");
hamburger.addEventListener("click", () => {
mobileMenu.classList.toggle("hidden");
});
// Underline the active page only
const currentPath = window.location.pathname.split("/").pop();
document.querySelectorAll(".nav-link").forEach((link) => {
if (link.getAttribute("href") === currentPath) {
link.classList.add("active-page"); // we'll style this in CSS
}
});
document.querySelectorAll("#mobile-menu a").forEach((link) => {
if (link.getAttribute("href") === currentPath) {
link.classList.add("active-page");
}
});
</script>
<div class="container mx-auto px-6 pt-24">
<div class="bg-white border border-gray-200 rounded-lg p-6 shadow mb-6">
<!-- VIEW MODE -->
<div id="profileViewSection">
<div class="flex items-start space-x-6 mb-10">
<!-- Avatar & Edit Button -->
<div class="flex flex-col items-center">
<div class="w-32 h-32 bg-gray-300 rounded-full"></div>
<button id="editProfileBtn" class="mt-2 px-4 py-2 rounded">
Edit Profile
</button>
<a href="analyzer.html"
><button id="analyzerBtn" class="mt-2 px-4 py-2 rounded">
Go To Analyzer
</button></a
>
</div>
<!-- User Info -->
<div>
<h2 class="text-xl font-semibold mb-4">Your Profile</h2>
<p class="mb-2">
Name: <span id="userName" class="font-medium">Loading...</span>
</p>
<p class="mb-2">
DOB: <span id="userDOB" class="font-medium">Loading...</span>
</p>
</div>
</div>
</div>
<!-- EDIT MODE -->
<div id="profileEditSection" class="hidden mb-10">
<div class="flex flex-col sm:flex-row items-start space-x-6">
<div class="flex flex-col items-center mb-4 sm:mb-0">
<div class="w-32 h-32 bg-gray-300 rounded-full"></div>
</div>
<div class="flex-1">
<h1 class="text-3xl font-semibold mb-4">Edit Profile</h1>
<div class="space-y-4">
<div>
<label for="inputName" class="block text-sm font-medium"
>Name</label
>
<input
type="text"
id="inputName"
class="w-full border rounded px-3 py-2 focus:ring-2 focus:ring-[#6B9080] focus:outline-none"
/>
</div>
<div>
<label for="inputDOB" class="block text-sm font-medium"
>Date of Birth</label
>
<input
type="date"
id="inputDOB"
class="w-full border rounded px-3 py-2 focus:ring-2 focus:ring-[#6B9080] focus:outline-none"
/>
</div>
</div>
<div class="flex space-x-2 mt-4">
<button id="saveProfileBtn" class="px-4 py-2 rounded">
Save
</button>
<button id="cancelProfileBtn" class="px-4 py-2 rounded">
Cancel
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Chart Section -->
<div class="mt-10" id="chartSection">
<div class="bg-white border border-gray-200 rounded-lg p-6 mb-6">
<h2 class="text-xl font-semibold mb-4">Health Progress</h2>
<div
class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6"
>
<div class="flex flex-1 gap-2">
<input
type="date"
id="entryDate"
class="flex-1 border rounded px-3 py-2 focus:ring-2 focus:ring-[#6B9080] focus:outline-none"
/>
<input
type="number"
id="entryScore"
min="0"
max="100"
placeholder="Score"
class="w-24 border rounded px-3 py-2 focus:ring-2 focus:ring-[#6B9080] focus:outline-none"
/>
</div>
<div class="flex gap-2">
<button id="addEntryBtn" class="px-4 py-2 rounded">
Add Entry
</button>
<button id="resetChartBtn" class="px-4 py-2 rounded">
Reset Chart
</button>
</div>
</div>
<div class="overflow-x-auto">
<canvas id="progressChart" class="w-full h-64"></canvas>
</div>
</div>
</div>
</div>
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
import {
getAuth,
onAuthStateChanged,
signOut,
} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js";
import {
getFirestore,
doc,
getDoc,
updateDoc,
collection,
addDoc,
serverTimestamp,
} from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
const firebaseConfig = {
apiKey: "AIzaSyAKWstCc7HqMgV8DmH2Sy6QwUP3JvZxu9g",
authDomain: "appchallenge-c8fe3.firebaseapp.com",
projectId: "appchallenge-c8fe3",
storageBucket: "appchallenge-c8fe3.firebasestorage.app",
messagingSenderId: "943791692455",
appId: "1:943791692455:web:ae04d06bf09669b6bdd982",
measurementId: "G-HJ7EHW8V4N"
};
// 🔧 Init
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
// Expose Firestore helpers if you need them elsewhere
window.firebaseAuth = auth;
window.onAuthStateChanged = onAuthStateChanged;
window.firestoreDb = db;
window.firestoreHelpers = { collection, doc, addDoc, serverTimestamp };
let currentUser = null;
// ✅ Auth state check
// ✅ Hide Home button when logged in
const homeNavDesktop = document.querySelector('ul.md\\:flex li a[href="index.html"]')
?.parentElement; // Desktop <li>
const homeNavMobile = document.querySelector('#mobile-menu a[href="index.html"]')
?.parentElement; // Mobile <li>
onAuthStateChanged(auth, async (user) => {
const authNavItem = document.getElementById("authNavItem");
if (user) {
currentUser = user;
await loadUserProfile();
// Swap login with logout
if (authNavItem) {
authNavItem.innerHTML =
'<button onclick="logout()" class="hover:text-[#6B9080] text-red-600">Logout</button>';
}
// Hide Home button
if (homeNavDesktop) homeNavDesktop.style.display = "none";
if (homeNavMobile) homeNavMobile.style.display = "none";
} else {
if (authNavItem) {
authNavItem.innerHTML =
'<a href="login.html" class="hover:text-[#6B9080]">Login</a>';
}
// Show Home button again
if (homeNavDesktop) homeNavDesktop.style.display = "";
if (homeNavMobile) homeNavMobile.style.display = "";
window.location.href = "login.html";
}
});
// 📄 Load user profile from Firestore
async function loadUserProfile() {
try {
const userDoc = await getDoc(doc(db, "users", currentUser.uid));
if (userDoc.exists()) {
const userData = userDoc.data();
document.getElementById("userName").textContent =
userData.name || "Name not set";
document.getElementById("userDOB").textContent =
userData.dob || "DOB not set";
localStorage.setItem("userName", userData.name || "");
localStorage.setItem("userDOB", userData.dob || "");
}
} catch (error) {
console.error("Error loading user profile:", error);
}
}
// 💾 Save profile to Firestore
window.saveProfile = async (name, dob) => {
try {
await updateDoc(doc(db, "users", currentUser.uid), {
name: name,
dob: dob,
});
localStorage.setItem("userName", name);
localStorage.setItem("userDOB", dob);
return true;
} catch (error) {
console.error("Error updating profile:", error);
return false;
}
};
// 🚪 Logout
window.logout = async () => {
try {
await signOut(auth);
localStorage.clear();
window.location.href = "login.html";
} catch (error) {
console.error("Error signing out:", error);
}
};
// 📊 LocalStorage for progress data
function loadProgressData() {
return JSON.parse(localStorage.getItem("progressData") || "[]");
}
function saveProgressData(data) {
localStorage.setItem("progressData", JSON.stringify(data));
}
function resetProgressData() {
localStorage.removeItem("progressData");
}
// 🖼️ DOM Content Loaded logic
document.addEventListener("DOMContentLoaded", () => {
const profileView = document.getElementById("profileViewSection");
const profileEdit = document.getElementById("profileEditSection");
const editBtn = document.getElementById("editProfileBtn");
const saveBtn = document.getElementById("saveProfileBtn");
const cancelBtn = document.getElementById("cancelProfileBtn");
const inputName = document.getElementById("inputName");
const inputDOB = document.getElementById("inputDOB");
// Toggle to edit mode
editBtn.addEventListener("click", () => {
inputName.value = document.getElementById("userName").textContent;
inputDOB.value = document.getElementById("userDOB").textContent;
profileView.classList.add("hidden");
profileEdit.classList.remove("hidden");
});
// Save profile
saveBtn.addEventListener("click", async () => {
const nameVal = inputName.value.trim();
const dobVal = inputDOB.value;
const success = await window.saveProfile(nameVal, dobVal);
if (success) {
document.getElementById("userName").textContent =
nameVal || "Name not set";
document.getElementById("userDOB").textContent =
dobVal || "DOB not set";
profileEdit.classList.add("hidden");
profileView.classList.remove("hidden");
} else {
alert("Error saving profile. Please try again.");
}
});
// Cancel editing
cancelBtn.addEventListener("click", () => {
profileEdit.classList.add("hidden");
profileView.classList.remove("hidden");
});
// Chart setup
const chartSection = document.getElementById("chartSection");
const welcomeMessage = document.getElementById("welcomeMessage");
const isNewUser = localStorage.getItem("isNewUser") === "true";
if (isNewUser) {
welcomeMessage.classList.remove("hidden");
chartSection.classList.add("hidden");
}
const stored = loadProgressData();
const labels = stored.map((e) => e.date);
const ctx = document.getElementById("progressChart").getContext("2d");
const progressChart = new Chart(ctx, {
type: "line",
data: {
labels,
datasets: [
{
label: "Health Score",
data: stored.map((e) => e.score),
borderColor: "#6B9080",
fill: true,
tension: 0.4,
},
],
},
options: {
scales: { y: { beginAtZero: true, max: 100 } },
},
});
// Add Entry
document.getElementById("addEntryBtn").addEventListener("click", () => {
const date = document.getElementById("entryDate").value;
const score = parseInt(document.getElementById("entryScore").value, 10);
if (!date || isNaN(score)) {
alert("Please select a date and enter a valid score.");
return;
}
stored.push({ date, score });
saveProgressData(stored);
progressChart.data.labels.push(date);
progressChart.data.datasets[0].data.push(score);
progressChart.update();
document.getElementById("entryDate").value = "";
document.getElementById("entryScore").value = "";
if (isNewUser) {
localStorage.setItem("isNewUser", "false");
welcomeMessage.classList.add("hidden");
chartSection.classList.remove("hidden");
}
});
// Reset Chart
document.getElementById("resetChartBtn").addEventListener("click", () => {
if (!confirm("Are you sure you want to clear all progress data?")) return;
resetProgressData();
progressChart.data.labels = [];
progressChart.data.datasets[0].data = [];
progressChart.update();
});
});
</script>
</body>
</html>