- Implemented the complete update of recurring todo and handle changing the recurring rule and date

This commit is contained in:
Dejan
2024-10-26 13:20:09 +02:00
parent d064d5c9c2
commit 5c67ffccbd
2 changed files with 153 additions and 68 deletions

View File

@ -2,7 +2,7 @@ import {useMutation, useQueryClient} from "react-query";
import firestore from "@react-native-firebase/firestore"; import firestore from "@react-native-firebase/firestore";
import {useAuthContext} from "@/contexts/AuthContext"; import {useAuthContext} from "@/contexts/AuthContext";
import {DAYS_OF_WEEK_ENUM, IToDo, REPEAT_TYPE} from "@/hooks/firebase/types/todoData"; import {DAYS_OF_WEEK_ENUM, IToDo, REPEAT_TYPE} from "@/hooks/firebase/types/todoData";
import {addDays, addMonths, addWeeks, compareAsc, format, getDay, subDays} from "date-fns"; import {addDays, addMonths, addWeeks, addYears, compareAsc, format, subDays} from "date-fns";
export const daysOfWeek = [ export const daysOfWeek = [
DAYS_OF_WEEK_ENUM.MONDAY, DAYS_OF_WEEK_ENUM.MONDAY,
@ -21,14 +21,20 @@ export const useCreateTodo = () => {
mutationKey: ["createTodo"], mutationKey: ["createTodo"],
mutationFn: async (todoData: Partial<IToDo>) => { mutationFn: async (todoData: Partial<IToDo>) => {
try { try {
// Create the one original to do if (todoData.repeatType === REPEAT_TYPE.NONE) {
const newDoc = firestore().collection('Todos').doc(); const newDoc = firestore().collection('Todos').doc();
let originalTodo = {...todoData, id: newDoc.id, familyId: profileData?.familyId, creatorId: currentUser?.uid} let originalTodo = {...todoData, id: newDoc.id, familyId: profileData?.familyId, creatorId: currentUser?.uid}
await firestore() await firestore()
.collection("Todos") .collection("Todos")
.add(originalTodo); .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};
await firestore()
.collection("Todos")
.add(originalTodo);
if (todoData.repeatType !== REPEAT_TYPE.NONE) {
const batch = firestore().batch(); const batch = firestore().batch();
if (todoData.repeatType === REPEAT_TYPE.EVERY_WEEK) { if (todoData.repeatType === REPEAT_TYPE.EVERY_WEEK) {
@ -57,36 +63,33 @@ export const useCreateTodo = () => {
dates?.forEach((dateToAdd) => { dates?.forEach((dateToAdd) => {
let newTodoDate = addWeeks(dateToAdd, i); let newTodoDate = addWeeks(dateToAdd, i);
if (compareAsc(newTodoDate, originalTodo.date) !== 0) { if (compareAsc(newTodoDate, originalTodo.date) !== 0) {
const newTodo = { ...originalTodo, date: newTodoDate, connectedTodoId: newDoc.id };
let docRef = firestore().collection("Todos").doc(); let docRef = firestore().collection("Todos").doc();
const newTodo = { ...originalTodo, id: docRef.id, date: newTodoDate, connectedTodoId: newDoc.id };
batch.set(docRef, newTodo); batch.set(docRef, newTodo);
console.log(newTodo);
} }
}) })
} }
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_MONTH) { } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_MONTH) {
// for the next 12 months // for the next 12 months
for (let i = 0; i < 12; i++) { for (let i = 1; i < 12; i++) {
let date = originalTodo.date; let date = originalTodo.date;
const nextMonth = addMonths(date, i + 1); const nextMonth = addMonths(date, i);
const newTodo = { ...originalTodo, date: nextMonth, connectedTodoId: newDoc.id };
console.log(newTodo);
let docRef = firestore().collection("Todos").doc(); let docRef = firestore().collection("Todos").doc();
const newTodo = { ...originalTodo, id: docRef.id, date: nextMonth, connectedTodoId: newDoc.id };
batch.set(docRef, newTodo); batch.set(docRef, newTodo);
} }
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) { } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) {
// for the next 5 years // for the next 5 years
for (let i = 0; i < 5; i++) { for (let i = 1; i < 5; i++) {
let date = originalTodo.date; let date = originalTodo.date;
const nextMonth = addMonths(date, i + 1); const nextMonth = addYears(date, i);
const newTodo = { ...originalTodo, date: nextMonth, connectedTodoId: newDoc.id };
console.log(newTodo);
let docRef = firestore().collection("Todos").doc(); let docRef = firestore().collection("Todos").doc();
const newTodo = { ...originalTodo, id: docRef.id, date: nextMonth, connectedTodoId: newDoc.id };
batch.set(docRef, newTodo); batch.set(docRef, newTodo);
} }
} }

View File

@ -1,24 +1,24 @@
import { useMutation, useQueryClient } from "react-query"; import { useMutation, useQueryClient } from "react-query";
import firestore from "@react-native-firebase/firestore"; import firestore from "@react-native-firebase/firestore";
import {IToDo} from "@/hooks/firebase/types/todoData"; import {IToDo, REPEAT_TYPE} from "@/hooks/firebase/types/todoData";
import {addDays, addWeeks, compareAsc, format, subDays} from "date-fns"; import {addDays, addMonths, addWeeks, addYears, compareAsc, format, subDays} from "date-fns";
import {daysOfWeek} from "@/hooks/firebase/useCreateTodo"; import {daysOfWeek} from "@/hooks/firebase/useCreateTodo";
import {useAuthContext} from "@/contexts/AuthContext";
export const useUpdateTodo = () => { export const useUpdateTodo = () => {
const { user: currentUser, profileData } = useAuthContext();
const queryClients = useQueryClient() const queryClients = useQueryClient()
return useMutation({ return useMutation({
mutationKey: ["updateTodo"], mutationKey: ["updateTodo"],
mutationFn: async (todoData: Partial<IToDo>) => { mutationFn: async (todoData: Partial<IToDo>) => {
try { try {
const snapshot = await firestore()
.collection("Todos")
.where("connectedTodoId", "==", todoData.connectedTodoId)
.get();
if (todoData.connectedTodoId) { if (todoData.connectedTodoId) {
console.log("CONNECTED TODO");
const snapshot = await firestore()
.collection("Todos")
.where("connectedTodoId", "==", todoData.connectedTodoId)
.get();
const connectedTodos = snapshot.docs.map((doc) => { const connectedTodos = snapshot.docs.map((doc) => {
const data = doc.data(); const data = doc.data();
@ -30,25 +30,37 @@ export const useUpdateTodo = () => {
}; };
}) as IToDo[]; }) as IToDo[];
let filteredTodos = connectedTodos?.filter((item) => item.date >= todoData.date).sort((a,b) =>{ 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(); return b.date?.getSeconds() - a.date?.getSeconds();
}); });
console.log(filteredTodos);
let firstTodo = filteredTodos?.[0]; let firstTodo = filteredTodos?.[0];
// resolve the repeating
const batch = firestore().batch(); const batch = firestore().batch();
const todosToAddCycles = filteredTodos?.length / firstTodo?.repeatDays?.length; if (compareAsc(format(firstTodo?.date, 'yyyy-MM-dd'), format(todoData.date, 'yyyy-MM-dd')) !== 0 || firstTodo?.repeatType !== todoData.repeatType) {
console.log(todosToAddCycles);
if (firstTodo?.repeatDays !== todoData.repeatDays) { console.log("DELETE");
let newRepeatDays = todoData.repeatDays?.filter((element) => firstTodo?.repeatDays?.indexOf(element) === -1); filteredTodos?.forEach((item) => {
let removeRepeatDays = firstTodo?.repeatDays?.filter((element) => todoData?.repeatDays?.indexOf(element) === -1); 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.EVERY_WEEK) {
console.log("EVERY WEEK");
let date = todoData?.date;
let repeatDays = todoData?.repeatDays;
const dates = []; const dates = [];
let date = firstTodo?.date;
const originalDateDay = format(date, 'EEEE'); const originalDateDay = format(date, 'EEEE');
const originalNumber = daysOfWeek.indexOf(originalDateDay); const originalNumber = daysOfWeek.indexOf(originalDateDay);
newRepeatDays?.forEach((day) => { repeatDays?.forEach((day) => {
let number = daysOfWeek.indexOf(day); let number = daysOfWeek.indexOf(day);
let newDate; let newDate;
if (originalNumber > number) { if (originalNumber > number) {
@ -61,53 +73,67 @@ export const useUpdateTodo = () => {
dates.push(newDate); dates.push(newDate);
}); });
console.log("REPEAT") let todosToAddCycles = 4;
console.log(newRepeatDays); if (firstTodo?.repeatType === REPEAT_TYPE.EVERY_WEEK) {
console.log(removeRepeatDays); todosToAddCycles = filteredTodos?.length / firstTodo?.repeatDays?.length;
}
console.log(todosToAddCycles);
let newDoc = firestore().collection("Todos").doc();
const newTodo = { ...todoData, id: newDoc.id, date: todoData.date, connectedTodoId: newDoc?.id };
batch.set(newDoc, newTodo);
console.log(dates); console.log(dates);
filteredTodos?.forEach((item) => {
batch.update(item.ref, {...todoData, date: item.date});
})
// TODO: for the next connected -> filtered todos - number of weeks
for (let i = 0; i < todosToAddCycles; i++) { for (let i = 0; i < todosToAddCycles; i++) {
dates?.forEach((dateToAdd) => { dates?.forEach((dateToAdd) => {
let newTodoDate = addWeeks(dateToAdd, i); let newTodoDate = addWeeks(dateToAdd, i);
if (compareAsc(newTodoDate, firstTodo?.date) !== 0) {
const newTodo = { ...todoData, date: newTodoDate };
console.log("ENTER")
let docRef = firestore().collection("Todos").doc(); let docRef = firestore().collection("Todos").doc();
const newTodo = { ...todoData, id: docRef.id, date: newTodoDate, connectedTodoId: newDoc?.id };
batch.set(docRef, newTodo); batch.set(docRef, newTodo);
console.log("ADD")
console.log(newTodo);
}
}) })
} }
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_MONTH) {
removeRepeatDays?.forEach((removeDay) => { console.log("ONCE A MONTH");
filteredTodos?.forEach((item) => { // for the next 12 months
for (let i = 0; i < 12; i++) {
let date = todoData?.date;
const nextMonth = addMonths(date, i);
const newTodo = { ...todoData, date: nextMonth, connectedTodoId: firstTodo?.connectedTodoId };
let todoDate = item.date; let docRef = firestore().collection("Todos").doc();
const todoDateDay = format(todoDate, 'EEEE'); batch.set(docRef, newTodo);
console.log(todoDateDay); }
if (todoDateDay === removeDay) { } else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) {
batch.delete(item.ref);
}
})
})
} else { console.log("ONCE A YEAR");
filteredTodos?.forEach((item) => { // for the next 5 years
for (let i = 0; i < 5; i++) {
let date = todoData?.date;
const nextMonth = addYears(date, i);
const newTodo = { ...todoData, date: nextMonth, connectedTodoId: firstTodo?.connectedTodoId };
console.log("UPDATE"); let docRef = firestore().collection("Todos").doc();
batch.update(item.ref, {...todoData, date: item.date}); batch.set(docRef, newTodo);
}) }
} }
await batch.commit(); 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 { } else {
console.log("Update"); console.log("REGULAR UPDATE");
console.log(todoData); console.log(todoData);
await firestore() await firestore()
.collection("Todos") .collection("Todos")
@ -123,3 +149,59 @@ export const useUpdateTodo = () => {
} }
}) })
} }
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);
});
// TODO: for the next connected -> filtered todos - number of weeks
for (let i = 0; i < todosToAddCycles; i++) {
dates?.forEach((dateToAdd) => {
let newTodoDate = addWeeks(dateToAdd, i);
if (compareAsc(newTodoDate, firstTodo?.date) !== 0) {
const newTodo = {...todoData, date: newTodoDate};
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();
}