Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 103 additions & 9 deletions app/dashboard/todo/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { getCurrentUser } from "@/lib/features/auth"
import { getTranslations, getUserLanguage } from "@/lib/config"
import { Plus, Trash2, Check, X, CheckCircle2, Circle, Search, Filter, Play, Pause, RotateCcw, Coffee, Timer } from "lucide-react"
import { Plus, Trash2, Check, X, CheckCircle2, Circle, Search, Filter, Play, Pause, RotateCcw, Coffee, Timer, HelpCircle, Settings, Music } from "lucide-react"
import { getTodos, createTodo, updateTodo, deleteTodo, type Todo as DBTodo } from "@/lib/database"

interface Task {
Expand Down Expand Up @@ -49,11 +49,16 @@ export default function TodoPage() {
const [workDuration, setWorkDuration] = useState(25)
const [breakDuration, setBreakDuration] = useState(5)
const [showSettings, setShowSettings] = useState(false)
const [showPomodoroHelp, setShowPomodoroHelp] = useState(false)
const [showMusic, setShowMusic] = useState(false)

// Toast notification state
const [toast, setToast] = useState<{ message: string; type: 'work' | 'break' } | null>(null)

// Sound Effect
const playNotificationSound = useCallback(() => {
try {
const audio = new Audio('https://assets.mixkit.co/active_storage/sfx/2869/2869-preview.mp3')
const audio = new Audio('/sounds/timer-complete.mp3')
audio.volume = 0.5
audio.play().catch(e => console.log('Audio play failed:', e))
} catch (e) {
Expand Down Expand Up @@ -120,16 +125,19 @@ export default function TodoPage() {
if (pomodoroMode === 'work') {
// Work session completed
setPomodoroSessions((s) => s + 1)
alert('Work session completed! Time for a break.')
setToast({ message: '🎉 Work session completed! Time for a break.', type: 'break' })
// Switch to break mode
setPomodoroMode('break')
setPomodoroTime(breakDuration * 60)
} else {
// Break completed
alert('Break is over! Ready for another session?')
setToast({ message: '💪 Break is over! Ready for another session?', type: 'work' })
setPomodoroMode('work')
setPomodoroTime(workDuration * 60)
}

// Auto-dismiss toast after 5 seconds
setTimeout(() => setToast(null), 5000)
}

return () => {
Expand Down Expand Up @@ -264,6 +272,25 @@ export default function TodoPage() {

return (
<div className="p-8 space-y-8">
{/* Toast Notification */}
{toast && (
<div className={`fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg border animate-in slide-in-from-top-2 duration-300 ${
toast.type === 'break'
? 'bg-green-500/10 border-green-500/30 text-green-500'
: 'bg-primary/10 border-primary/30 text-primary'
}`}>
<div className="flex items-center gap-3">
<span className="text-lg">{toast.message}</span>
<button
onClick={() => setToast(null)}
className="text-current opacity-60 hover:opacity-100"
>
<X className="h-4 w-4" />
</button>
</div>
</div>
)}

<div className="flex items-center justify-between border-b border-border pb-8">
<div>
<h1 className="text-4xl font-bold mb-2">{t.title}</h1>
Expand Down Expand Up @@ -291,7 +318,16 @@ export default function TodoPage() {
onClick={() => setShowSettings(!showSettings)}
title="Timer Settings"
>
<RotateCcw className="h-4 w-4" />
<Settings className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="icon"
className={`h-8 w-8 ${showMusic ? 'text-primary' : ''}`}
onClick={() => setShowMusic(!showMusic)}
title="Focus Music"
>
<Music className="h-4 w-4" />
</Button>
<span className={`px-3 py-1 rounded-full text-xs font-medium ${
pomodoroMode === 'work'
Expand All @@ -303,6 +339,35 @@ export default function TodoPage() {
</div>
</div>

{/* Lofi Music Player - Minimal Auto-Play */}
{showMusic && (
<div className="mb-6 p-3 border border-primary/30 bg-primary/5 rounded-lg flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="h-8 w-8 rounded-full bg-primary/20 flex items-center justify-center">
<Music className="h-4 w-4 text-primary animate-pulse" />
</div>
<div>
<p className="text-sm font-medium">🎵 Lofi Girl - beats to study/relax</p>
<p className="text-xs text-muted-foreground">Now playing...</p>
</div>
</div>
<button
onClick={() => setShowMusic(false)}
className="text-muted-foreground hover:text-foreground p-2"
title="Stop Music"
>
<X className="h-4 w-4" />
</button>
{/* Hidden YouTube iframe for audio */}
<iframe
className="hidden"
src="https://www.youtube.com/embed/jfKfPfyJRdk?autoplay=1&loop=1"
title="Lofi Music"
allow="autoplay"
/>
</div>
)}

{showSettings && (
<div className="mb-6 p-4 border border-border bg-secondary/50 rounded-lg animate-fade-in-down">
<h3 className="text-sm font-medium mb-3">Timer Settings (minutes)</h3>
Expand Down Expand Up @@ -354,7 +419,7 @@ export default function TodoPage() {
pomodoroMode === 'work' ? 'bg-primary' : 'bg-green-500'
}`}
style={{
width: `${(pomodoroTime / (pomodoroMode === 'work' ? 25 * 60 : 5 * 60)) * 100}%`
width: `${(pomodoroTime / (pomodoroMode === 'work' ? workDuration * 60 : breakDuration * 60)) * 100}%`
}}
/>
</div>
Expand Down Expand Up @@ -383,18 +448,47 @@ export default function TodoPage() {
</div>
</div>

{/* Info Sidebar */}
{/* Info Sidebar with Instructions */}
<div className="md:border-l md:border-border md:pl-8 space-y-4 max-w-xs">
{/* Help Toggle */}
<div className="flex items-center justify-between">
<h3 className="text-sm font-medium text-muted-foreground">How to Use</h3>
<Button
variant="ghost"
size="sm"
onClick={() => setShowPomodoroHelp(!showPomodoroHelp)}
className="h-6 px-2"
>
<HelpCircle className="h-4 w-4" />
</Button>
</div>

{/* User Instructions */}
{showPomodoroHelp && (
<div className="bg-primary/5 border border-primary/20 rounded-lg p-3 space-y-2 text-sm animate-fade-in-down">
<p className="font-medium text-primary">Getting Started:</p>
<ol className="space-y-1.5 text-muted-foreground text-xs">
<li>1. Click the <span className="text-primary">⚙️ Settings</span> icon to set your preferred work/break durations</li>
<li>2. Press <span className="text-primary">▶ Start</span> to begin your focus session</li>
<li>3. Work until the timer ends (you&apos;ll hear a sound)</li>
<li>4. Take a break when prompted, then repeat!</li>
</ol>
<p className="text-xs text-muted-foreground/80 pt-2 border-t border-border">
💡 Tip: The classic Pomodoro uses 25 min work + 5 min break
</p>
</div>
)}

<div>
<h3 className="text-sm font-medium mb-3 text-muted-foreground">Technique</h3>
<div className="space-y-2 text-sm">
<div className="flex items-center gap-2">
<div className="h-2 w-2 rounded-full bg-primary" />
<span>25 min work</span>
<span>{workDuration} min work</span>
</div>
<div className="flex items-center gap-2">
<div className="h-2 w-2 rounded-full bg-green-500" />
<span>5 min break</span>
<span>{breakDuration} min break</span>
</div>
</div>
</div>
Expand Down
Binary file added public/sounds/timer-complete.mp3
Binary file not shown.
Loading