import { useMutation, useQueryClient } from "@tanstack/react-query"; import firestore from "@react-native-firebase/firestore"; import {IToDo, REPEAT_TYPE} from "@/hooks/firebase/types/todoData"; import {addDays, addMonths, addWeeks, addYears, compareAsc, format, subDays} from "date-fns"; import {daysOfWeek, resolveTodoAlternatingAssignees} from "@/hooks/firebase/useCreateTodo"; import {useAuthContext} from "@/contexts/AuthContext"; export const useUpdateTodo = () => { const { user: currentUser, profileData } = useAuthContext(); const queryClients = useQueryClient() return useMutation({ mutationKey: ["updateTodo"], mutationFn: async (todoData: Partial) => { try { if (todoData.connectedTodoId) { console.log("CONNECTED") const snapshot = await firestore() .collection("Todos") .where("connectedTodoId", "==", todoData.connectedTodoId) .get(); const connectedTodos = snapshot.docs.map((doc) => { const data = doc.data(); return { ...data, id: doc.id, date: data.date ? new Date(data.date.seconds * 1000) : null, ref: doc.ref }; }) as IToDo[]; console.log("CONNECTED TODO"); let filteredTodos = connectedTodos?.filter((item) => compareAsc(format(item.date, 'yyyy-MM-dd'), format(todoData.date, 'yyyy-MM-dd')) === 1 || compareAsc(format(item.date, 'yyyy-MM-dd'), format(todoData.date, 'yyyy-MM-dd')) === 0).sort((a,b) =>{ return b.date?.getSeconds() - a.date?.getSeconds(); }); let firstTodo = filteredTodos?.[0]; const batch = firestore().batch(); if (compareAsc(format(firstTodo?.date, 'yyyy-MM-dd'), format(todoData.date, 'yyyy-MM-dd')) !== 0 || firstTodo?.repeatType !== todoData.repeatType) { console.log("DELETE"); filteredTodos?.forEach((item) => { batch.delete(item.ref); }); if (todoData.repeatType === REPEAT_TYPE.NONE) { console.log("NONE"); const newDoc = firestore().collection('Todos').doc(); let originalTodo = {...todoData, id: newDoc.id, familyId: profileData?.familyId, creatorId: currentUser?.uid} batch.set(newDoc, originalTodo); } else if (todoData.repeatType === REPEAT_TYPE.DAILY) { console.log("DAILY"); // for the next 52 weeks for (let i = 0; i < 52; i++) { let date = todoData?.date; const nextWeek = addWeeks(date, i); let docRef = firestore().collection("Todos").doc(); let newTodo = { ...todoData, id: docRef.id, date: nextWeek, connectedTodoId: firstTodo?.connectedTodoId }; newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, i); batch.set(docRef, newTodo); } } else if (todoData.repeatType === REPEAT_TYPE.EVERY_WEEK) { console.log("EVERY WEEK"); let date = todoData?.date; let repeatDays = todoData?.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 todosToAddCycles = 52; if (firstTodo?.repeatType === REPEAT_TYPE.EVERY_WEEK) { todosToAddCycles = filteredTodos?.length / firstTodo?.repeatDays?.length; } console.log(todosToAddCycles); let newDoc = firestore().collection("Todos").doc(); let originalTodo = { ...todoData, id: newDoc.id, date: todoData.date, connectedTodoId: newDoc?.id }; originalTodo = resolveTodoAlternatingAssignees(todoData, originalTodo, 0); batch.set(newDoc, originalTodo); console.log(dates); let index = 1; for (let i = 0; i <= todosToAddCycles; i++) { dates?.forEach((dateToAdd) => { index++; let newTodoDate = addWeeks(dateToAdd, i); if (compareAsc(newTodoDate, originalTodo.date) !== 0) { let docRef = firestore().collection("Todos").doc(); let newTodo = { ...todoData, 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) { console.log("ONCE A MONTH"); // for the next 12 months for (let i = 0; i < 12; i++) { let date = todoData?.date; const nextMonth = addMonths(date, i); let docRef = firestore().collection("Todos").doc(); let newTodo = { ...todoData, id: docRef.id, date: nextMonth, connectedTodoId: firstTodo?.connectedTodoId }; newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, i); batch.set(docRef, newTodo); } } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) { console.log("ONCE A YEAR"); // for the next 5 years for (let i = 0; i < 5; i++) { let date = todoData?.date; const nextMonth = addYears(date, i); let docRef = firestore().collection("Todos").doc(); let newTodo = { ...todoData, id: docRef.id, date: nextMonth, connectedTodoId: firstTodo?.connectedTodoId }; newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, i); batch.set(docRef, newTodo); } } await batch.commit(); } else if (firstTodo?.repeatDays !== todoData.repeatDays) { console.log("UPDATE REPEAT DAYS"); await updateRepeatDaysTodos(batch, todoData, firstTodo, filteredTodos) } else { filteredTodos?.forEach((item) => { console.log("UPDATE"); batch.update(item.ref, {...todoData, date: item.date}); }) await batch.commit(); } } else { console.log("REGULAR UPDATE"); console.log(todoData); await firestore() .collection("Todos") .doc(todoData.id) .update(todoData); } } catch (e) { console.error(e) } }, onSuccess: () => { queryClients.invalidateQueries({queryKey: ["todos"]}) } }) } const updateRepeatDaysTodos = async (batch: any, todoData: IToDo, firstTodo: IToDo, filteredTodos: IToDo[]) => { const todosToAddCycles = filteredTodos?.length / firstTodo?.repeatDays?.length; console.log(todosToAddCycles); filteredTodos?.forEach((item) => { batch.update(item.ref, {...todoData, date: item.date}); }) let newRepeatDays = todoData.repeatDays?.filter((element) => firstTodo?.repeatDays?.indexOf(element) === -1); let removeRepeatDays = firstTodo?.repeatDays?.filter((element) => todoData?.repeatDays?.indexOf(element) === -1); const dates = []; let date = firstTodo?.date; const originalDateDay = format(date, 'EEEE'); const originalNumber = daysOfWeek.indexOf(originalDateDay); newRepeatDays?.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 = 0; for (let i = 0; i < todosToAddCycles; i++) { dates?.forEach((dateToAdd) => { index ++; let newTodoDate = addWeeks(dateToAdd, i); if (compareAsc(newTodoDate, firstTodo?.date) !== 0) { let newTodo = {...todoData, date: newTodoDate}; newTodo = resolveTodoAlternatingAssignees(todoData, newTodo, index); let docRef = firestore().collection("Todos").doc(); batch.set(docRef, newTodo); } }) } removeRepeatDays?.forEach((removeDay) => { filteredTodos?.forEach((item) => { let todoDate = item.date; const todoDateDay = format(todoDate, 'EEEE'); if (todoDateDay === removeDay) { batch.delete(item.ref); } }) }) await batch.commit(); }