diff --git a/src/app/habit-tracker/page.tsx b/src/app/habit-tracker/page.tsx new file mode 100644 index 0000000..2abfad7 --- /dev/null +++ b/src/app/habit-tracker/page.tsx @@ -0,0 +1,239 @@ +"use client"; + +import { useState } from "react"; + +// Mock data for habit tracking +const initialHabits = [ + { + id: "h1", + name: "Morning Exercise", + icon: "🏃", + frequency: "daily" as const, + streak: 12, + completedDays: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + targetDays: 30, + }, + { + id: "h2", + name: "Read 30 minutes", + icon: "📚", + frequency: "daily" as const, + streak: 5, + completedDays: [8, 9, 10, 11, 12], + targetDays: 30, + }, + { + id: "h3", + name: "Meditation", + icon: "🧘", + frequency: "daily" as const, + streak: 21, + completedDays: Array.from({ length: 21 }, (_, i) => i + 1), + targetDays: 30, + }, + { + id: "h4", + name: "Learn TypeScript", + icon: "💻", + frequency: "weekly" as const, + streak: 3, + completedDays: [1, 2, 3], + targetDays: 12, + }, +]; + +const today = 12; // Mock current day of month + +export default function HabitTrackerPage() { + const [habits, setHabits] = useState(initialHabits); + + const toggleHabit = (habitId: string) => { + setHabits( + habits.map((habit) => { + if (habit.id !== habitId) return habit; + + const isCompleted = habit.completedDays.includes(today); + let newCompletedDays: number[]; + let newStreak: number; + + if (isCompleted) { + // Uncomplete for today + newCompletedDays = habit.completedDays.filter((d) => d !== today); + newStreak = Math.max(0, habit.streak - 1); + } else { + // Complete for today + newCompletedDays = [...habit.completedDays, today].sort((a, b) => a - b); + newStreak = habit.streak + 1; + } + + return { + ...habit, + completedDays: newCompletedDays, + streak: newStreak, + }; + }) + ); + }; + + const totalStreak = habits.reduce((sum, h) => sum + h.streak, 0); + const completedToday = habits.filter((h) => h.completedDays.includes(today)).length; + + return ( +
+ {/* Header */} +
+

Habit Tracker

+

+ Track your daily habits and build streaks to stay motivated. +

+ + {/* Stats */} +
+
+
{habits.length}
+
Active Habits
+
+
+
{totalStreak}
+
Total Streak Days
+
+
+
+ {completedToday}/{habits.length} +
+
Completed Today
+
+
+
+ {Math.round((completedToday / habits.length) * 100)}% +
+
Daily Progress
+
+
+
+ + {/* Habit List */} +
+ {habits.map((habit) => ( + toggleHabit(habit.id)} + /> + ))} +
+ + {/* Legend */} +
+

How it works

+ +
+
+ ); +} + +interface Habit { + id: string; + name: string; + icon: string; + frequency: "daily" | "weekly"; + streak: number; + completedDays: number[]; + targetDays: number; +} + +function HabitCard({ + habit, + isCompletedToday, + onToggle, +}: { + habit: Habit; + isCompletedToday: boolean; + onToggle: () => void; +}) { + const progress = (habit.completedDays.length / habit.targetDays) * 100; + + return ( +
+
+
+ {/* Checkbox */} +
+ {isCompletedToday ? "✓" : habit.icon} +
+ + {/* Habit Info */} +
+

{habit.name}

+
+ {habit.frequency} + + + 🔥 {habit.streak} day streak + +
+
+
+ + {/* Progress */} +
+
+ {habit.completedDays.length}/{habit.targetDays} days +
+
+
= 80 + ? "bg-green-500" + : progress >= 50 + ? "bg-blue-500" + : "bg-amber-500" + }`} + style={{ width: `${progress}%` }} + /> +
+
+
+ + {/* Streak Badge */} + {habit.streak >= 7 && ( +
+ {habit.streak >= 21 && ( + + 🏆 3 Week Champion + + )} + {habit.streak >= 14 && habit.streak < 21 && ( + + ⭐ 2 Week Achiever + + )} + {habit.streak >= 7 && habit.streak < 14 && ( + + 🌟 1 Week Warrior + + )} +
+ )} +
+ ); +}