import { View, Text, TouchableOpacity, Icon } from "react-native-ui-lib"; import React, { useState } from "react"; import { useToDosContext } from "@/contexts/ToDosContext"; import ToDoItem from "./ToDoItem"; import { addDays, format, isToday, isTomorrow, isWithinInterval, } from "date-fns"; import { AntDesign } from "@expo/vector-icons"; import { IToDo } from "@/hooks/firebase/types/todoData"; const groupToDosByDate = (toDos: IToDo[]) => { let sortedTodos = toDos.sort((a, b) => a.date - b.date); return sortedTodos.reduce( (groups, toDo) => { let dateKey; let subDateKey; const isNext7Days = (date: Date) => { const today = new Date(); return isWithinInterval(date, { start: today, end: addDays(today, 7) }); }; const isNext30Days = (date: Date) => { const today = new Date(); return isWithinInterval(date, { start: today, end: addDays(today, 30), }); }; if (toDo.date === null) { dateKey = "No Date"; } else if (isToday(toDo.date)) { dateKey = "Today"; } else if (isTomorrow(toDo.date)) { dateKey = "Tomorrow"; } else if (isNext7Days(toDo.date)) { dateKey = "Next 7 Days"; } else if (isNext30Days(toDo.date)) { dateKey = "Next 30 Days"; subDateKey = format(toDo.date, "MMM d"); } else { return groups; } if (!groups[dateKey]) { groups[dateKey] = { items: [], subgroups: {}, }; } if (dateKey === "Next 30 Days" && subDateKey) { if (!groups[dateKey].subgroups[subDateKey]) { groups[dateKey].subgroups[subDateKey] = []; } groups[dateKey].subgroups[subDateKey].push(toDo); } else { groups[dateKey].items.push(toDo); } return groups; }, {} as { [key: string]: { items: IToDo[]; subgroups: { [key: string]: IToDo[] }; }; } ); }; const ToDosList = ({ isSettings }: { isSettings?: boolean }) => { const { toDos } = useToDosContext(); const groupedToDos = groupToDosByDate(toDos); const [expandedGroups, setExpandedGroups] = useState<{ [key: string]: boolean; }>({}); const [expandNoDate, setExpandNoDate] = useState(true); const toggleExpand = (dateKey: string) => { setExpandedGroups((prev) => ({ ...prev, [dateKey]: !prev[dateKey], })); }; const noDateToDos = groupedToDos["No Date"]?.items || []; const datedToDos = Object.keys(groupedToDos).filter( (key) => key !== "No Date" ); const renderTodoGroup = (dateKey: string) => { const isExpanded = expandedGroups[dateKey] || false; if (dateKey === "Next 30 Days") { const subgroups = Object.entries(groupedToDos[dateKey].subgroups).sort( ([dateA], [dateB]) => { const dateAObj = new Date(dateA); const dateBObj = new Date(dateB); return dateAObj.getTime() - dateBObj.getTime(); } ); return ( toggleExpand(dateKey)} style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center", paddingHorizontal: 0, marginBottom: 4, marginTop: 15, }} > {dateKey} {isExpanded && subgroups.map(([subDate, items]) => { const sortedItems = [ ...items.filter((toDo) => !toDo.done), ...items.filter((toDo) => toDo.done), ]; return ( {subDate} {sortedItems.map((item) => ( ))} ); })} ); } const sortedToDos = [ ...groupedToDos[dateKey].items.filter((toDo) => !toDo.done), ...groupedToDos[dateKey].items.filter((toDo) => toDo.done), ]; return ( toggleExpand(dateKey)} style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center", paddingHorizontal: 0, marginBottom: 4, marginTop: 15, }} > {dateKey} {isExpanded && sortedToDos.map((item) => ( ))} ); }; return ( {noDateToDos.length > 0 && ( Unscheduled { setExpandNoDate(!expandNoDate); }} /> {expandNoDate && noDateToDos .sort((a, b) => Number(a.done) - Number(b.done)) .map((item) => ( ))} )} {datedToDos.map(renderTodoGroup)} ); }; export default ToDosList;