import { Circle, Coins, ArrowRight, CircleCheck, ChevronDown, ChevronUp, Timer } from 'lucide-react' import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger, } from "@/components/ui/context-menu" import { cn, isHabitDueToday, getHabitFreq } from '@/lib/utils' import Link from 'next/link' import { useState, useEffect } from 'react' import { useAtom } from 'jotai' import { pomodoroAtom, settingsAtom, completedHabitsMapAtom, transientSettingsAtom } from '@/lib/atoms' import { getTodayInTimezone, isSameDate, t2d, d2t, getNow } from '@/lib/utils' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Progress } from '@/components/ui/progress' import { WishlistItemType } from '@/lib/types' import { Habit } from '@/lib/types' import Linkify from './linkify' import { useHabits } from '@/hooks/useHabits' interface UpcomingItemsProps { habits: Habit[] wishlistItems: WishlistItemType[] coinBalance: number } export default function DailyOverview({ habits, wishlistItems, coinBalance, }: UpcomingItemsProps) { const { completeHabit, undoComplete } = useHabits() const [settings] = useAtom(settingsAtom) const [dailyHabits, setDailyHabits] = useState([]) const [completedHabitsMap] = useAtom(completedHabitsMapAtom) const today = getTodayInTimezone(settings.system.timezone) const todayCompletions = completedHabitsMap.get(today) || [] useEffect(() => { // Filter habits that are due today based on their recurrence rule const filteredHabits = habits.filter(habit => isHabitDueToday({ habit, timezone: settings.system.timezone })) setDailyHabits(filteredHabits) }, [habits]) // Get all wishlist items sorted by redeemable status (non-redeemable first) then by coin cost const sortedWishlistItems = wishlistItems .sort((a, b) => { const aRedeemable = a.coinCost <= coinBalance const bRedeemable = b.coinCost <= coinBalance // Non-redeemable items first if (aRedeemable !== bRedeemable) { return aRedeemable ? 1 : -1 } // Then sort by coin cost (lower cost first) return a.coinCost - b.coinCost }) const [expandedHabits, setExpandedHabits] = useState(false) const [expandedWishlist, setExpandedWishlist] = useState(false) const [_, setPomo] = useAtom(pomodoroAtom) return ( <> Today's Overview

Daily Habits

{`${dailyHabits.filter(habit => { const completions = (completedHabitsMap.get(today) || []) .filter(h => h.id === habit.id).length; return completions >= (habit.targetCompletions || 1); }).length}/${dailyHabits.length} Completed`}
    {dailyHabits .sort((a, b) => { // First by completion status const aCompleted = todayCompletions.includes(a); const bCompleted = todayCompletions.includes(b); if (aCompleted !== bCompleted) { return aCompleted ? 1 : -1; } // Then by frequency (daily first) const aFreq = getHabitFreq(a); const bFreq = getHabitFreq(b); const freqOrder = ['daily', 'weekly', 'monthly', 'yearly']; if (freqOrder.indexOf(aFreq) !== freqOrder.indexOf(bFreq)) { return freqOrder.indexOf(aFreq) - freqOrder.indexOf(bFreq); } // Then by coin reward (higher first) if (a.coinReward !== b.coinReward) { return b.coinReward - a.coinReward; } // Finally by target completions (higher first) const aTarget = a.targetCompletions || 1; const bTarget = b.targetCompletions || 1; return bTarget - aTarget; }) .slice(0, expandedHabits ? undefined : 5) .map((habit) => { const completionsToday = habit.completions.filter(completion => isSameDate(t2d({ timestamp: completion, timezone: settings.system.timezone }), t2d({ timestamp: d2t({ dateTime: getNow({ timezone: settings.system.timezone }) }), timezone: settings.system.timezone })) ).length const target = habit.targetCompletions || 1 const isCompleted = completionsToday >= target return (
  • {habit.name} { setPomo((prev) => ({ ...prev, show: true, selectedHabitId: habit.id })) }}> Start Pomodoro
    {habit.targetCompletions && ( {completionsToday}/{target} )} {getHabitFreq(habit) !== 'daily' && ( {getHabitFreq(habit)} )} {habit.coinReward}
  • ) })}
View

Wishlist Goals

{wishlistItems.filter(item => item.coinCost <= coinBalance).length}/{wishlistItems.length} Redeemable
{sortedWishlistItems.length === 0 ? (
No wishlist items yet. Add some goals to work towards!
) : ( <> {sortedWishlistItems .slice(0, expandedWishlist ? undefined : 5) .map((item) => { const isRedeemable = item.coinCost <= coinBalance return (
{item.name} {item.coinCost}

{isRedeemable ? "Ready to redeem!" : `${item.coinCost - coinBalance} coins to go` }

) })} )}
View
) }