diff --git a/dashboard-euclideans.html b/dashboard-euclideans.html index 7e302392..e6b3e87a 100644 --- a/dashboard-euclideans.html +++ b/dashboard-euclideans.html @@ -359,8 +359,10 @@

Vinternship Dashboard Euclideans

Leaderboard
CS Progress
Health Points
+
My Dashboard
Tickets
Endorsements
+
@@ -495,7 +497,101 @@

Vinternship Dashboard Euclideans

+ +
+
+
+ +

My Dashboard

+ + +
+ + + +
+ + + +
+
Rank:
+
CS: %
+
Vibe: %
+
HP:
+
Overall: %
+
+ +
+
+ + + +

Vibe Milestones

+
+ + +

Case Study Milestones

+
+ + + + +

HP Status

+
+ +
+
+
+
+
@@ -1122,6 +1218,344 @@

Silve // Boot loadAPI(); + + const VIBE_MILESTONES = [ + { label: "Vibe Phase 1", required: 25, deadline: "2026-01-22" }, + { label: "Vibe Phase 2", required: 50, deadline: "2026-01-29" }, + { label: "Vibe Phase 3", required: 75, deadline: "2026-02-05" }, + { label: "Vibe Phase 4", required: 100, deadline: "2026-02-12" } +]; + +// ========= DAILY VIBE RULE ========= +const VIBE_START_DATE = new Date("2026-01-14"); // first day of vibe +const DAILY_VIBE_REQUIRED = 3.33; + +const CS_MILESTONES = [ + { label: "CS Week 1", cumulative: 6, deadline: "2026-02-12" }, + { label: "CS Week 2", cumulative: 18, deadline: "2026-02-19" }, + { label: "CS Week 3", cumulative: 30, deadline: "2026-02-26" }, + { label: "CS Week 4", cumulative: 42, deadline: "2026-03-05" } +]; + +function setEmail() { + const email = document.getElementById("emailInput").value.trim(); + + if (!email) { + alert("Please enter your email"); + return; + } + + localStorage.setItem("userEmail", email); + renderMyDashboard(); +} + +function getMyData() { + const email = localStorage.getItem("userEmail"); + if (!email || !apiData || !apiData.dashboard) return null; + + return apiData.dashboard.find( + r => r.Email && r.Email.toLowerCase() === email.toLowerCase() + ); +} + +function renderMyDashboard() { + const me = getMyData(); + + if (!me) { + document.getElementById("my-rank").textContent = "Not found"; + return; + } + + document.getElementById("my-rank").textContent = me.Rank; + document.getElementById("my-cs").textContent = me["Case Study Progress"]; + document.getElementById("my-vibe").textContent = me["Vibe Progress"]; + document.getElementById("my-hp").textContent = me["Health Points"]; + document.getElementById("my-overall").textContent = me["Overall Progress"]; + + console.log("Rendering vibe milestones"); + renderMyVibe(); + renderMyCS(); + renderMyHPStatus(); + renderNextDeadline(); +} + +function getMyVibeProgress() { + const email = localStorage.getItem("userEmail"); + if (!email || !apiData || !apiData.dashboard) return 0; + + const row = apiData.dashboard.find( + r => r.Email && r.Email.toLowerCase() === email.toLowerCase() + ); + + return row ? Number(row["Vibe Progress"]) : 0; +} + +function getExpectedVibeProgressToday() { + const today = new Date(); + const daysPassed = Math.floor( + (today - VIBE_START_DATE) / (1000 * 60 * 60 * 24) + ); + + if (daysPassed <= 0) return 0; + + return Math.min(100, daysPassed * DAILY_VIBE_REQUIRED); +} + +function getDailyVibeCheck() { + const actual = getMyVibeProgress(); + const expected = getExpectedVibeProgressToday(); + + if (actual >= expected) { + return { + onTrack: true, + message: `📈 Daily Vibe: On track (${actual.toFixed(1)}% ≥ ${expected.toFixed(1)}%)` + }; + } + + const deficit = (expected - actual).toFixed(1); + + return { + onTrack: false, + message: `⚠️ Daily Vibe lagging by ${deficit}% (Expected ${expected.toFixed(1)}%)` + }; +} + + +function computeVibeStatus() { + const current = getMyVibeProgress(); + const now = new Date(); + + return VIBE_MILESTONES.map(m => ({ + ...m, + current, + completed: current >= m.required, + isLate: now > new Date(m.deadline) && current < m.required + })); +} + +function renderMyVibe() { + const container = document.getElementById("my-vibe-section"); + const vibeData = computeVibeStatus(); + + container.innerHTML = vibeData.map(v => { + const shown = Math.min(v.current, v.required); + + let status = + v.completed ? "✅ Completed" + : v.isLate ? "❌ Missed deadline" + : "⚠️ In progress"; + + return ` +
+ ${v.label} — ${shown}% / ${v.required}% +  |  ${status} +  |  Deadline: ${v.deadline} +
+ `; + }).join(""); +} + +function getMyCSCount() { + const email = localStorage.getItem("userEmail"); + if (!email || !apiData || !apiData.csProgress) return 0; + + const row = apiData.csProgress.find( + r => r.Email && r.Email.toLowerCase() === email.toLowerCase() + ); + + if (!row) return 0; + + let count = 0; + + Object.keys(row).forEach(key => { + if ( + key.includes("_CS") && + !key.toLowerCase().includes("progress") + ) { + const val = row[key]; + + if (val === "Yes" || val === "✓" || val === true) { + count++; + } + } + }); + + return count; +} + +function computeCSStatus() { + const submitted = getMyCSCount(); + const now = new Date(); + + return CS_MILESTONES.map(m => { + const required = Number(m.cumulative); + const shown = Math.min(submitted, required); + + return { + label: m.label, + submitted: shown, + required, + completed: submitted >= required, + isLate: now > new Date(m.deadline) && submitted < required, + deadline: m.deadline + }; + }); +} + +function renderMyCS() { + const container = document.getElementById("my-cs-section"); + if (!container) return; + + const csData = computeCSStatus(); + + container.innerHTML = csData.map(cs => { + let status = + cs.completed ? "✅ Completed" + : cs.isLate ? "❌ Missed deadline" + : "⚠️ In progress"; + + return ` +
+ ${cs.label} — ${cs.submitted} / ${cs.required} CS +  |  ${status} +  |  Deadline: ${cs.deadline} +
+ `; + }).join(""); +} + +function renderMyHPStatus() { + const statusEl = document.getElementById("my-hp-status"); + const actionEl = document.getElementById("my-hp-action"); + + if (!statusEl || !actionEl || !hpData) return; + + const email = localStorage.getItem("userEmail"); + if (!email) return; + + const me = hpData.leaderboard.find( + r => r.email && r.email.toLowerCase() === email.toLowerCase() + ); + + if (!me) return; + + const isSafe = me.status === "SAFE"; + + // STATUS PILL + statusEl.innerHTML = ` + HP STATUS: ${me.status} + (Current: ${me.currentHP.toFixed(2)} | Base: ${me.baseHP.toFixed(2)}) + `; + + statusEl.style.background = isSafe ? "#C8E6C9" : "#FFCDD2"; + statusEl.style.color = isSafe ? "#1B5E20" : "#B71C1C"; + + // ACTION GUIDANCE + actionEl.style.display = "block"; + + const vibeStatus = computeVibeStatus(); +const csStatus = computeCSStatus(); + +// find first pending / missed items +const pendingVibe = vibeStatus.find(v => !v.completed); +const pendingCS = csStatus.find(c => !c.completed); + +let messages = []; +// DAILY VIBE CHECK +const dailyVibe = getDailyVibeCheck(); +messages.push(dailyVibe.message); + + +if (pendingVibe) { + if (pendingVibe.isLate) { + messages.push(`❌ Missed ${pendingVibe.label} deadline`); + } else { + messages.push(`⏳ ${pendingVibe.label} in progress`); + } +} + +if (pendingCS) { + if (pendingCS.isLate) { + messages.push(`❌ ${pendingCS.label} missed`); + } else { + messages.push(`⏳ ${pendingCS.label} incomplete (${pendingCS.submitted}/${pendingCS.required})`); + } +} + +if (isSafe) { + actionEl.style.background = "#E8F5E9"; + actionEl.style.color = "#1B5E20"; + actionEl.innerHTML = ` + ✅ You are SAFE.
+ ${messages.length ? messages.join("
") : "All milestones on track."} + `; +} else { + actionEl.style.background = "#FDECEA"; + actionEl.style.color = "#B71C1C"; + actionEl.innerHTML = ` + ⚠️ You are UNSAFE. Focus areas:
+ ${messages.join("
")} +
👉 Priority: Complete the earliest pending milestone. + `; + } +} + +function renderNextDeadline() { + const el = document.getElementById("my-next-deadline"); + if (!el) return; + + const vibe = computeVibeStatus(); + const cs = computeCSStatus(); + + const pending = [...vibe, ...cs] + .filter(m => !m.completed) + .sort((a, b) => new Date(a.deadline) - new Date(b.deadline)); + + + if (!pending.length) { + el.textContent = "No upcoming deadlines. You’re all caught up!"; + el.style.background = "#E8F5E9"; + el.style.color = "#1B5E20"; + return; + } + + const next = pending[0]; + const daysLeft = Math.ceil( + (new Date(next.deadline) - new Date()) / (1000 * 60 * 60 * 24) + ); + + el.textContent = `⏰ Next Deadline: ${next.label} — ${next.deadline} (${daysLeft} days left)`; + + if (daysLeft <= 0) { + el.style.background = "#FFCDD2"; + el.style.color = "#B71C1C"; + } else if (daysLeft <= 3) { + el.style.background = "#FFF3CD"; + el.style.color = "#856404"; + } else { + el.style.background = "#E3F2FD"; + el.style.color = "#0D47A1"; + } +} + +document.getElementById("view-my-cs")?.addEventListener("click", () => { + const email = localStorage.getItem("userEmail"); + if (!email) return; + + // switch to CS tab + activateTopTab("cs"); + + // wait for CS tab to render + setTimeout(() => { + const search = document.getElementById("cs-search"); + if (!search) return; + + search.value = email; + search.dispatchEvent(new Event("input", { bubbles: true })); + search.focus(); + }, 300); +}); +