Rise to your healthiest self
๐Ÿ” Welcome Back
๐Ÿš€ Create Account
J
๐Ÿฅ Health Dashboard
Enter your daily health data below
๐Ÿ‘ค

Basic Details

Age, Height, Weight, Vitals

ENTER
๐Ÿฅ—

Food Routine

Meals, Water intake, Snacks

ENTER
๐ŸŒ™

Sleep Cycle

Hours, Quality, Pattern

ENTER
โšก

Body Condition

Energy levels, Activities

ENTER
๐Ÿ’จ

Breathing

Breathing levels at rest & activity

ENTER
๐Ÿ‘ค Basic Details
Core health metrics
๐Ÿ“‹ Required Information
๐Ÿฉบ Optional Vitals
๐Ÿฅ— Food Routine
Track your daily nutrition
๐Ÿฝ๏ธ Meals Per Day
๐Ÿ’ง Water & Snacks
๐ŸŒ™ Sleep Cycle
Your rest and recovery patterns
๐Ÿ’ค Sleep Details
โšก Body Condition
Energy levels throughout your day
๐Ÿ”‹ Energy Levels

Rate your energy: 1 (Exhausted) โ†’ 5 (Very Energetic)

Exhausted3Energetic
Exhausted3Energetic
Exhausted3Energetic
Exhausted2Energetic
๐Ÿƒ Physical Activities
๐Ÿ’จ Breathing
Respiratory health indicators
๐Ÿซ Breathing Levels
๐Ÿงฌ Digital Twin
Your virtual health representation
๐Ÿ’ฏ Health Score
-- /100
OVERALL HEALTH SCORE
๐Ÿ“Š Health Trend (7 Days)
๐ŸŽฏ Lifestyle Correction
Your personalized improvement plan
๐ŸŽฏ
Run Analysis first to get your personalized plan
๐Ÿ”ฎ Simulation Mode
Predict your future health outcomes
โš™๏ธ Adjust Lifestyle Variables
๐Ÿ“ˆ Predicted Outcomes
๐Ÿ† Habit Tracker
Build your daily health rituals
๐Ÿ”ฅ
0
Day Streak
0
Completed Today
7
Total Habits
โœ… Today's Habits
๐Ÿ“Š Weekly Completion
๐Ÿค– JARVIS AI
Your personal health assistant
โšก JARVIS
Hello! I'm JARVIS, your AI health assistant. I have access to your health data and can answer questions about your diet, exercise, sleep, medical concerns, and more. How can I help you today?
๐Ÿ“Š Weekly Report
Your health trends this week
+12%
Health Score
Improvement
6.8h
Avg Sleep
This Week
74%
Habit Rate
Completion
-8%
Risk Score
Reduction
๐Ÿ“ˆ Health Score Trend
๐ŸŽฏ Key Insights
โš™๏ธ Settings
Manage your profile
๐Ÿ‘ค Profile Information
๐Ÿ”” Notifications
Smart Alerts
Health risk warnings
Daily Reminders
Habit check-ins
๐Ÿ“ฑ App Information
App VersionJARVIS v1.0
AI EngineGemini 2.0
DatabaseFirebase
// ============================================================ // STATE // ============================================================ window.appState = { currentUser: null, healthData: {}, analysisResult: null, habitData: { streak: 0, habits: [] }, charts: {} }; const defaultHabits = [ { id: 'sleep', name: '๐Ÿ’ค Sleep 7+ Hours', desc: 'Get quality rest tonight', done: false }, { id: 'water', name: '๐Ÿ’ง Drink 2L Water', desc: 'Stay hydrated all day', done: false }, { id: 'exercise', name: '๐Ÿƒ Exercise 30 mins', desc: 'Any physical activity', done: false }, { id: 'meditation', name: '๐Ÿง˜ Meditate 10 mins', desc: 'Reduce stress & anxiety', done: false }, { id: 'fruits', name: '๐ŸŽ Eat Fruits/Veggies', desc: 'At least 2 servings', done: false }, { id: 'nosugar', name: '๐Ÿšซ Limit Sugar', desc: 'Avoid excess sweets', done: false }, { id: 'steps', name: '๐Ÿ‘ฃ 10K Steps', desc: 'Walk throughout the day', done: false } ]; // ============================================================ // SPLASH โ†’ AUTH // ============================================================ setTimeout(() => { showPage('auth'); showAuthCard('login'); }, 3100); // ============================================================ // AUTH FUNCTIONS // ============================================================ window.showAuthCard = (type) => { document.getElementById('auth-login').classList.remove('active'); document.getElementById('auth-register').classList.remove('active'); document.getElementById('auth-' + type).classList.add('active'); }; window.handleLogin = async () => { const u = document.getElementById('login-username').value.trim(); const p = document.getElementById('login-password').value; const errEl = document.getElementById('login-error'); if (!u || !p) { errEl.textContent = 'Please enter username and password'; return; } try { const docRef = doc(db, 'users', u); const snap = await getDoc(docRef); if (!snap.exists()) { errEl.textContent = 'โŒ User not found. Please register.'; return; } const userData = snap.data(); if (userData.password !== btoa(p)) { errEl.textContent = 'โŒ Incorrect password'; return; } appState.currentUser = { username: u, ...userData }; loadApp(); } catch(e) { errEl.textContent = 'โš ๏ธ Login error: ' + e.message; } }; window.handleRegister = async () => { const name = document.getElementById('reg-name').value.trim(); const phone = document.getElementById('reg-phone').value.trim(); const u = document.getElementById('reg-username').value.trim(); const p = document.getElementById('reg-password').value; const errEl = document.getElementById('reg-error'); if (!name || !phone || !u || !p) { errEl.textContent = 'Please fill all fields'; return; } try { const docRef = doc(db, 'users', u); const snap = await getDoc(docRef); if (snap.exists()) { errEl.textContent = 'โŒ Username already taken'; return; } const userData = { name, phone, username: u, password: btoa(p), createdAt: new Date().toISOString() }; await setDoc(docRef, userData); appState.currentUser = { username: u, ...userData }; loadApp(); } catch(e) { errEl.textContent = 'โš ๏ธ Registration error: ' + e.message; } }; window.handleLogout = () => { appState.currentUser = null; appState.healthData = {}; appState.analysisResult = null; showPage('auth'); showAuthCard('login'); }; async function loadApp() { const user = appState.currentUser; document.getElementById('header-greeting').textContent = 'Hi, ' + user.name.split(' ')[0]; document.getElementById('header-avatar').textContent = user.name[0].toUpperCase(); // Load health data try { const snap = await getDoc(doc(db, 'healthData', user.username)); if (snap.exists()) { appState.healthData = snap.data(); updateInputStatuses(); } } catch(e) {} // Load habits const today = new Date().toDateString(); const savedHabits = JSON.parse(localStorage.getItem('jarvis_habits_' + user.username) || 'null'); if (savedHabits && savedHabits.date === today) { appState.habitData.habits = savedHabits.habits; } else { appState.habitData.habits = JSON.parse(JSON.stringify(defaultHabits)); } const streakData = JSON.parse(localStorage.getItem('jarvis_streak_' + user.username) || '{"streak":0}'); appState.habitData.streak = streakData.streak || 0; showPage('app'); generateMealFields(); renderHabits(); renderSmartAlerts(); initSimulation(); renderReport(); loadSettingsForm(); // Set settings form document.getElementById('set-name').value = user.name || ''; document.getElementById('set-phone').value = user.phone || ''; document.getElementById('set-username').value = user.username || ''; } // ============================================================ // PAGE NAVIGATION // ============================================================ function showPage(id) { document.querySelectorAll('.page').forEach(p => p.classList.remove('active')); document.getElementById(id).classList.add('active'); } window.navigateTo = (sub) => { document.querySelectorAll('.sub-page').forEach(p => { p.classList.remove('active'); p.style.display = ''; }); document.getElementById('page-' + sub).classList.add('active'); document.getElementById('main-content').scrollTop = 0; }; window.navigateTab = (tab) => { navigateTo(tab); document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active')); const navEl = document.getElementById('nav-' + tab); if (navEl) navEl.classList.add('active'); const chatRow = document.getElementById('chat-input-row'); if (tab === 'chat') { chatRow.style.display = 'flex'; document.getElementById('page-chat').style.display = 'flex'; } else { chatRow.style.display = 'none'; } // Init charts when switching to those pages if (tab === 'twin') renderTwin(); if (tab === 'habits') { renderHabits(); renderHabitChart(); } if (tab === 'report') renderReport(); if (tab === 'simulation') initSimulation(); }; // ============================================================ // INPUT STATUS // ============================================================ function updateInputStatuses() { const hd = appState.healthData; const sections = ['basic','food','sleep','body','breathing']; sections.forEach(s => { const el = document.getElementById('status-' + s); if (el && hd[s]) { el.className = 'input-card-status status-done'; el.textContent = 'โœ“ DONE'; } }); } // ============================================================ // FORM HELPERS // ============================================================ window.updateRangeLabel = (input, labelId) => { document.getElementById(labelId).textContent = input.value; }; window.toggleWakeCount = () => { const val = document.getElementById('sl-pattern').value; document.getElementById('wake-count-group').style.display = val === 'disturbed' ? 'block' : 'none'; }; window.generateMealFields = () => { const count = parseInt(document.getElementById('f-meals').value); const mealNames = ['๐ŸŒ… Breakfast','โ˜€๏ธ Lunch','๐ŸŒ† Evening Snack','๐ŸŒ™ Dinner','๐ŸŒ™ Late Snack']; const times = ['08:00','13:00','16:00','19:30','21:00']; let html = ''; for (let i = 0; i < count; i++) { html += `
${mealNames[i] || 'Meal ' + (i+1)}
`; } document.getElementById('meal-entries').innerHTML = html; }; window.addActivity = () => { const div = document.createElement('div'); div.className = 'activity-entry'; div.innerHTML = ` `; document.getElementById('activity-list').appendChild(div); }; window.removeActivity = (btn) => btn.parentElement.remove(); // ============================================================ // SAVE FUNCTIONS // ============================================================ async function saveSection(section, data) { appState.healthData[section] = data; try { await setDoc(doc(db, 'healthData', appState.currentUser.username), appState.healthData); } catch(e) { console.warn('Save error:', e); } updateInputStatuses(); showNotification('โœ“ ' + section.charAt(0).toUpperCase() + section.slice(1) + ' data saved!', 'success'); navigateTo('dashboard'); } window.saveBasic = async () => { const age = document.getElementById('b-age').value; const gender = document.getElementById('b-gender').value; const height = document.getElementById('b-height').value; const weight = document.getElementById('b-weight').value; if (!age || !gender || !height || !weight) { showNotification('Please fill all required fields', 'error'); return; } const bmi = (weight / ((height/100)**2)).toFixed(1); await saveSection('basic', { age: parseInt(age), gender, height: parseFloat(height), weight: parseFloat(weight), bmi: parseFloat(bmi), bp: document.getElementById('b-bp').value || '', sugar: document.getElementById('b-sugar').value || '', cholesterol: document.getElementById('b-chol').value || '' }); }; window.saveFood = async () => { const meals = []; document.querySelectorAll('.meal-food').forEach((el, i) => { const time = document.querySelectorAll('.meal-time')[i]; meals.push({ food: el.value, time: time ? time.value : '' }); }); const snacks = []; ['milk','chips','fruits','coffee','sweets','nuts'].forEach(s => { if (document.getElementById('s-'+s)?.checked) snacks.push(s); }); const other = document.getElementById('f-other-snacks').value; if (other) snacks.push(other); await saveSection('food', { mealsPerDay: parseInt(document.getElementById('f-meals').value), meals, water: parseFloat(document.getElementById('f-water').value) || 0, snacks }); }; window.saveSleep = async () => { await saveSection('sleep', { hours: parseFloat(document.getElementById('sl-hours').value) || 0, quality: document.getElementById('sl-quality').value, sleepTime: document.getElementById('sl-time').value, wakeTime: document.getElementById('sl-wake').value, pattern: document.getElementById('sl-pattern').value, wakeCount: parseInt(document.getElementById('sl-wakecnt').value) || 0, nightUrination: parseInt(document.getElementById('sl-urine').value) || 0 }); }; window.saveBody = async () => { const activities = []; document.querySelectorAll('#activity-list .activity-entry').forEach(row => { const name = row.querySelector('.act-name')?.value; const dur = row.querySelector('.act-dur')?.value; if (name) activities.push({ name, duration: dur }); }); await saveSection('body', { energyMorning: parseInt(document.getElementById('bc-morning').value), energyAfternoon: parseInt(document.getElementById('bc-afternoon').value), energyEvening: parseInt(document.getElementById('bc-evening').value), energyNight: parseInt(document.getElementById('bc-night').value), activities }); }; window.saveBreathing = async () => { await saveSection('breathing', { atRest: document.getElementById('br-rest').value, walking: document.getElementById('br-walk').value, running: document.getElementById('br-run').value, nightBreath: document.getElementById('br-night').value, notes: document.getElementById('br-notes').value }); }; // ============================================================ // AI ANALYSIS (GEMINI) // ============================================================ window.runAnalysis = async () => { const hd = appState.healthData; const btn = document.querySelector('.btn-analyze'); const resultEl = document.getElementById('analysis-result'); if (!hd.basic) { showNotification('โš ๏ธ Please enter Basic Details first', 'warning'); return; } btn.textContent = 'โšก Analysing with JARVIS AI...'; btn.disabled = true; resultEl.style.display = 'block'; resultEl.innerHTML = `
JARVIS is analysing your health data...
This may take 10-15 seconds
`; const prompt = buildAnalysisPrompt(hd); try { const response = await fetch(GEMINI_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }] }) }); const data = await response.json(); const text = data.candidates?.[0]?.content?.parts?.[0]?.text || ''; const result = parseAnalysisResult(text, hd); appState.analysisResult = result; // Save to Firebase try { await setDoc(doc(db, 'analysis', appState.currentUser.username), { ...result, timestamp: new Date().toISOString(), userData: hd }); } catch(e) {} renderAnalysisResult(result, resultEl); updateLifestyleCorrection(result); checkEmergency(result); } catch(e) { resultEl.innerHTML = `
โš ๏ธ Analysis error. Using smart offline mode.
${e.message}
`; const fallback = offlineAnalysis(hd); appState.analysisResult = fallback; renderAnalysisResult(fallback, resultEl); updateLifestyleCorrection(fallback); checkEmergency(fallback); } btn.textContent = 'โšก RE-ANALYSE MY HEALTH'; btn.disabled = false; }; function buildAnalysisPrompt(hd) { return `You are JARVIS, an advanced AI health analysis system. Analyze this health data and provide a structured JSON response. HEALTH DATA: - Basic: Age ${hd.basic?.age}, Gender ${hd.basic?.gender}, Height ${hd.basic?.height}cm, Weight ${hd.basic?.weight}kg, BMI ${hd.basic?.bmi}, BP: ${hd.basic?.bp||'unknown'}, Sugar: ${hd.basic?.sugar||'unknown'}mg/dL, Cholesterol: ${hd.basic?.cholesterol||'unknown'} - Sleep: ${hd.sleep?.hours||'unknown'} hours, Quality: ${hd.sleep?.quality||'unknown'}, Pattern: ${hd.sleep?.pattern||'unknown'}, Night urination: ${hd.sleep?.nightUrination||0} times - Food: ${hd.food?.mealsPerDay||'unknown'} meals/day, Water: ${hd.food?.water||'unknown'}L, Snacks: ${hd.food?.snacks?.join(', ')||'unknown'} - Body: Morning energy ${hd.body?.energyMorning||3}/5, Activities: ${hd.body?.activities?.map(a=>a.name+' '+a.duration)?.join(', ')||'none'} - Breathing: Rest: ${hd.breathing?.atRest||'unknown'}, Walking: ${hd.breathing?.walking||'unknown'} Return ONLY this JSON (no markdown, no extra text): { "healthScore": <0-100 integer>, "status": "", "risks": [ {"name": "Disease/Condition Name", "percentage": <0-100>, "level": "", "cause": "Brief explanation"} ], "deficiencies": ["deficiency1", "deficiency2"], "explanation": "Detailed 3-4 sentence explanation of main health concerns and root causes", "foodPlan": ["Specific food recommendation 1", "recommendation 2", "recommendation 3", "recommendation 4"], "exercisePlan": ["Exercise step 1 with duration", "step 2", "step 3"], "habitChanges": ["Habit change 1", "change 2", "change 3"], "weeklyPlan": [ {"days": "Day 1-2", "task": "Specific actionable task", "goal": "Expected benefit"}, {"days": "Day 3-4", "task": "Next step task", "goal": "Expected benefit"}, {"days": "Day 5-7", "task": "Advanced task", "goal": "Expected benefit"}, {"days": "Week 2", "task": "Progression task", "goal": "Expected benefit"} ], "keyInsights": ["Insight 1", "Insight 2", "Insight 3"] }`; } function parseAnalysisResult(text, hd) { try { const clean = text.replace(/```json|```/g, '').trim(); return JSON.parse(clean); } catch(e) { return offlineAnalysis(hd); } } function offlineAnalysis(hd) { const sleep = hd.sleep?.hours || 7; const sugar = hd.basic?.sugar ? parseInt(hd.basic.sugar) : 90; const bmi = hd.basic?.bmi || 22; const water = hd.food?.water || 2; const energy = hd.body?.energyMorning || 3; let score = 75; if (sleep < 6) score -= 15; if (sleep < 5) score -= 10; if (sugar > 140) score -= 15; if (bmi > 30) score -= 10; if (bmi < 18.5) score -= 8; if (water < 1.5) score -= 8; if (energy <= 2) score -= 5; score = Math.max(20, Math.min(100, score)); const risks = []; if (sleep < 6 || sugar > 120) risks.push({ name: 'Diabetes Risk', percentage: sleep < 5 ? 68 : 45, level: sleep < 5 ? 'high' : 'medium', cause: 'Low sleep disrupts insulin regulation' }); if (bmi > 27 || hd.breathing?.walking === 'moderate') risks.push({ name: 'Heart Risk', percentage: bmi > 30 ? 55 : 38, level: bmi > 30 ? 'high' : 'medium', cause: 'BMI and activity levels affect cardiovascular health' }); if (energy <= 2 || sleep < 6) risks.push({ name: 'Stress / Fatigue', percentage: 52, level: 'medium', cause: 'Poor sleep and low energy indicate elevated stress' }); if (water < 1.5) risks.push({ name: 'Dehydration Risk', percentage: 40, level: 'medium', cause: 'Insufficient water intake' }); if (risks.length === 0) risks.push({ name: 'General Health', percentage: 25, level: 'low', cause: 'Maintain current healthy habits' }); return { healthScore: score, status: score >= 75 ? 'Healthy' : score >= 50 ? 'Moderate' : 'At Risk', risks, deficiencies: ['Vitamin D', 'Omega-3', water < 1.5 ? 'Hydration' : 'Iron'].filter(Boolean), explanation: `Based on your data, ${sleep < 6 ? 'insufficient sleep is your primary concern. ' : ''}${bmi > 25 ? 'Your BMI suggests weight management would benefit you. ' : ''}${water < 2 ? 'Increasing water intake will improve overall function. ' : ''}Regular monitoring and lifestyle adjustments are recommended.`, foodPlan: ['Start day with warm lemon water', 'Include green leafy vegetables in lunch', 'Reduce processed sugar and refined carbs', 'Add protein-rich foods to every meal', 'Eat dinner 3 hours before sleep'], exercisePlan: ['Start with 10-min morning walk daily', 'Add 5 mins each week until 30 mins', 'Include stretching for flexibility', '2x/week light strength training'], habitChanges: ['Fix sleep schedule โ€” same time daily', 'Drink water first thing in morning', 'Take 5-min breathing breaks every 2 hours'], weeklyPlan: [ { days: 'Day 1-2', task: 'Walk 10 mins every morning', goal: 'Build exercise habit' }, { days: 'Day 3-4', task: 'Increase walk to 20 mins, reduce sugar', goal: 'Improve cardiovascular health' }, { days: 'Day 5-7', task: 'Walk 30 mins + meditation 10 mins', goal: 'Reduce stress levels' }, { days: 'Week 2', task: 'Add strength exercises + meal planning', goal: 'Build sustainable healthy routine' } ], keyInsights: ['Sleep quality directly affects your energy and metabolism', 'Small consistent changes outperform drastic diets', 'Hydration is the easiest win for immediate health improvement'] }; } function renderAnalysisResult(result, el) { const statusColor = result.status === 'Healthy' ? 'var(--green)' : result.status === 'Moderate' ? 'var(--yellow)' : 'var(--red)'; const statusEmoji = result.status === 'Healthy' ? '๐ŸŸข' : result.status === 'Moderate' ? '๐ŸŸก' : '๐Ÿ”ด'; let risksHTML = result.risks.map(r => `
${r.name} ${r.percentage}%
${r.cause}
`).join(''); let defHTML = result.deficiencies?.map(d => `โš ๏ธ ${d}`).join('') || ''; let planHTML = result.weeklyPlan?.map((p, i) => `
${i+1}

