import React, { useState, useEffect, useRef, useCallback } from 'react'; import { StorageService } from '../services/storageService'; import { AirQualityService } from '../services/airQualityService'; import { interpretDream, createHealthAssistant } from '../services/geminiService'; import { HealthLog, AQIData, WeatherData, ChatMessage } from '../types'; import { Heart, Droplets, Smile, Moon, Plus, Minus, Loader2, Wind, CloudFog, MapPin, Sun, CloudRain, CloudLightning, Activity, Leaf, Thermometer, Umbrella, Eye, Dumbbell, Flower2, Sprout, Timer, Apple, Users, ShieldCheck, HeartPulse, Play, Waves, Sparkles, Brain, Zap, BatteryMedium, CloudMoon, BookOpen, Quote, ChevronRight, X, Send, BarChart, MessageSquare, Info, GripVertical, Pause, RotateCcw, CheckCircle, Languages, Mic } from 'lucide-react'; import { useLanguage } from '../contexts/LanguageContext'; import confetti from 'canvas-confetti'; import { Button } from '../components/ui/Button'; import { BarChart as RechartsBarChart, Bar, ResponsiveContainer, XAxis, Tooltip, Cell, YAxis } from 'recharts'; const QUOTES = [ { en: "The earth does not belong to us: we belong to the earth.", ne: "पृथ्वी हाम्रो होइन, हामी पृथ्वीका हौं।" }, { en: "A healthy body houses a healthy mind.", ne: "स्वस्थ शरीरमा नै स्वस्थ मनको बास हुन्छ।" }, { en: "Look deep into nature, and then you will understand everything better.", ne: "प्रकृतिमा गहिरिएर हेर्नुहोस्, अनि सबै कुरा राम्ररी बुझ्नुहुनेछ।" }, ]; const YOGA_POSES = [ { id: 'yoga_1', name: 'Surya Namaskar', neName: 'सूर्य नमस्कार', icon: Sun, benefits: 'Full body workout, improves blood circulation.', neBenefits: 'पूरा शरीरको व्यायाम, रक्तसञ्चारमा सुधार।', steps: '12 steps combining 7 different asanas.', neSteps: '७ विभिन्न आसनहरू मिलाएर १२ चरणहरू।', detailedSteps: [ "Stand straight, palms folded in prayer pose. Breathe in.", "Raise arms overhead, arch back slightly. Breathe out.", "Bend forward, touch your feet. Keep knees straight.", "Step right leg back, look up (Equestrian Pose).", "Step left leg back into Plank pose. Keep body straight.", "Lower knees, chest, and chin to floor (Ashtanga Namaskar).", "Slide forward into Cobra pose. Look up.", "Lift hips into Inverted V (Mountain pose).", "Step right foot forward between hands.", "Step left foot forward, bend down.", "Raise arms overhead, stretch back.", "Return to standing prayer pose." ], detailedStepsNe: [ "सीधा उभिनुहोस्, हातहरू जोडेर प्रार्थना मुद्रामा। सास लिनुहोस्।", "हातहरू टाउको माथि उठाउनुहोस्, अलिकति पछाडि ढल्किनुहोस्। सास छोड्नुहोस्।", "अगाडि झुक्नुहोस्, खुट्टा छुनुहोस्। घुँडाहरू सीधा राख्नुहोस्।", "दायाँ खुट्टा पछाडि सार्नुहोस्, माथि हेर्नुहोस् (अश्व सञ्चालन आसन)।", "बायाँ खुट्टा पछाडि सार्नुहोस् र प्ल्याङ्क पोजमा जानुहोस्। शरीर सीधा राख्नुहोस्।", "घुँडा, छाती र चिउँडो भुइँमा राख्नुहोस् (अष्टाङ्ग नमस्कार)।", "अगाडि सर्दै कोब्रा पोज (भुजङ्गासन) मा जानुहोस्। माथि हेर्नुहोस्।", "कम्मर माथि उठाउनुहोस् र उल्टो V आकार (पर्वतासन) बनाउनुहोस्।", "दायाँ खुट्टा हातहरूको बीचमा अगाडि ल्याउनुहोस्।", "बायाँ खुट्टा अगाडि ल्याउनुहोस्, तल झुक्नुहोस्।", "हातहरू माथि उठाउनुहोस्, पछाडि तन्किनुहोस्।", "प्रार्थना मुद्रामा फर्कनुहोस्।" ] }, { id: 'yoga_2', name: 'Pranayama', neName: 'प्राणायाम', icon: Wind, benefits: 'Reduces stress, improves lung capacity.', neBenefits: 'तनाव कम गर्छ, फोक्सोको क्षमता बढाउँछ।', steps: 'Breath awareness and controlled breathing.', neSteps: 'श्वासप्रश्वासको जागरूकता र नियन्त्रित श्वास।', detailedSteps: [ "Sit in a comfortable cross-legged position.", "Close your eyes and relax your shoulders.", "Inhale deeply through your nose for 4 seconds.", "Hold your breath for 4 seconds.", "Exhale slowly through your nose for 6 seconds.", "Repeat this cycle for 5 minutes." ], detailedStepsNe: [ "आरामदायी पलेँटी कसरे बस्नुहोस्।", "आँखा बन्द गर्नुहोस् र काँधहरूलाई खुकुलो छोड्नुहोस्।", "नाकबाट ४ सेकेन्डसम्म गहिरो सास लिनुहोस्।", "४ सेकेन्डसम्म सास रोक्नुहोस्।", "बिस्तारै ६ सेकेन्डसम्म नाकबाट सास छोड्नुहोस्।", "यो प्रक्रिया ५ मिनेटसम्म दोहोर्याउनुहोस्।" ] }, { id: 'yoga_3', name: 'Vrikshasana', neName: 'वृक्षासन', icon: Sprout, benefits: 'Improves balance and leg strength.', neBenefits: 'सन्तुलन र खुट्टाको बल सुधार गर्छ।', steps: 'Stand on one leg, foot on inner thigh.', neSteps: 'एउटा खुट्टामा उभिनुहोस्, अर्को पाइतला तिघ्रामा राख्नुहोस्।', detailedSteps: [ "Stand tall with feet together.", "Shift weight to left leg.", "Place right foot on inner left thigh.", "Bring hands to prayer position at chest.", "Raise hands above head, keep elbows straight.", "Focus on a point in front of you. Hold.", "Slowly lower hands and leg. Repeat other side." ], detailedStepsNe: [ "खुट्टाहरू जोडेर सीधा उभिनुहोस्।", "तौल बायाँ खुट्टामा सार्नुहोस्।", "दायाँ खुट्टाको पाइतला बायाँ तिघ्राको भित्री भागमा राख्नुहोस्।", "हातहरू छातीको अगाडि नमस्कार मुद्रामा ल्याउनुहोस्।", "हातहरू टाउको माथि उठाउनुहोस्, कुहिनो सीधा राख्नुहोस्।", "अगाडि एउटा बिन्दुमा ध्यान केन्द्रित गर्नुहोस्। अडिनुहोस्।", "बिस्तारै हात र खुट्टा तल झार्नुहोस्। अर्को तर्फ दोहोर्याउनुहोस्।" ] } ]; const AYURVEDA_TIPS = [ { title: 'Dinacharya (Daily Routine)', neTitle: 'दिनचर्या', icon: Timer, tip: 'Wake up before sunrise (Brahma Muhurta) to synchronize with nature.', neTip: 'प्रकृतिसँग तालमेल मिलाउन सूर्योदयभन्दा अगाडि (ब्रह्म मुहूर्त) उठ्नुहोस्।' }, { title: 'Warm Water Secret', neTitle: 'तातो पानीको रहस्य', icon: Droplets, tip: 'Sip warm water throughout the day to boost metabolism and digestion.', neTip: 'मेटाबोलिज्म र पाचन बढाउन दिनभरि तातो पानी पिउनुहोस्।' }, { title: 'Herbal Power', neTitle: 'जडीबुटी शक्ति', icon: Leaf, tip: 'Chew a few Tulsi leaves daily to strengthen your immune system.', neTip: 'रोग प्रतिरोधात्मक क्षमता बलियो बनाउन दिनहुँ तुलसीका पातहरू चपाउनुहोस्।' } ]; const LONGEVITY_PILLARS = [ { en: "Active Lifestyle", ne: "सक्रिय जीवनशैली", icon: Dumbbell, desc: "Walk at least 30 mins daily in nature.", neDesc: "प्रकृतिमा दैनिक कम्तीमा ३० मिनेट हिड्नुहोस्।" }, { en: "Sattvic Diet", ne: "सात्त्विक आहार", icon: Apple, desc: "Eat fresh, seasonal, and plant-based foods.", neDesc: "ताजा, मौसमी र वनस्पतिमा आधारित खाना खानुहोस्।" }, { en: "Social Connection", ne: "सामाजिक सम्बन्ध", icon: Users, desc: "Talk to loved ones daily to reduce cortisol.", neDesc: "तनाव कम गर्न दैनिक प्रियजनहरूसँग कुरा गर्नुहोस्।" }, { en: "Consistent Sleep", ne: "नियमित निद्रा", icon: Moon, desc: "Rest is the best medicine. Sleep 7-8 hours.", neDesc: "आराम नै उत्तम औषधि हो। ७-८ घण्टा सुत्नुहोस्।" } ]; // --- YOGA SESSION OVERLAY COMPONENT --- const YogaSession = ({ pose, onClose }: { pose: any, onClose: () => void }) => { const { t } = useLanguage(); const [stepIndex, setStepIndex] = useState(0); const [timer, setTimer] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const [isFinished, setIsFinished] = useState(false); const [isSpeaking, setIsSpeaking] = useState(false); const [sessionLang, setSessionLang] = useState<'en' | 'ne' | null>(null); const [awardMessage, setAwardMessage] = useState(''); const timerRef = useRef(null); const steps = sessionLang === 'ne' ? (pose.detailedStepsNe || pose.detailedSteps) : pose.detailedSteps; // Enhanced Voice Feedback Function const speakStep = useCallback((text: string) => { if (!window.speechSynthesis) return; window.speechSynthesis.cancel(); const utterance = new SpeechSynthesisUtterance(text); utterance.rate = 0.9; utterance.pitch = 1; utterance.volume = 1; // Find best voice for Nepali if (sessionLang === 'ne') { const voices = window.speechSynthesis.getVoices(); // Try Nepali specific, then Hindi (often works for Devanagari), then generic const neVoice = voices.find(v => v.lang.includes('ne')) || voices.find(v => v.lang.includes('hi')) || voices.find(v => v.lang.includes('IN')); if (neVoice) utterance.voice = neVoice; utterance.lang = 'hi-IN'; // Fallback hint } else { utterance.lang = 'en-US'; } utterance.onstart = () => setIsSpeaking(true); utterance.onend = () => setIsSpeaking(false); window.speechSynthesis.speak(utterance); }, [sessionLang]); // Ensure voices are loaded (Chrome quirk) useEffect(() => { window.speechSynthesis.getVoices(); }, []); // Handle initial start useEffect(() => { if (sessionLang && !isFinished && !isPlaying) { setIsPlaying(true); setTimer(0); // Intro Voice Instruction const intro = sessionLang === 'ne' ? `${pose.neName} सुरु हुँदैछ। तयार हुनुहोस्।` : `Starting ${pose.name}. Get ready.`; speakStep(intro); // Wait for intro to finish approx before starting steps logic setTimeout(() => { const stepOne = sessionLang === 'ne' ? `चरण एक। ${steps[0]}` : `Step 1. ${steps[0]}`; speakStep(stepOne); }, 3000); } }, [sessionLang, pose, speakStep, steps]); // Voice Control Listener useEffect(() => { const handleVoiceControl = (e: CustomEvent) => { if (!sessionLang || isFinished) return; const { action } = e.detail; if (action === 'next') { if (stepIndex < steps.length - 1) { setStepIndex(prev => prev + 1); } else { finishSession(); } } else if (action === 'prev') { if (stepIndex > 0) { setStepIndex(prev => prev - 1); } } else if (action === 'repeat') { const txt = sessionLang === 'ne' ? `फेरि भन्दै। ${steps[stepIndex]}` : `Repeating. ${steps[stepIndex]}`; speakStep(txt); } else if (action === 'exit') { onClose(); } }; window.addEventListener('rudraksha-yoga-control' as any, handleVoiceControl); return () => window.removeEventListener('rudraksha-yoga-control' as any, handleVoiceControl); }, [sessionLang, stepIndex, steps, isFinished, onClose, speakStep]); // Effect for step changes (Trigger speech when stepIndex updates) useEffect(() => { if (isPlaying && !isFinished && sessionLang) { // Don't speak immediately on mount (handled by intro effect), only on change if (timer > 0 || stepIndex > 0) { const prefix = sessionLang === 'ne' ? 'चरण' : 'Step'; const num = sessionLang === 'ne' ? String(stepIndex + 1).replace(/[0-9]/g, d => "०१२३४५६७८९"[Number(d)]) : (stepIndex + 1); speakStep(`${prefix} ${num}. ${steps[stepIndex]}`); } } }, [stepIndex, sessionLang]); // Timer Logic useEffect(() => { if (isPlaying && !isFinished) { timerRef.current = setInterval(() => { setTimer(prev => prev + 1); }, 1000); } else { clearInterval(timerRef.current); } return () => clearInterval(timerRef.current); }, [isPlaying, isFinished]); // Cleanup speech on unmount useEffect(() => { return () => { window.speechSynthesis.cancel(); }; }, []); const nextStep = () => { if (stepIndex < steps.length - 1) { setStepIndex(prev => prev + 1); } else { finishSession(); } }; const prevStep = () => { if (stepIndex > 0) { setStepIndex(prev => prev - 1); } }; const finishSession = async () => { setIsFinished(true); setIsPlaying(false); const finalText = sessionLang === 'ne' ? "सत्र पूरा भयो। नमस्ते।" : "Session complete. Namaste."; speakStep(finalText); // Awarding Logic via StorageService const result = await StorageService.trackYogaSession(pose.id); setAwardMessage(result.message); if (result.awarded) { confetti({ particleCount: 150, spread: 70, origin: { y: 0.6 }, colors: ['#a855f7', '#6366f1'] }); } }; if (!sessionLang) { return (

