'use client'; import { useState, useEffect, useCallback } from 'react'; import { useTimerStore } from '@/lib/store'; import { useTickLoop } from '@/lib/use-tick'; import { useKeyboardShortcuts, SHORTCUT_MAP } from '@/lib/use-keyboard-shortcuts'; import { TimerCard } from './TimerCard'; import { PomodoroView } from './PomodoroView'; import { QuickTimerBar } from './QuickTimerBar'; import { CreateTimerModal } from './CreateTimerModal'; import { AlarmOverlay } from './AlarmOverlay'; import { requestNotificationPermission } from '@/lib/notifications'; import { formatTime, formatDate } from '@/lib/format'; import { Plus, Clock, Bell, Keyboard } from 'lucide-react'; export function Dashboard() { const [isCreateOpen, setIsCreateOpen] = useState(false); const [showShortcuts, setShowShortcuts] = useState(false); const [mounted, setMounted] = useState(false); const timers = useTimerStore((s) => s.timers); const now = useTimerStore((s) => s.now); const { pause, resume } = useTimerStore(); // Start the tick loop useTickLoop(); // Keyboard shortcuts const getFirstActiveTimer = useCallback(() => { return timers.find((t) => ['active', 'warning', 'paused'].includes(t.state)); }, [timers]); useKeyboardShortcuts({ onNewTimer: () => setIsCreateOpen(true), onQuickTimer: () => setIsCreateOpen(true), onTogglePause: () => { const t = getFirstActiveTimer(); if (!t) return; if (t.state === 'paused') resume(t.id); else if (t.type !== 'alarm') pause(t.id); }, onDismiss: () => { if (isCreateOpen) setIsCreateOpen(false); else if (showShortcuts) setShowShortcuts(false); }, onShowHelp: () => setShowShortcuts((p) => !p), }); // Hydration guard useEffect(() => { setMounted(true); requestNotificationPermission(); }, []); if (!mounted) { return (
); } const activeTimers = timers.filter((t) => ['active', 'warning', 'snoozed', 'firing', 'paused'].includes(t.state) ); const completedTimers = timers .filter((t) => ['dismissed', 'completed'].includes(t.state)) .slice(-10) .reverse(); // Tab title update useEffect(() => { const next = activeTimers .filter((t) => ['active', 'warning'].includes(t.state)) .sort((a, b) => a.targetTime - b.targetTime)[0]; if (next) { const remaining = Math.max(0, next.targetTime - now); const mins = Math.floor(remaining / 60000); const secs = Math.floor((remaining % 60000) / 1000); document.title = `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')} โ€” ${next.label} | ChronoMind`; } else { document.title = 'ChronoMind โ€” Smart Pre-Warning Timer'; } }, [now, activeTimers]); return (
{/* Alarm overlay for firing timers */} {/* Header */}

ChronoMind

{formatTime(now)} ยท {formatDate(now)}
{/* Keyboard shortcuts overlay */} {showShortcuts && (
setShowShortcuts(false)} />

Keyboard Shortcuts

{SHORTCUT_MAP.map((s) => (
{s.description} {s.key}
))}
)} {/* Main content */}
{/* Quick timer bar */}
{/* Active timers */} {activeTimers.length > 0 ? (

Active ({activeTimers.length})

{activeTimers .sort((a, b) => a.targetTime - b.targetTime) .map((timer) => timer.type === 'pomodoro' ? ( ) : ( ) )}
) : ( /* Empty state */

No active timers

Create your first timer and never be caught off-guard again.

)} {/* Completed timers */} {completedTimers.length > 0 && (

Recent ({completedTimers.length})

{completedTimers.map((timer) => ( ))}
)}
{/* Create Timer Modal */} setIsCreateOpen(false)} /> {/* Footer */}
); }