${p.days}

${p.task}

โ†’ ${p.goal}

`).join('') || ''; let foodHTML = result.foodPlan?.map(f => `
๐Ÿฅ—

${f}

`).join('') || ''; el.innerHTML = `
๐Ÿงฌ Health Analysis Complete
${result.healthScore}
HEALTH SCORE
${statusEmoji} ${result.status}
${result.explanation}
โš ๏ธ Disease Risk Predictions
${risksHTML}
${defHTML ? `
๐Ÿงช Possible Deficiencies
${defHTML}
` : ''}
๐Ÿ“… Your Correction Plan
${planHTML}
๐Ÿฅ— Food Recommendations
${foodHTML}
๐Ÿ’ก Key Insights
${result.keyInsights?.map(k => `
๐Ÿ’ก ${k}
`).join('') || ''}
`; // Animate risk bars setTimeout(() => { el.querySelectorAll('.risk-bar-fill').forEach(bar => { bar.style.width = bar.dataset.width; }); }, 100); } // ============================================================ // DIGITAL TWIN // ============================================================ function renderTwin() { const result = appState.analysisResult; const hd = appState.healthData; if (!result && !hd.basic) { document.getElementById('score-number').textContent = '--'; return; } const score = result?.healthScore || estimateScore(hd); const status = result?.status || (score >= 75 ? 'Healthy' : score >= 50 ? 'Moderate' : 'At Risk'); const statusColor = status === 'Healthy' ? 'var(--green)' : status === 'Moderate' ? 'var(--yellow)' : 'var(--red)'; document.getElementById('score-number').textContent = score; document.getElementById('score-number').style.color = statusColor; const arc = document.getElementById('score-arc'); const circumference = 2 * Math.PI * 80; const offset = circumference - (score / 100) * circumference; arc.style.strokeDashoffset = circumference; arc.style.stroke = statusColor; setTimeout(() => { arc.style.strokeDashoffset = offset; }, 200); const statusClass = status === 'Healthy' ? 'status-healthy' : status === 'Moderate' ? 'status-moderate' : 'status-risk'; const statusEmoji = status === 'Healthy' ? '๐ŸŸข' : status === 'Moderate' ? '๐ŸŸก' : '๐Ÿ”ด'; document.getElementById('twin-status-badge').innerHTML = `
${statusEmoji} ${status}
`; // Metrics const bmi = hd.basic?.bmi || '--'; const sleep = hd.sleep?.hours || '--'; const water = hd.food?.water || '--'; const energy = hd.body?.energyMorning ? ['','Very Low','Low','Moderate','High','Very High'][hd.body.energyMorning] : '--'; document.getElementById('twin-metrics').innerHTML = `
${bmi}
kg/mยฒ
BMI
${sleep}h
hours
Sleep
${water}L
litres
Water
${energy}
Energy
`; // Twin trend chart const ctx = document.getElementById('twinChart').getContext('2d'); if (appState.charts.twin) appState.charts.twin.destroy(); const days = ['Mon','Tue','Wed','Thu','Fri','Sat','Today']; const scores = [score-12, score-8, score-5, score-3, score-1, score+2, score].map(v => Math.max(0, Math.min(100, v))); appState.charts.twin = new Chart(ctx, { type: 'line', data: { labels: days, datasets: [{ label: 'Health Score', data: scores, borderColor: statusColor, backgroundColor: statusColor.replace('var(--','').replace(')','') === 'green' ? 'rgba(0,255,136,0.1)' : 'rgba(0,212,255,0.1)', fill: true, tension: 0.4, pointBackgroundColor: statusColor, pointRadius: 4 }] }, options: { responsive: true, plugins: { legend: { display: false } }, scales: { x: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#8899aa', font: { size: 11 } } }, y: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#8899aa', font: { size: 11 } }, min: 0, max: 100 } } } }); // Risks if (result?.risks?.length) { document.getElementById('twin-risk-card').style.display = 'block'; document.getElementById('twin-risks').innerHTML = result.risks.map(r => `
${r.name} ${r.percentage}%
`).join(''); } } function estimateScore(hd) { let s = 70; if (hd.sleep?.hours < 6) s -= 10; if (hd.food?.water < 1.5) s -= 5; if (hd.basic?.bmi > 30) s -= 10; return Math.max(20, s); } // ============================================================ // LIFESTYLE CORRECTION // ============================================================ function updateLifestyleCorrection(result) { const el = document.getElementById('lifestyle-content'); if (!result) return; const planHTML = result.weeklyPlan?.map((p, i) => `
${i+1}

