'use client'; import { useEffect, useState } from 'react'; import api from '@/lib/api'; import { FlameIcon, StarIcon, ClockIcon, ActivityIcon, TargetIcon } from '@/components/ui/Icons'; interface RoutineStats { routine_id: string; routine_name: string; period_days: number; total_sessions: number; completed: number; aborted: number; completion_rate_percent: number; avg_duration_minutes: number; total_time_minutes: number; } interface Streak { routine_id: string; routine_name: string; current_streak: number; longest_streak: number; last_completed_date?: string; } interface WeeklySummary { total_completed: number; total_time_minutes: number; routines_started: number; routines: { routine_id: string; name: string; completed_this_week: number; }[]; } function getStreakMessage(streak: number): string { if (streak === 0) return 'Ready for a fresh start'; if (streak === 1) return "You're back! Day 1"; if (streak <= 3) return `${streak} days of showing up`; if (streak <= 7) return `${streak} days — building momentum`; return `${streak} days — you're someone who shows up`; } function getCompletionLabel(rate: number): { label: string; color: string } { if (rate >= 80) return { label: 'Rock solid', color: 'text-green-600' }; if (rate >= 60) return { label: 'Strong habit', color: 'text-indigo-600' }; if (rate >= 30) return { label: 'Building momentum', color: 'text-amber-600' }; return { label: 'Getting started', color: 'text-gray-600' }; } interface Victory { type: string; message: string; date?: string; } export default function StatsPage() { const [routines, setRoutines] = useState<{ id: string; name: string }[]>([]); const [selectedRoutine, setSelectedRoutine] = useState(''); const [routineStats, setRoutineStats] = useState(null); const [streaks, setStreaks] = useState([]); const [weeklySummary, setWeeklySummary] = useState(null); const [victories, setVictories] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchData = async () => { try { const [routinesData, streaksData, summaryData, victoriesData] = await Promise.all([ api.routines.list(), api.stats.getStreaks(), api.stats.getWeeklySummary(), api.victories.get(30).catch(() => []), ]); setRoutines(routinesData); setStreaks(streaksData); setWeeklySummary(summaryData); setVictories(victoriesData); if (routinesData.length > 0) { setSelectedRoutine(routinesData[0].id); } } catch (err) { console.error('Failed to fetch stats:', err); } finally { setIsLoading(false); } }; fetchData(); }, []); useEffect(() => { const fetchRoutineStats = async () => { if (!selectedRoutine) return; try { const stats = await api.routines.getStats(selectedRoutine, 30); setRoutineStats(stats); } catch (err) { console.error('Failed to fetch routine stats:', err); } }; fetchRoutineStats(); }, [selectedRoutine]); const formatTime = (minutes: number) => { const m = Math.max(0, minutes); if (m < 60) return `${m}m`; const hours = Math.floor(m / 60); const mins = m % 60; return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`; }; if (isLoading) { return (
); } return (

Your Progress

{/* Weekly Summary */} {weeklySummary && (

{weeklySummary.total_completed}

Completed

{formatTime(weeklySummary.total_time_minutes)}

Invested

{weeklySummary.routines_started}

Active

)} {/* Wins This Month */} {victories.length > 0 && (

Wins This Month

{victories.map((victory, i) => (
{victory.type === 'comeback' ? '💪' : victory.type === 'weekend' ? '🎉' : victory.type === 'variety' ? '🌈' : victory.type === 'consistency' ? '🔥' : '⭐'}

{victory.message}

))}
)} {/* Consistency (formerly Streaks) */} {streaks.length > 0 && (

Your Consistency

{streaks.map((streak) => (

{streak.routine_name}

{getStreakMessage(streak.current_streak)}

{streak.current_streak > 0 ? ( <>

{streak.current_streak}

days

) : (

Ready

)}
))} {/* Longest streak callout */} {streaks.some(s => s.longest_streak > 0) && (

Your personal best: {Math.max(...streaks.map(s => s.longest_streak))} days — you've done it before

)}
)} {/* Per-Routine Stats */} {routines.length > 0 && (

Routine Details

{routineStats && (

{getCompletionLabel(routineStats.completion_rate_percent).label}

{routineStats.completion_rate_percent}%

{formatTime(routineStats.avg_duration_minutes)}

Avg Duration

{routineStats.completed}

Completed

{routineStats.total_sessions}

Total Sessions

)} {/* Plateau messaging */} {routineStats && routineStats.total_sessions >= 5 && (

{routineStats.completion_rate_percent >= 60 ? "You're showing up consistently — that's the hard part. The exact rate doesn't matter." : "Life has seasons. The fact that you're checking in shows this matters to you."}

)}
)}
); }