import React, { useEffect, useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { StorageService } from '../services/storageService'; import { UserProfile, Task, TaskStatus, Priority, FTLMission } from '../types'; import { useLanguage } from '../contexts/LanguageContext'; import { ArrowRight, CheckSquare, Loader2, Calendar as CalendarIcon, Zap, Coins, Library as LibraryIcon, MessageCircle, MapPin, Activity, Gamepad2, CheckCircle2, Camera, ListTodo, Siren, Utensils, Bot, Shield, ChevronRight } from 'lucide-react'; import confetti from 'canvas-confetti'; // --- COMPONENTS --- const XPToast = ({ amount, onComplete }: { amount: number, onComplete: () => void }) => { useEffect(() => { const timer = setTimeout(onComplete, 2000); return () => clearTimeout(timer); }, [onComplete]); return (
+{amount} XP
); }; const CountUp = ({ end, duration = 1500 }: { end: number, duration?: number }) => { const [count, setCount] = useState(0); useEffect(() => { let startTime: number; let animationFrame: number; const update = (currentTime: number) => { if (!startTime) startTime = currentTime; const progress = Math.min((currentTime - startTime) / duration, 1); const ease = 1 - Math.pow(1 - progress, 4); setCount(Math.floor(ease * end)); if (progress < 1) animationFrame = requestAnimationFrame(update); }; animationFrame = requestAnimationFrame(update); return () => cancelAnimationFrame(animationFrame); }, [end, duration]); return <>{count}; }; const getFrameStyle = (id?: string) => { if (!id || id === 'none') return 'ring-2 ring-white/30'; if (id === 'unicorn') return 'ring-2 ring-pink-400 shadow-[0_0_15px_#f472b6]'; if (id === 'royal') return 'ring-2 ring-yellow-500 shadow-[0_0_20px_#eab308]'; if (id === 'nature') return 'ring-2 ring-green-500 border-green-300'; if (id === 'dark') return 'ring-2 ring-gray-800 shadow-[0_0_15px_#000]'; return 'ring-2 ring-white/30'; }; // --- DATA --- const SLOGANS = [ { en: "Small Country, Big Thinking", ne: "सानो देश, ठूलो सोच" }, { en: "Heritage is Identity", ne: "सम्पदा नै पहिचान हो" }, { en: "Unity in Diversity", ne: "विविधतामा एकता" }, { en: "Digital Nepal, Smart Future", ne: "डिजिटल नेपाल, स्मार्ट भविष्य" }, ]; // --- RENDERERS --- interface TaskItemProps { task: Task; onComplete: (task: Task) => void | Promise; } const TaskItem: React.FC = ({ task, onComplete }) => (

{task.subject}