${p.days}

${p.task}

โ†’ ${p.goal}

`).join('') || ''; const exerciseHTML = result.exercisePlan?.map((e, i) => `
๐Ÿ’ช

${e}

`).join('') || ''; const habitHTML = result.habitChanges?.map(h => `
๐Ÿ”„ ${h}
`).join('') || ''; el.innerHTML = `
๐Ÿ“… Step-by-Step Plan
${planHTML}
๐Ÿ’ช Exercise Progression
${exerciseHTML}
๐Ÿ”„ Habit Changes
${habitHTML}
`; } // ============================================================ // SIMULATION // ============================================================ let simChart = null; function initSimulation() { updateSim(); } window.updateSim = () => { const sleep = parseFloat(document.getElementById('sim-sleep').value); const exercise = parseInt(document.getElementById('sim-exercise').value); const water = parseFloat(document.getElementById('sim-water').value); const sugar = parseInt(document.getElementById('sim-sugar').value); const stress = parseInt(document.getElementById('sim-stress').value); const sugarLabels = ['','Very Low','Low','Moderate','High','Very High']; const stressLabels = ['','Very Low','Low','Moderate','High','Very High']; document.getElementById('sim-sleep-val').textContent = sleep; document.getElementById('sim-exercise-val').textContent = exercise; document.getElementById('sim-water-val').textContent = water; document.getElementById('sim-sugar-val').textContent = sugarLabels[sugar]; document.getElementById('sim-stress-val').textContent = stressLabels[stress]; // Calculate simulated risks let diabetesBase = 50; let heartBase = 45; let stressBase = 55; diabetesBase -= (sleep - 5) * 4; diabetesBase -= (exercise / 10) * 3; diabetesBase -= (water - 1) * 5; diabetesBase += (sugar - 3) * 6; diabetesBase += (stress - 3) * 3; heartBase -= (sleep - 5) * 3; heartBase -= (exercise / 10) * 4; heartBase += (stress - 3) * 5; stressBase -= (sleep - 5) * 5; stressBase -= (exercise / 15) * 4; stressBase += (stress - 3) * 8; diabetesBase = Math.max(5, Math.min(95, diabetesBase)); heartBase = Math.max(5, Math.min(95, heartBase)); stressBase = Math.max(5, Math.min(95, stressBase)); const healthScore = Math.max(20, Math.min(100, 100 - (diabetesBase + heartBase + stressBase) / 4)); const current = appState.analysisResult; const prevDiabetes = current?.risks?.find(r => r.name.includes('Diabet'))?.percentage || 50; const prevHeart = current?.risks?.find(r => r.name.includes('Heart'))?.percentage || 45; const prevStress = current?.risks?.find(r => r.name.includes('Stress'))?.percentage || 55; document.getElementById('sim-results').innerHTML = `
Current
${prevDiabetes}%
Diabetes
โ†’
Projected
${Math.round(diabetesBase)}%
Diabetes
Current
${prevHeart}%
Heart Risk
โ†’
Projected
${Math.round(heartBase)}%
Heart Risk
Current
${Math.round(healthScore - 10)}%
Health Score
โ†’
Projected
${Math.round(healthScore)}%
Health Score
`; const ctx = document.getElementById('simChart').getContext('2d'); if (simChart) simChart.destroy(); simChart = new Chart(ctx, { type: 'bar', data: { labels: ['Diabetes Risk', 'Heart Risk', 'Stress Risk', 'Health Score'], datasets: [ { label: 'Current', data: [prevDiabetes, prevHeart, prevStress, 100 - healthScore + 10], backgroundColor: 'rgba(255,71,87,0.5)', borderColor: 'rgba(255,71,87,0.8)', borderWidth: 1 }, { label: 'Projected', data: [diabetesBase, heartBase, stressBase, 100 - healthScore].map(v => Math.round(v)), backgroundColor: 'rgba(0,255,136,0.4)', borderColor: 'rgba(0,255,136,0.8)', borderWidth: 1 } ] }, options: { responsive: true, plugins: { legend: { labels: { color: '#8899aa', font: { size: 11 } } } }, scales: { x: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#8899aa', font: { size: 10 } } }, y: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#8899aa', font: { size: 10 } }, min: 0, max: 100 } } } }); appState.charts.sim = simChart; }; // ============================================================ // HABIT TRACKER // ============================================================ function renderHabits() { const habits = appState.habitData.habits; const streak = appState.habitData.streak; document.getElementById('streak-count').textContent = streak; const completedCount = habits.filter(h => h.done).length; document.getElementById('habit-completed').textContent = completedCount; document.getElementById('habit-total').textContent = habits.length; if (streak >= 7) document.getElementById('streak-msg').textContent = '๐Ÿ”ฅ Amazing! ' + streak + '-day streak!'; else if (streak >= 3) document.getElementById('streak-msg').textContent = '๐Ÿ’ช Keep it up! ' + streak + ' days strong'; else if (streak === 0) document.getElementById('streak-msg').textContent = 'Start today to build your streak!'; const list = document.getElementById('habit-list'); list.innerHTML = habits.map(h => `
${h.done ? 'โœ“' : ''}
${h.name}
${h.desc}
${h.done ? 'Done! โœ“' : ''}
`).join(''); } window.toggleHabit = (id) => { const habit = appState.habitData.habits.find(h => h.id === id); if (!habit) return; habit.done = !habit.done; const allDone = appState.habitData.habits.every(h => h.done); if (allDone) { appState.habitData.streak++; const streakData = { streak: appState.habitData.streak }; localStorage.setItem('jarvis_streak_' + appState.currentUser.username, JSON.stringify(streakData)); showNotification('๐Ÿ”ฅ All habits done! +1 streak!', 'success'); } localStorage.setItem('jarvis_habits_' + appState.currentUser.username, JSON.stringify({ date: new Date().toDateString(), habits: appState.habitData.habits })); renderHabits(); }; function renderHabitChart() { const ctx = document.getElementById('habitChart').getContext('2d'); if (appState.charts.habit) appState.charts.habit.destroy(); const habits = appState.habitData.habits; const done = habits.filter(h => h.done).length; const remaining = habits.length - done; appState.charts.habit = new Chart(ctx, { type: 'doughnut', data: { labels: ['Completed', 'Remaining'], datasets: [{ data: [done, remaining], backgroundColor: ['rgba(0,255,136,0.7)', 'rgba(255,255,255,0.1)'], borderColor: ['rgba(0,255,136,1)', 'rgba(255,255,255,0.2)'], borderWidth: 1 }] }, options: { responsive: true, cutout: '70%', plugins: { legend: { labels: { color: '#8899aa', font: { size: 12 } } } } } }); } // ============================================================ // AI CHATBOT // ============================================================ window.sendChat = async () => { const input = document.getElementById('chat-input'); const msg = input.value.trim(); if (!msg) return; input.value = ''; addChatBubble(msg, 'user'); const typingEl = document.createElement('div'); typingEl.className = 'chat-typing'; typingEl.innerHTML = '
'; document.getElementById('chat-messages').appendChild(typingEl); scrollChat(); const hd = appState.healthData; const systemContext = `You are JARVIS, an advanced AI health assistant. Be concise, helpful, and personalized. User health data: Age ${hd.basic?.age||'unknown'}, BMI ${hd.basic?.bmi||'unknown'}, Sleep ${hd.sleep?.hours||'unknown'}h (${hd.sleep?.quality||'unknown'} quality), Water ${hd.food?.water||'unknown'}L/day, Morning energy ${hd.body?.energyMorning||'unknown'}/5, Breathing at rest: ${hd.breathing?.atRest||'normal'}. Analysis result: Health score ${appState.analysisResult?.healthScore||'not yet analyzed'}, Status: ${appState.analysisResult?.status||'unknown'}. Answer the user's health question in 2-4 sentences. Be personalized and actionable.`; try { const response = await fetch(GEMINI_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: systemContext + '\n\nUser question: ' + msg }] }] }) }); const data = await response.json(); const reply = data.candidates?.[0]?.content?.parts?.[0]?.text || 'I apologize, I could not process that. Please try again.'; typingEl.remove(); addChatBubble(reply, 'jarvis'); } catch(e) { typingEl.remove(); addChatBubble('I\'m having trouble connecting right now. Please check your internet connection and try again.', 'jarvis'); } }; function addChatBubble(text, type) { const div = document.createElement('div'); div.className = `chat-bubble chat-${type}`; if (type === 'jarvis') { div.innerHTML = `
โšก JARVIS
${text}`; } else { div.textContent = text; } document.getElementById('chat-messages').appendChild(div); scrollChat(); } function scrollChat() { const msgs = document.getElementById('chat-messages'); msgs.scrollTop = msgs.scrollHeight; } // ============================================================ // WEEKLY REPORT // ============================================================ function renderReport() { const ctx = document.getElementById('reportChart').getContext('2d'); if (appState.charts.report) appState.charts.report.destroy(); const score = appState.analysisResult?.healthScore || 70; const days = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']; const scores = days.map((_, i) => Math.max(30, score - 15 + (i * 2.5) + (Math.random() * 4 - 2))); appState.charts.report = new Chart(ctx, { type: 'line', data: { labels: days, datasets: [ { label: 'Health Score', data: scores.map(v => Math.round(v)), borderColor: 'rgba(0,212,255,0.8)', backgroundColor: 'rgba(0,212,255,0.1)', fill: true, tension: 0.4, pointRadius: 4, pointBackgroundColor: 'rgba(0,212,255,1)' } ] }, options: { responsive: true, plugins: { legend: { labels: { color: '#8899aa', font: { size: 11 } } } }, scales: { x: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#8899aa', font: { size: 11 } } }, y: { grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#8899aa', font: { size: 11 } }, min: 0, max: 100 } } } }); const insights = document.getElementById('report-insights'); const result = appState.analysisResult; const insightList = result?.keyInsights || ['Log daily habits for better tracking', 'Stay consistent with your correction plan', 'Keep hydration levels optimal']; insights.innerHTML = insightList.map(i => `
๐Ÿ“Œ ${i}
`).join(''); } window.switchPeriod = (btn, days) => { document.querySelectorAll('.period-btn').forEach(b => b.classList.remove('active')); btn.classList.add('active'); renderReport(); }; // ============================================================ // SMART ALERTS // ============================================================ function renderSmartAlerts() { const hd = appState.healthData; const el = document.getElementById('smart-alerts'); let alerts = []; if (hd.sleep?.hours && hd.sleep.hours < 5) { alerts.push({ type: 'warning', msg: 'โš ๏ธ Poor sleep pattern detected โ€” less than 5 hours' }); } if (hd.sleep?.pattern === 'disturbed' && hd.sleep?.wakeCount > 3) { alerts.push({ type: 'warning', msg: 'โš ๏ธ Highly disturbed sleep detected โ€” consider sleep hygiene' }); } if (hd.food?.water && hd.food.water < 1.5) { alerts.push({ type: 'warning', msg: '๐Ÿ’ง Low water intake detected โ€” increase hydration' }); } if (hd.breathing?.walking === 'extreme') { alerts.push({ type: 'danger', msg: '๐Ÿซ Severe breathing difficulty while walking โ€” consult doctor' }); } if (hd.body?.energyMorning <= 1) { alerts.push({ type: 'warning', msg: 'โšก Critically low energy levels โ€” possible deficiency' }); } el.innerHTML = alerts.map(a => `
${a.msg}
`).join(''); } function checkEmergency(result) { const criticals = result.risks?.filter(r => r.percentage > 80); if (criticals?.length) { const names = criticals.map(r => r.name).join(', '); document.getElementById('emergency-msg').textContent = `High risk detected for: ${names}. Immediate medical consultation is strongly recommended.`; document.getElementById('emergency-modal').style.display = 'flex'; } } window.closeEmergency = () => { document.getElementById('emergency-modal').style.display = 'none'; }; // ============================================================ // SETTINGS // ============================================================ function loadSettingsForm() {} window.saveSettings = async () => { const user = appState.currentUser; const updates = { name: document.getElementById('set-name').value, phone: document.getElementById('set-phone').value, password: user.password }; try { await setDoc(doc(db, 'users', user.username), { ...user, ...updates }); appState.currentUser = { ...user, ...updates }; document.getElementById('header-greeting').textContent = 'Hi, ' + updates.name.split(' ')[0]; document.getElementById('header-avatar').textContent = updates.name[0].toUpperCase(); showNotification('โœ“ Profile saved successfully', 'success'); } catch(e) { showNotification('โš ๏ธ Save error: ' + e.message, 'error'); } }; // ============================================================ // UTILITIES // ============================================================ function showNotification(msg, type = 'success') { const n = document.createElement('div'); n.style.cssText = `position:fixed;top:80px;left:50%;transform:translateX(-50%);z-index:999; padding:12px 24px;border-radius:12px;font-size:14px;font-weight:600; background:${type==='success'?'rgba(0,255,136,0.15)':type==='error'?'rgba(255,71,87,0.15)':'rgba(255,215,0,0.15)'}; border:1px solid ${type==='success'?'rgba(0,255,136,0.3)':type==='error'?'rgba(255,71,87,0.3)':'rgba(255,215,0,0.3)'}; color:${type==='success'?'var(--green)':type==='error'?'var(--red)':'var(--yellow)'}; backdrop-filter:blur(20px);animation:slideDown 0.3s ease-out;max-width:90vw;text-align:center;`; n.textContent = msg; document.body.appendChild(n); setTimeout(() => n.style.opacity = '0', 2500); setTimeout(() => n.remove(), 3000); } window.toggleSwitch = (id) => { const input = document.getElementById(id); const span = document.getElementById(id + '-span'); input.checked = !input.checked; span.style.background = input.checked ? 'rgba(0,212,255,0.3)' : 'rgba(255,255,255,0.1)'; span.style.borderColor = input.checked ? 'var(--cyan)' : 'var(--border)'; };