'use client' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input'; // Added import { Label } from '@/components/ui/label'; // Added import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; // Added import { useHabits } from '@/hooks/useHabits' import { habitsAtom } from '@/lib/atoms' import { HabitIcon, TaskIcon } from '@/lib/constants' import { Habit } from '@/lib/types' import { getHabitFreq } from '@/lib/utils'; // Added import { useAtom } from 'jotai' import { ArrowDownWideNarrow, ArrowUpNarrowWide, Plus, Search } from 'lucide-react'; // Added sort icons, Search icon import { DateTime } from 'luxon'; // Added import { useEffect, useMemo, useState } from 'react'; // Added useMemo, useEffect import AddEditHabitModal from './AddEditHabitModal' import ConfirmDialog from './ConfirmDialog' import EmptyState from './EmptyState' import HabitItem from './HabitItem' import { ViewToggle } from './ViewToggle' export default function HabitList({ isTasksView }: { isTasksView: boolean}) { const { saveHabit, deleteHabit } = useHabits() const [habitsData] = useAtom(habitsAtom) // setHabitsData removed as it's not used type SortableField = 'name' | 'coinReward' | 'dueDate' | 'frequency'; type SortOrder = 'asc' | 'desc'; const [searchTerm, setSearchTerm] = useState(''); const [sortBy, setSortBy] = useState('name'); const [sortOrder, setSortOrder] = useState('asc'); useEffect(() => { if (isTasksView && sortBy === 'frequency') { setSortBy('name'); } else if (!isTasksView && sortBy === 'dueDate') { setSortBy('name'); } }, [isTasksView, sortBy]); const compareHabits = useMemo(() => { return (a: Habit, b: Habit, currentSortBy: SortableField, currentSortOrder: SortOrder, tasksView: boolean): number => { let comparison = 0; switch (currentSortBy) { case 'name': comparison = a.name.localeCompare(b.name); break; case 'coinReward': comparison = a.coinReward - b.coinReward; break; case 'dueDate': if (tasksView && a.isTask && b.isTask) { const dateA = DateTime.fromISO(a.frequency); const dateB = DateTime.fromISO(b.frequency); if (dateA.isValid && dateB.isValid) comparison = dateA.toMillis() - dateB.toMillis(); else if (dateA.isValid) comparison = -1; // Valid dates first else if (dateB.isValid) comparison = 1; // If both invalid, comparison remains 0 } break; case 'frequency': if (!tasksView && !a.isTask && !b.isTask) { const freqOrder = ['daily', 'weekly', 'monthly', 'yearly']; const freqAVal = getHabitFreq(a); const freqBVal = getHabitFreq(b); comparison = freqOrder.indexOf(freqAVal) - freqOrder.indexOf(freqBVal); } break; } return currentSortOrder === 'asc' ? comparison : -comparison; }; }, []); const allHabitsInView = useMemo(() => { return habitsData.habits.filter(habit => isTasksView ? habit.isTask : !habit.isTask ); }, [habitsData.habits, isTasksView]); const searchedHabits = useMemo(() => { if (!searchTerm.trim()) { return allHabitsInView; } const lowercasedSearchTerm = searchTerm.toLowerCase(); return allHabitsInView.filter(habit => habit.name.toLowerCase().includes(lowercasedSearchTerm) || (habit.description && habit.description.toLowerCase().includes(lowercasedSearchTerm)) ); }, [allHabitsInView, searchTerm]); const activeHabits = useMemo(() => { return searchedHabits .filter(h => !h.archived) .sort((a, b) => { if (a.pinned && !b.pinned) return -1; if (!a.pinned && b.pinned) return 1; // For items in the same pinned group (both pinned or both not pinned), apply general sort return compareHabits(a, b, sortBy, sortOrder, isTasksView); }); }, [searchedHabits, sortBy, sortOrder, isTasksView, compareHabits]); const archivedHabits = useMemo(() => { return searchedHabits .filter(h => h.archived) .sort((a, b) => compareHabits(a, b, sortBy, sortOrder, isTasksView)); }, [searchedHabits, sortBy, sortOrder, isTasksView, compareHabits]); const [modalConfig, setModalConfig] = useState<{ isOpen: boolean, isTask: boolean }>({ isOpen: false, isTask: false }) const [editingHabit, setEditingHabit] = useState(null) const [deleteConfirmation, setDeleteConfirmation] = useState<{ isOpen: boolean, habitId: string | null }>({ isOpen: false, habitId: null }) return (

{`My ${isTasksView ? "Tasks" : "Habits"}`}

{/* Search and Sort Controls */}
setSearchTerm(e.target.value)} className="pl-10 w-full" />
{activeHabits.length === 0 && searchTerm.trim() ? (
No {isTasksView ? 'tasks' : 'habits'} found matching your search.
) : activeHabits.length === 0 ? (
) : ( activeHabits.map((habit: Habit) => ( { setEditingHabit(habit) setModalConfig({ isOpen: true, isTask: isTasksView }) }} onDelete={() => setDeleteConfirmation({ isOpen: true, habitId: habit.id })} /> )) )} {archivedHabits.length > 0 && ( <>
Archived
{archivedHabits.map((habit: Habit) => ( { setEditingHabit(habit) setModalConfig({ isOpen: true, isTask: isTasksView }) }} onDelete={() => setDeleteConfirmation({ isOpen: true, habitId: habit.id })} /> ))} )}
{modalConfig.isOpen && { setModalConfig({ isOpen: false, isTask: false }) setEditingHabit(null) }} onSave={async (habit) => { await saveHabit({ ...habit, id: editingHabit?.id, isTask: modalConfig.isTask }) setModalConfig({ isOpen: false, isTask: false }) setEditingHabit(null) }} habit={editingHabit} isTask={modalConfig.isTask} /> } setDeleteConfirmation({ isOpen: false, habitId: null })} onConfirm={async () => { if (deleteConfirmation.habitId) { await deleteHabit(deleteConfirmation.habitId) } setDeleteConfirmation({ isOpen: false, habitId: null }) }} title={isTasksView ? "Delete Task" : "Delete Habit"} message={isTasksView ? "Are you sure you want to delete this task? This action cannot be undone." : "Are you sure you want to delete this habit? This action cannot be undone."} confirmText="Delete" />
) }