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"; export const daysOfWeek = [ DAYS_OF_WEEK_ENUM.MONDAY, DAYS_OF_WEEK_ENUM.TUESDAY, DAYS_OF_WEEK_ENUM.WEDNESDAY, DAYS_OF_WEEK_ENUM.THURSDAY, DAYS_OF_WEEK_ENUM.FRIDAY, DAYS_OF_WEEK_ENUM.SATURDAY, DAYS_OF_WEEK_ENUM.SUNDAY]; export const useCreateTodo = () => { const { user: currentUser, profileData } = useAuthContext(); const queryClients = useQueryClient(); return useMutation({ mutationKey: ["createTodo"], mutationFn: async (todoData: Partial) => { try { if (todoData.repeatType === REPEAT_TYPE.NONE) { const newDoc = firestore().collection('Todos').doc(); let originalTodo = {...todoData, id: newDoc.id, familyId: profileData?.familyId, creatorId: currentUser?.uid} await firestore() .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); await firestore() .collection("Todos") .add(originalTodo); const batch = firestore().batch(); 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); } 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) { 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); } }) } } 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(); } } catch (e) { console.error(e) } }, onSuccess: () => { queryClients.invalidateQueries("todos") } }) } export const resolveTodoAlternatingAssignees = (todoData, newTodo, i) => { if (todoData.assignees && todoData.rotate && todoData?.assignees?.length !== 0) { const assignees = todoData.assignees; const assignee = assignees[i % assignees.length]; newTodo = {...newTodo, assignees: [assignee]}; } return newTodo; }