Avery Felts ec0d83586d Add QuitPlanCard with 7-day tracking and personalized quit plan
- Restore QuitPlanCard component under calendar on dashboard
- Yellow gradient during tracking phase (before 7 days of data)
- Pink gradient when quit plan is active
- Track unique days with logged data for countdown
- Generate 4-week plan with 25% weekly reduction
- White text throughout for readability

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 01:45:59 -07:00

180 lines
5.1 KiB
TypeScript

'use client';
import { useState, useEffect, useCallback } from 'react';
import { User } from '@/lib/session';
import {
fetchPreferences,
fetchUsageData,
savePreferencesAsync,
saveUsageEntryAsync,
shouldShowUsagePrompt,
generateQuitPlan,
UserPreferences,
UsageEntry,
} 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 { Button } from '@/components/ui/button';
import { PlusCircle } from 'lucide-react';
interface DashboardProps {
user: User;
}
export function Dashboard({ user }: DashboardProps) {
const [preferences, setPreferences] = useState<UserPreferences | null>(null);
const [usageData, setUsageData] = useState<UsageEntry[]>([]);
const [showSetup, setShowSetup] = useState(false);
const [showUsagePrompt, setShowUsagePrompt] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [refreshKey, setRefreshKey] = useState(0);
const loadData = useCallback(async () => {
const [prefs, usage] = await Promise.all([
fetchPreferences(),
fetchUsageData(),
]);
setPreferences(prefs);
setUsageData(usage);
setRefreshKey(prev => prev + 1);
return prefs;
}, []);
useEffect(() => {
const init = async () => {
const prefs = await loadData();
if (!prefs.hasCompletedSetup) {
setShowSetup(true);
} else if (shouldShowUsagePrompt()) {
setShowUsagePrompt(true);
}
setIsLoading(false);
};
init();
}, [loadData]);
const handleSetupComplete = async (data: { substance: 'nicotine' | 'weed'; name: string; age: number }) => {
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,
};
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);
};
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="animate-pulse text-lg text-white">Loading...</div>
</div>
);
}
return (
<div className="min-h-screen">
<UserHeader user={user} />
<main className="container mx-auto px-4 py-8">
{preferences && (
<>
{/* Floating Log Button */}
<div className="fixed bottom-6 right-6 z-50">
<Button
size="lg"
onClick={() => setShowUsagePrompt(true)}
className="h-16 px-8 text-lg rounded-full shadow-xl bg-gradient-to-r from-primary to-primary/80 hover:from-primary/90 hover:to-primary/70 drop-shadow-lg"
>
<PlusCircle className="mr-2 h-6 w-6" />
Log Usage
</Button>
</div>
<div className="grid gap-6 md:grid-cols-2">
<div className="space-y-6">
<UsageCalendar
key={refreshKey}
usageData={usageData}
onDataUpdate={loadData}
userId={user.id}
/>
<QuitPlanCard
key={`quit-plan-${refreshKey}`}
plan={preferences.quitPlan}
onGeneratePlan={handleGeneratePlan}
usageData={usageData}
/>
</div>
<div className="space-y-6">
<StatsCard key={`stats-nicotine-${refreshKey}`} usageData={usageData} substance="nicotine" />
<StatsCard key={`stats-weed-${refreshKey}`} usageData={usageData} substance="weed" />
</div>
</div>
</>
)}
</main>
<SetupWizard open={showSetup} onComplete={handleSetupComplete} />
{preferences && (
<UsagePromptDialog
open={showUsagePrompt}
onClose={() => setShowUsagePrompt(false)}
onSubmit={handleUsageSubmit}
userId={user.id}
/>
)}
</div>
);
}