- Added validation on todo creation to avoid creating todos with Every week repeat type, but no selected days

- Reworked and improved the creation of repeat todo
This commit is contained in:
Dejan
2024-12-15 15:31:55 +01:00
parent d30ed9b130
commit 4f96bb071b
2 changed files with 103 additions and 82 deletions

View File

@ -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();
}