Select Instruction Language

); } const formatTimer = (t: number) => { const m = Math.floor(t / 60); const s = t % 60; if (sessionLang === 'ne') { const timeStr = `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; return timeStr.replace(/[0-9]/g, d => "०१२३४५६७८९"[Number(d)]); } return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`; }; return (
{!isFinished ? (

{sessionLang === 'ne' ? pose.neName : pose.name}

{sessionLang === 'ne' ? `चरण ${String(stepIndex + 1).replace(/[0-9]/g, d => "०१२३४५६७८९"[Number(d)])} / ${String(steps.length).replace(/[0-9]/g, d => "०१२३४५६७८९"[Number(d)])}` : `Step ${stepIndex + 1} / ${steps.length}`}

"{steps[stepIndex]}"

{formatTimer(timer)}
{/* Voice Control Hint */}

{sessionLang === 'ne' ? "भन्नुहोस्: अर्को, अघिल्लो, फेरि" : 'Say "Next", "Back", "Repeat"'}

) : (

{sessionLang === 'ne' ? "नमस्ते" : "Namaste"}

{sessionLang === 'ne' ? "सत्र सफलतापूर्वक सम्पन्न भयो।" : "Session Completed Successfully."}

Status
{awardMessage}
)}
); }; const Health: React.FC = () => { const today = new Date().toISOString().split('T')[0]; const { language, t } = useLanguage(); const [activeTab, setActiveTab] = useState<'climate' | 'personal' | 'yog' | 'ancient' | 'dream'>('climate'); const [log, setLog] = useState(null); const [aqiData, setAqiData] = useState(null); const [weatherData, setWeatherData] = useState(null); const [loadingClimate, setLoadingClimate] = useState(false); const [loadingLog, setLoadingLog] = useState(false); const [quote, setQuote] = useState(QUOTES[0]); const [dreamInput, setDreamInput] = useState(''); const [dreamResult, setDreamResult] = useState<{ folklore: { en: string, ne: string }, psychology: { en: string, ne: string }, symbol: string } | null>(null); const [isDreaming, setIsDreaming] = useState(false); // Yoga Interaction State const [isSelectingPose, setIsSelectingPose] = useState(false); const [activeYogaPose, setActiveYogaPose] = useState(null); useEffect(() => { const fetchClimate = async () => { setLoadingClimate(true); try { const [aqi, weather] = await Promise.all([ AirQualityService.getAQI(), AirQualityService.getWeather() ]); setAqiData(aqi); setWeatherData(weather); } catch (e) { console.error("Climate Fetch Error:", e); } finally { setLoadingClimate(false); } }; fetchClimate(); setQuote(QUOTES[Math.floor(Math.random() * QUOTES.length)]); }, []); useEffect(() => { if (activeTab === 'personal' && !log) { const fetchLog = async () => { setLoadingLog(true); try { const data = await StorageService.getHealthLog(today); setLog(data); } finally { setLoadingLog(false); } }; fetchLog(); } }, [activeTab, log, today]); const updateLog = async (newLog: HealthLog) => { setLog(newLog); await StorageService.saveHealthLog(newLog); if (newLog.waterGlasses === 8) { StorageService.addPoints(10); confetti({ particleCount: 150, spread: 70, origin: { y: 0.6 }, colors: ['#3b82f6', '#60a5fa', '#93c5fd'] }); } }; const handleDreamInterpret = async () => { if (!dreamInput.trim()) return; setIsDreaming(true); setDreamResult(null); try { const result = await interpretDream(dreamInput); setDreamResult(result); } catch (e) { console.error(e); } finally { setIsDreaming(false); } }; const getWeatherIcon = (condition: string) => { switch(condition) { case 'Sunny': return ; case 'Rainy': return ; case 'Stormy': return ; case 'Foggy': return ; default: return ; } }; const getWeatherGradient = (condition: string) => { switch(condition) { case 'Sunny': return "from-blue-400 to-blue-200 dark:from-blue-800 dark:to-blue-600"; case 'Rainy': return "from-slate-700 to-slate-500 dark:from-gray-800 dark:to-gray-700"; case 'Foggy': return "from-gray-400 to-gray-200 dark:from-gray-700 dark:to-gray-600"; default: return "from-blue-500 to-cyan-400"; } }; const getMoodEmoji = (mood: string) => { switch(mood) { case 'Happy': return { emoji: '😊', color: 'bg-yellow-100 dark:bg-yellow-900/40 text-yellow-600' }; case 'Neutral': return { emoji: '😐', color: 'bg-gray-100 dark:bg-gray-700 text-gray-500' }; case 'Stressed': return { emoji: '😫', color: 'bg-red-100 dark:bg-red-900/40 text-red-600' }; case 'Tired': return { emoji: '😴', color: 'bg-indigo-100 dark:bg-indigo-900/40 text-indigo-600' }; default: return { emoji: '😐', color: 'bg-gray-100 dark:bg-gray-700 text-gray-500' }; } }; const isWaterOverflowing = log && log.waterGlasses >= 8; const handleStartFlow = () => { setIsSelectingPose(true); }; const handleSelectPose = (pose: any) => { setIsSelectingPose(false); setActiveYogaPose(pose); }; return (
{activeYogaPose && setActiveYogaPose(null)} />}