{task.title}

); const Dashboard: React.FC = () => { const { t, language } = useLanguage(); const navigate = useNavigate(); // Data State const [profile, setProfile] = useState(null); const [tasks, setTasks] = useState([]); const [missions, setMissions] = useState([]); const [loading, setLoading] = useState(true); const [currentDate, setCurrentDate] = useState(new Date()); // UI State const [xpGain, setXpGain] = useState(null); const [sloganIndex, setSloganIndex] = useState(0); useEffect(() => { const timer = setInterval(() => setCurrentDate(new Date()), 60000); const sloganTimer = setInterval(() => setSloganIndex(prev => (prev + 1) % SLOGANS.length), 4000); const fetchData = async () => { setLoading(true); const [p, t_data, m] = await Promise.all([ StorageService.getProfile(), StorageService.getTasks(), StorageService.getMissions() ]); setProfile(p); setTasks(t_data); setMissions(m); setLoading(false); }; fetchData(); const handleUpdate = async () => { const [p, t_data, m] = await Promise.all([ StorageService.getProfile(), StorageService.getTasks(), StorageService.getMissions() ]); if (p && profile && p.xp > profile.xp) { setXpGain(p.xp - profile.xp); } setProfile(p); setTasks(t_data); setMissions(m); }; window.addEventListener('rudraksha-profile-update', handleUpdate); return () => { clearInterval(timer); clearInterval(sloganTimer); window.removeEventListener('rudraksha-profile-update', handleUpdate); }; }, [profile?.xp]); const handleQuickCompleteTask = async (task: Task) => { const updatedStatus = TaskStatus.COMPLETED; await StorageService.saveTask({ ...task, status: updatedStatus }); await StorageService.addPoints(10, 50); confetti({ particleCount: 50, spread: 60, origin: { y: 0.8 } }); window.dispatchEvent(new Event('rudraksha-profile-update')); }; if (loading && !profile) return
; const dateString = currentDate.toLocaleDateString(language === 'ne' ? 'ne-NP' : 'en-US', { weekday: 'long', month: 'long', day: 'numeric' }); const currentXP = profile?.xp || 0; const userLevel = Math.floor(currentXP / 500) + 1; const xpProgress = Math.min(100, Math.round(((currentXP - ((userLevel - 1) * 500)) / 500) * 100)); const pendingTasks = tasks.filter(t => t.status !== TaskStatus.COMPLETED).slice(0, 3); const activeFTL = missions.filter(m => m.status === 'active'); const currentSlogan = SLOGANS[sloganIndex]; // Define Sections Logic const SECTIONS = [ { title: 'ACADEMICS', color: 'text-indigo-500', items: [ { to: '/study-buddy', label: 'Rudra AI', icon: Bot, color: 'text-indigo-400', bg: 'bg-indigo-500/10', desc: 'Your Personal AI Tutor' }, { to: '/planner', label: 'Planner', icon: CheckSquare, color: 'text-emerald-400', bg: 'bg-emerald-500/10', desc: `${pendingTasks.length} Pending Tasks` }, { to: '/library', label: 'Library', icon: LibraryIcon, color: 'text-amber-400', bg: 'bg-amber-500/10', desc: 'Curriculum Resources' }, ] }, { title: 'CULTURE & LIFESTYLE', color: 'text-rose-500', items: [ { to: '/culture', label: 'Calendar', icon: CalendarIcon, color: 'text-rose-400', bg: 'bg-rose-500/10', desc: dateString }, { to: '/map', label: 'Heritage Map', icon: MapPin, color: 'text-red-400', bg: 'bg-red-500/10', desc: 'Explore Nepal' }, { to: '/recipes', label: 'Kitchen', icon: Utensils, color: 'text-orange-400', bg: 'bg-orange-500/10', desc: 'Traditional Recipes' }, ] }, { title: 'COMMUNITY & UTILITIES', color: 'text-blue-500', items: [ { to: '/community-chat', label: 'Community', icon: MessageCircle, color: 'text-blue-400', bg: 'bg-blue-500/10', desc: 'Global Chat' }, { to: '/safety', label: 'Safety', icon: Siren, color: 'text-red-500', bg: 'bg-red-500/10', desc: activeFTL.length > 0 ? `${activeFTL.length} Active Alerts` : 'System Secure' }, { to: '/health', label: 'Wellness', icon: Activity, color: 'text-teal-400', bg: 'bg-teal-500/10', desc: 'Health Tracker' }, { to: '/arcade', label: 'Arcade', icon: Gamepad2, color: 'text-fuchsia-400', bg: 'bg-fuchsia-500/10', desc: 'Play & Earn' }, { to: '/rewards', label: 'Karma Bazaar', icon: Coins, color: 'text-yellow-400', bg: 'bg-yellow-500/10', desc: 'Redeem Points' }, ] } ]; return (
{/* 1. HERO SECTION */}
navigate('/profile', { state: { action: 'avatar' } })} className="relative cursor-pointer group/avatar">
{dateString} ID Verified

Namaste, {profile?.name.split(' ')[0]}

{language === 'ne' ? currentSlogan.ne : currentSlogan.en}

Level

{userLevel}

Karma

Progress to Level {userLevel + 1} {currentXP} / {userLevel * 500} XP
{xpGain && setXpGain(null)} />}
{/* 2. DYNAMIC SECTIONS GRID */} {SECTIONS.map((section, idx) => (

{section.title}

{section.items.map((item, i) => (

{item.label}

{item.desc}

))}
))} {/* 3. WIDGETS ROW */}
{/* Priority Tasks */}

Priority Queue

View All
{pendingTasks.length > 0 ? pendingTasks.map(t => ) : (
All Clear
)}
{/* Active Alerts */}

FTL Network

View Map
{activeFTL.length > 0 ? activeFTL.slice(0, 3).map(m => (

{m.type} ALERT

{m.location}

)) : (
Sector Secure
)}
); }; export default Dashboard;