'use client'; import { useState, useEffect, useCallback } from 'react'; import { User } from '@/lib/session'; import { fetchPreferences, fetchUsageData, savePreferencesAsync, saveUsageEntryAsync, shouldShowUsagePrompt, markPromptShown, generateQuitPlan, fetchAchievements, fetchSavingsConfig, saveSavingsConfig, unlockAchievement, checkBadgeEligibility, UserPreferences, UsageEntry, Achievement, SavingsConfig, BADGE_DEFINITIONS, BadgeDefinition, } from '@/lib/storage'; import { UserHeader } from './UserHeader'; import { SetupWizard } from './SetupWizard'; import { UsagePromptDialog } from './UsagePromptDialog'; import { UsageCalendar } from './UsageCalendar'; import { StatsCard } from './StatsCard'; import { QuitPlanCard } from './QuitPlanCard'; import { AchievementsCard } from './AchievementsCard'; import { CelebrationAnimation } from './CelebrationAnimation'; import { HealthTimelineCard } from './HealthTimelineCard'; import { SavingsTrackerCard } from './SavingsTrackerCard'; import { Button } from '@/components/ui/button'; import { PlusCircle } from 'lucide-react'; import { useTheme } from '@/lib/theme-context'; interface DashboardProps { user: User; } export function Dashboard({ user }: DashboardProps) { const [preferences, setPreferences] = useState(null); const [usageData, setUsageData] = useState([]); const [achievements, setAchievements] = useState([]); const [savingsConfig, setSavingsConfig] = useState(null); const [showSetup, setShowSetup] = useState(false); const [showUsagePrompt, setShowUsagePrompt] = useState(false); const [showCelebration, setShowCelebration] = useState(false); const [newBadge, setNewBadge] = useState(null); const [isLoading, setIsLoading] = useState(true); const [refreshKey, setRefreshKey] = useState(0); const { theme } = useTheme(); const loadData = useCallback(async () => { const [prefs, usage, achvs, savings] = await Promise.all([ fetchPreferences(), fetchUsageData(), fetchAchievements(), fetchSavingsConfig(), ]); setPreferences(prefs); setUsageData(usage); setAchievements(achvs); setSavingsConfig(savings); setRefreshKey(prev => prev + 1); return { prefs, usage, achvs }; }, []); const checkAndUnlockAchievements = useCallback(async ( usage: UsageEntry[], prefs: UserPreferences, currentAchievements: Achievement[] ) => { const unlockedIds = new Set(currentAchievements.map(a => `${a.badgeId}-${a.substance}`)); for (const badge of BADGE_DEFINITIONS) { for (const substance of ['nicotine', 'weed'] as const) { const key = `${badge.id}-${substance}`; if (unlockedIds.has(key)) continue; const isEligible = checkBadgeEligibility(badge.id, usage, prefs, substance); if (isEligible) { const result = await unlockAchievement(badge.id, substance); if (result.isNew && result.achievement) { setNewBadge(badge); setShowCelebration(true); setAchievements(prev => [...prev, result.achievement!]); return; // Only show one celebration at a time } } } } }, []); useEffect(() => { const init = async () => { const { prefs, usage, achvs } = await loadData(); if (!prefs.hasCompletedSetup) { setShowSetup(true); } else { // Check for achievements await checkAndUnlockAchievements(usage, prefs, achvs); if (shouldShowUsagePrompt()) { setShowUsagePrompt(true); markPromptShown(); } } setIsLoading(false); }; init(); }, [loadData, checkAndUnlockAchievements]); const handleSetupComplete = async (data: { substance: 'nicotine' | 'weed'; name: string; age: number; religion: 'christian' | 'muslim' | 'jewish' | 'secular' }) => { const today = new Date().toISOString().split('T')[0]; const newPrefs: UserPreferences = { substance: data.substance, trackingStartDate: today, hasCompletedSetup: true, dailyGoal: null, quitPlan: null, userName: data.name, userAge: data.age, religion: data.religion, }; await savePreferencesAsync(newPrefs); setPreferences(newPrefs); setShowSetup(false); setShowUsagePrompt(true); setRefreshKey(prev => prev + 1); }; const handleUsageSubmit = async (count: number, substance: 'nicotine' | 'weed') => { if (!preferences) { setShowUsagePrompt(false); return; } if (count > 0) { const today = new Date().toISOString().split('T')[0]; await saveUsageEntryAsync({ date: today, count, substance, }); } setShowUsagePrompt(false); // Reload data and force calendar refresh const usage = await fetchUsageData(); setUsageData(usage); setRefreshKey(prev => prev + 1); }; const handleGeneratePlan = async () => { if (!preferences) return; const plan = generateQuitPlan(preferences.substance); const updatedPrefs = { ...preferences, quitPlan: plan, }; await savePreferencesAsync(updatedPrefs); setPreferences(updatedPrefs); setRefreshKey(prev => prev + 1); }; const handleSavingsConfigChange = async (config: SavingsConfig) => { setSavingsConfig(config); await saveSavingsConfig(config); }; const handleCelebrationComplete = () => { setShowCelebration(false); setNewBadge(null); }; if (isLoading) { return (
Loading...
); } return (
{preferences && ( <> {/* Floating Log Button */}
{ const updatedPrefs = { ...preferences, religion }; setPreferences(updatedPrefs); await savePreferencesAsync(updatedPrefs); }} />
)}
{preferences && ( setShowUsagePrompt(false)} onSubmit={handleUsageSubmit} userId={user.id} /> )} {showCelebration && newBadge && ( )}
); }