{t("Wellness Centre", "Wellness Centre")}

{t("Harmonizing ancient wisdom with modern health analytics.", "Harmonizing ancient wisdom with modern health analytics.")}

{[ { id: 'climate', icon: Wind, label: 'Environment', color: 'text-teal-500' }, { id: 'personal', icon: BatteryMedium, label: 'Daily Log', color: 'text-red-500' }, { id: 'yog', icon: Waves, label: 'Yoga Flow', color: 'text-indigo-500' }, { id: 'ancient', icon: Sparkles, label: 'Wisdom', color: 'text-amber-500' }, { id: 'dream', icon: CloudMoon, label: 'Sapana', color: 'text-purple-500' } ].map(tab => ( ))}
{/* CLIMATE VIEW */} {activeTab === 'climate' && (
{loadingClimate ? (

Locating Environment...

) : weatherData && aqiData ? (

{weatherData.location}

{new Date().toDateString()}

{weatherData.temp}°

{t(weatherData.condition, weatherData.condition)}

{getWeatherIcon(weatherData.condition)}
{t("Humidity", "Humidity")} {weatherData.humidity}%
{t("Wind", "Wind")} {weatherData.windSpeed} km/h
{t("Feels Like", "Feels Like")} {weatherData.feelsLike}°

{t("Air Quality Index", "Air Quality Index")}

{aqiData.aqi}

{t(aqiData.status, aqiData.status)}

{t("Dominant Pollutant", "Dominant Pollutant")}

{aqiData.pollutant}

{t("Health Advice", "Health Advice")}

"{aqiData.advice}"

) : (

Weather data unavailable. Please check location permissions.

)}
)} {/* DREAM INTERPRETER VIEW */} {activeTab === 'dream' && (

{t("Sapana Interpreter", "Sapana Interpreter")}

{t("Unlock the hidden messages of your subconscious through the lens of ancient Nepali folklore and modern psychology.", "Unlock the hidden messages of your subconscious through the lens of ancient Nepali folklore and modern psychology.")}