diff --git a/components/pages/todos/AddChoreDialog.tsx b/components/pages/todos/AddChoreDialog.tsx index 777c30b..561c4d9 100644 --- a/components/pages/todos/AddChoreDialog.tsx +++ b/components/pages/todos/AddChoreDialog.tsx @@ -120,6 +120,10 @@ const AddChoreDialog = (addChoreDialogProps: IAddChoreDialog) => { Alert.alert('Alert', 'Cannot have a todo without any assignees'); return false; } + if (todo?.repeatType === REPEAT_TYPE.EVERY_WEEK && todo?.repeatDays?.length === 0) { + Alert.alert('Alert', 'Please select a specific day for the Weekly recurrence'); + return false; + } return true; } diff --git a/components/pages/todos/ToDosList.tsx b/components/pages/todos/ToDosList.tsx index 19f1191..9c4be7e 100644 --- a/components/pages/todos/ToDosList.tsx +++ b/components/pages/todos/ToDosList.tsx @@ -7,9 +7,9 @@ import {AntDesign} from "@expo/vector-icons"; import {IToDo} from "@/hooks/firebase/types/todoData"; import DropdownIcon from "@/assets/svgs/DropdownIcon"; import {Dropdown} from "react-native-element-dropdown"; -import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers"; import {ProfileType, useAuthContext} from "@/contexts/AuthContext"; import {StyleSheet} from "react-native"; +import {UserProfile} from "@/hooks/firebase/types/profileTypes"; const FILTER_OPTIONS = { ME: "Me", @@ -108,13 +108,11 @@ const resolveFilterOptions = (members, user) => { return options; } -const ToDosList = ({ isSettings }: { isSettings?: boolean }) => { +const ToDosList = ({ isSettings, members }: { isSettings?: boolean, members?: Array }) => { const { toDos } = useToDosContext(); const [groupedToDos, setGroupedToDos] = useState([]); const { user } = useAuthContext() - const { data: members } = useGetFamilyMembers(); - const [expandedGroups, setExpandedGroups] = useState<{ [key: string]: boolean; @@ -130,7 +128,7 @@ const ToDosList = ({ isSettings }: { isSettings?: boolean }) => { let selectedOption = options?.find((option) => option.value === user?.uid); setSelectedFilter(selectedOption); - }, []); + }, [members]); useEffect(() => { if (toDos && selectedFilter) { diff --git a/components/pages/todos/ToDosPage.tsx b/components/pages/todos/ToDosPage.tsx index 6c88672..da997ff 100644 --- a/components/pages/todos/ToDosPage.tsx +++ b/components/pages/todos/ToDosPage.tsx @@ -11,11 +11,14 @@ import FamilyChoresProgress from "./family-chores/FamilyChoresProgress"; import UserChoresProgress from "./user-chores/UserChoresProgress"; import { useAtom } from "jotai"; import { toDosPageIndex } from "../calendar/atoms"; +import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers"; const ToDosPage = () => { const { profileData } = useAuthContext(); const [pageIndex, setPageIndex] = useAtom(toDosPageIndex); + const { data: members } = useGetFamilyMembers(); + const { width, height } = Dimensions.get("screen"); const pageLink = ( setPageIndex(1)}> @@ -65,7 +68,7 @@ const ToDosPage = () => { /> )} - + )} diff --git a/hooks/firebase/useCreateTodo.ts b/hooks/firebase/useCreateTodo.ts index d8456c2..af89afa 100644 --- a/hooks/firebase/useCreateTodo.ts +++ b/hooks/firebase/useCreateTodo.ts @@ -1,8 +1,8 @@ -import {useMutation, useQueryClient} from "react-query"; +import { useMutation, useQueryClient } from "react-query"; import firestore from "@react-native-firebase/firestore"; -import {useAuthContext} from "@/contexts/AuthContext"; -import {DAYS_OF_WEEK_ENUM, IToDo, REPEAT_TYPE} from "@/hooks/firebase/types/todoData"; -import {addDays, addMonths, addWeeks, addYears, compareAsc, format, subDays} from "date-fns"; +import { useAuthContext } from "@/contexts/AuthContext"; +import { DAYS_OF_WEEK_ENUM, IToDo, REPEAT_TYPE } from "@/hooks/firebase/types/todoData"; +import { addMonths, addWeeks, addYears } from "date-fns"; export const daysOfWeek = [ DAYS_OF_WEEK_ENUM.MONDAY, @@ -13,6 +13,66 @@ export const daysOfWeek = [ DAYS_OF_WEEK_ENUM.SATURDAY, DAYS_OF_WEEK_ENUM.SUNDAY]; +const getNextDailyDates = (date) => { + const today = new Date(); + const dates = []; + + for (let weekOffset = 0; weekOffset < 2; weekOffset++) { + const targetDate = addWeeks(date, weekOffset); + if (targetDate > today) { + dates.push(targetDate); + } + } + + return dates; +}; + +const getNextWeeklyDates = (selectedDays, date) => { + const today = new Date(); + const currentDay = date.getDay(); + const dates = []; + + for (let week = 0; week < 2; week++) { + selectedDays.forEach((day) => { + const targetDay = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'].indexOf(day); + const diff = (targetDay - currentDay + 7) % 7 + week * 7; // Move to the next week + const nextDate = new Date(today); + nextDate.setDate(date.getDate() + diff); + dates.push(nextDate); + }); + } + + return dates; +}; + +const getNextMonthlyDates = (date) => { + const today = new Date(); + const dates = []; + + for (let monthOffset = 0; monthOffset < 12; monthOffset++) { + const targetDate = addMonths(date, monthOffset); + if (targetDate > today) { + dates.push(targetDate); + } + } + + return dates; +}; + +const getNextYearlyDates = (date) => { + const today = new Date(); + const dates = []; + + for (let yearOffset = 0; yearOffset < 5; yearOffset++) { + const nextYear = addYears(date, yearOffset); + if (nextYear > today) { + dates.push(nextYear); + } + } + + return dates; +}; + export const useCreateTodo = () => { const { user: currentUser, profileData } = useAuthContext(); const queryClients = useQueryClient(); @@ -28,93 +88,50 @@ export const useCreateTodo = () => { .collection("Todos") .add(originalTodo); } else { - // Create the one original to do - const newDoc = firestore().collection('Todos').doc(); - let originalTodo = {...todoData, id: newDoc.id, familyId: profileData?.familyId, creatorId: currentUser?.uid, connectedTodoId: newDoc.id}; - originalTodo = resolveTodoAlternatingAssignees(todoData, originalTodo, 0); + let nextDates; + if (todoData.repeatType === REPEAT_TYPE.DAILY) { + nextDates = getNextDailyDates(todoData.date); + } else if (todoData.repeatType === REPEAT_TYPE.EVERY_WEEK) { + nextDates = getNextWeeklyDates(todoData.repeatDays, todoData.date); + } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_MONTH) { + nextDates = getNextMonthlyDates(todoData.date); + } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) { + nextDates = getNextYearlyDates(todoData.date); + } - await firestore() - .collection("Todos") - .add(originalTodo); + const todosRef = firestore().collection("Todos"); + const ruleDocRef = todosRef.doc(); + const ruleDoc = await todosRef.add( + {...todoData, + id: ruleDocRef.id, + familyId: profileData?.familyId, + creatorId: currentUser?.uid, + connectedTodoId: ruleDocRef.id,} + ); const batch = firestore().batch(); + nextDates.forEach((date, index) => { + const newDocRef = todosRef.doc(); - if (todoData.repeatType === REPEAT_TYPE.DAILY) { - // for the next 52 weeks - for (let i = 1; i < 52; i++) { - let date = originalTodo.date; - const nextWeek = addWeeks(date, i); - - let docRef = firestore().collection("Todos").doc(); - let newTodo = { ...originalTodo, id: docRef.id, date: nextWeek, connectedTodoId: newDoc.id }; - newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, i); - - batch.set(docRef, newTodo); - } - } else if (todoData.repeatType === REPEAT_TYPE.EVERY_WEEK) { - - let date = originalTodo.date; - let repeatDays = originalTodo.repeatDays; - const dates = []; - - const originalDateDay = format(date, 'EEEE'); - const originalNumber = daysOfWeek.indexOf(originalDateDay); - repeatDays?.forEach((day) => { - let number = daysOfWeek.indexOf(day); - let newDate; - if (originalNumber > number) { - let diff = originalNumber - number; - newDate = subDays(date, diff); - } else { - let diff = number - originalNumber; - newDate = addDays(date, diff); + let assignee; + if (todoData.assignees && todoData.rotate && todoData?.assignees?.length !== 0) { + assignee = todoData.assignees[index % todoData.assignees.length]; } - dates.push(newDate); - }); - let index = 1; - for (let i = 0; i < 52; i++) { - dates?.forEach((dateToAdd) => { - index ++; - let newTodoDate = addWeeks(dateToAdd, i); - if (compareAsc(newTodoDate, originalTodo.date) !== 0) { + const nextTodo = { + ...todoData, + date: date, + id: newDocRef.id, + familyId: profileData?.familyId, + creatorId: currentUser?.uid, + connectedTodoId: ruleDocRef.id, + assignees: assignee ? [assignee] : null + } - let docRef = firestore().collection("Todos").doc(); - let newTodo = { ...originalTodo, id: docRef.id, date: newTodoDate, connectedTodoId: newDoc.id }; - newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, index); - - batch.set(docRef, newTodo); - } - }) + batch.set(newDocRef, nextTodo) } - } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_MONTH) { - - // for the next 12 months - for (let i = 1; i < 12; i++) { - let date = originalTodo.date; - const nextMonth = addMonths(date, i); - - let docRef = firestore().collection("Todos").doc(); - let newTodo = { ...originalTodo, id: docRef.id, date: nextMonth, connectedTodoId: newDoc.id }; - newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, i); - - batch.set(docRef, newTodo); - } - } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) { - - // for the next 5 years - for (let i = 1; i < 5; i++) { - let date = originalTodo.date; - const nextMonth = addYears(date, i); - - let docRef = firestore().collection("Todos").doc(); - let newTodo = { ...originalTodo, id: docRef.id, date: nextMonth, connectedTodoId: newDoc.id }; - newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, i); - - batch.set(docRef, newTodo); - } - } + ); await batch.commit(); }