mirror of
https://github.com/urosran/cally.git
synced 2025-07-17 02:25:10 +00:00
Merge branch 'dev'
This commit is contained in:
@ -73,7 +73,7 @@ const AddBrainDump = ({
|
|||||||
onPress={() => {
|
onPress={() => {
|
||||||
addBrainDump({
|
addBrainDump({
|
||||||
|
|
||||||
id: 99,
|
id: '99',
|
||||||
|
|
||||||
title: dumpTitle.trimEnd().trimStart(),
|
title: dumpTitle.trimEnd().trimStart(),
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ export const DetailedCalendar: React.FC<EventCalendarProps> = React.memo(({calen
|
|||||||
{...bodyProps}
|
{...bodyProps}
|
||||||
renderEvent={renderEvent}
|
renderEvent={renderEvent}
|
||||||
/>
|
/>
|
||||||
<View marginB-45/>
|
<View marginB-0/>
|
||||||
</CalendarContainer>
|
</CalendarContainer>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -74,7 +74,8 @@ const styles = StyleSheet.create({
|
|||||||
eventCell: {
|
eventCell: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
padding: 8,
|
paddingHorizontal: 8,
|
||||||
|
paddingBottom: 8,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
},
|
},
|
||||||
eventTitle: {
|
eventTitle: {
|
||||||
|
@ -28,7 +28,7 @@ export const InnerCalendar = () => {
|
|||||||
style={{flex: 1, backgroundColor: "#fff", borderRadius: 0, marginBottom: 0, overflow: "hidden"}}
|
style={{flex: 1, backgroundColor: "#fff", borderRadius: 0, marginBottom: 0, overflow: "hidden"}}
|
||||||
ref={calendarContainerRef}
|
ref={calendarContainerRef}
|
||||||
onLayout={onLayout}
|
onLayout={onLayout}
|
||||||
paddingB-15
|
paddingB-0
|
||||||
>
|
>
|
||||||
{calendarHeight > 0 && (
|
{calendarHeight > 0 && (
|
||||||
<EventCalendar
|
<EventCalendar
|
||||||
|
@ -567,18 +567,10 @@ export const ManuallyAddEventModal = () => {
|
|||||||
Save
|
Save
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{editEvent && (
|
|
||||||
<Button
|
|
||||||
style={styles.topBtn}
|
|
||||||
marginL-5
|
|
||||||
iconSource={() => <BinIcon/>}
|
|
||||||
onPress={showDeleteEventModal}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{/*)}*/}
|
{/*)}*/}
|
||||||
<ScrollView style={{minHeight: "85%"}}>
|
<ScrollView style={{minHeight: "81%"}}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Add event title"
|
placeholder="Add event title"
|
||||||
ref={titleRef}
|
ref={titleRef}
|
||||||
@ -788,7 +780,6 @@ export const ManuallyAddEventModal = () => {
|
|||||||
<Button
|
<Button
|
||||||
disabled
|
disabled
|
||||||
marginH-30
|
marginH-30
|
||||||
marginB-30
|
|
||||||
label="Create event from image"
|
label="Create event from image"
|
||||||
text70
|
text70
|
||||||
style={{height: 47}}
|
style={{height: 47}}
|
||||||
@ -799,7 +790,24 @@ export const ManuallyAddEventModal = () => {
|
|||||||
<CameraIcon color="white"/>
|
<CameraIcon color="white"/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{editEvent && (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={showDeleteEventModal}
|
||||||
|
style={{ marginTop: 15, marginBottom: 40, alignSelf: "center" }}
|
||||||
|
hitSlop={{left: 30, right: 30, top: 10, bottom: 10}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "#ff1637",
|
||||||
|
fontFamily: "PlusJakartaSans_500Medium",
|
||||||
|
fontSize: 15,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete Event
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
{editEvent && (
|
{editEvent && (
|
||||||
<DeleteEventDialog
|
<DeleteEventDialog
|
||||||
|
@ -652,7 +652,7 @@ export const MonthCalendar: React.FC<EventCalendarProps> = React.memo(
|
|||||||
ampm
|
ampm
|
||||||
// renderCustomDateForMonth={renderCustomDateForMonth}
|
// renderCustomDateForMonth={renderCustomDateForMonth}
|
||||||
/>
|
/>
|
||||||
<View style={{backgroundColor: 'white', height: 50, width: '100%'}}/>
|
{/*<View style={{backgroundColor: 'white', height: 50, width: '100%'}}/>*/}
|
||||||
</>
|
</>
|
||||||
|
|
||||||
);
|
);
|
||||||
@ -666,7 +666,7 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
calHeader: {
|
calHeader: {
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
paddingBottom: 60,
|
paddingBottom: 0,
|
||||||
},
|
},
|
||||||
dayModeHeader: {
|
dayModeHeader: {
|
||||||
alignSelf: "flex-start",
|
alignSelf: "flex-start",
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
Checkbox,
|
Checkbox,
|
||||||
} from "react-native-ui-lib";
|
} from "react-native-ui-lib";
|
||||||
|
|
||||||
import React, {useEffect, useState} from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useToDosContext } from "@/contexts/ToDosContext";
|
import { useToDosContext } from "@/contexts/ToDosContext";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import PointsSlider from "@/components/shared/PointsSlider";
|
import PointsSlider from "@/components/shared/PointsSlider";
|
||||||
@ -26,7 +26,7 @@ const ToDoItem = (props: {
|
|||||||
isSettings?: boolean;
|
isSettings?: boolean;
|
||||||
is7Days?: boolean;
|
is7Days?: boolean;
|
||||||
localTodos: Array<IToDo>;
|
localTodos: Array<IToDo>;
|
||||||
setLocalTodos: Function
|
setLocalTodos: Function;
|
||||||
}) => {
|
}) => {
|
||||||
const { updateToDo } = useToDosContext();
|
const { updateToDo } = useToDosContext();
|
||||||
const { data: members } = useGetFamilyMembers();
|
const { data: members } = useGetFamilyMembers();
|
||||||
@ -38,13 +38,15 @@ const ToDoItem = (props: {
|
|||||||
const [visible, setVisible] = useState<boolean>(false);
|
const [visible, setVisible] = useState<boolean>(false);
|
||||||
const [points, setPoints] = useState(props.item.points);
|
const [points, setPoints] = useState(props.item.points);
|
||||||
const [pointsModalVisible, setPointsModalVisible] = useState<boolean>(false);
|
const [pointsModalVisible, setPointsModalVisible] = useState<boolean>(false);
|
||||||
const [creator, setCreator] = useState('');
|
const [creator, setCreator] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let creatorMember = members?.find((member) => member?.uid === props.item.creatorId);
|
let creatorMember = members?.find(
|
||||||
|
(member) => member?.uid === props.item.creatorId
|
||||||
|
);
|
||||||
const fullName = `${creatorMember?.firstName ?? ""}`;
|
const fullName = `${creatorMember?.firstName ?? ""}`;
|
||||||
setCreator(fullName);
|
setCreator(fullName);
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
const handlePointsChange = (text: string) => {
|
const handlePointsChange = (text: string) => {
|
||||||
const numericValue = parseInt(text, 10);
|
const numericValue = parseInt(text, 10);
|
||||||
@ -93,15 +95,15 @@ const ToDoItem = (props: {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{showAnimation && (
|
{showAnimation && (
|
||||||
<View style={styles.animationContainer}>
|
<View style={styles.animationContainer}>
|
||||||
<View style={styles.animationOverlay}>
|
<View style={styles.animationOverlay}>
|
||||||
<Image
|
<Image
|
||||||
source={require("@/assets/animations/todoCompletedAnimation.gif")}
|
source={require("@/assets/animations/todoCompletedAnimation.gif")}
|
||||||
style={styles.animation}
|
style={styles.animation}
|
||||||
resizeMode="contain"
|
resizeMode="contain"
|
||||||
/>
|
/>
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
{visible && (
|
{visible && (
|
||||||
<AddChoreDialog
|
<AddChoreDialog
|
||||||
@ -111,20 +113,24 @@ const ToDoItem = (props: {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<View paddingB-8 row spread>
|
<View paddingB-8 row spread>
|
||||||
<Text
|
<TouchableOpacity
|
||||||
text70
|
|
||||||
style={{
|
|
||||||
textDecorationLine: props.item.done ? "line-through" : "none",
|
|
||||||
fontFamily: "Manrope_500Medium",
|
|
||||||
color: props.item.done ? "#a09f9f" : "black",
|
|
||||||
fontSize: 15,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
isTodoEditable ? setVisible(true) : null;
|
isTodoEditable ? setVisible(true) : null;
|
||||||
}}
|
}}
|
||||||
|
hitSlop={{right: 150, top:10}}
|
||||||
>
|
>
|
||||||
{props.item.title}
|
<Text
|
||||||
</Text>
|
text70
|
||||||
|
style={{
|
||||||
|
textDecorationLine: props.item.done ? "line-through" : "none",
|
||||||
|
fontFamily: "Manrope_500Medium",
|
||||||
|
color: props.item.done ? "#a09f9f" : "black",
|
||||||
|
fontSize: 15,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.item.title}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
value={props.item.done}
|
value={props.item.done}
|
||||||
containerStyle={[styles.checkbox, { borderRadius: 50 }]}
|
containerStyle={[styles.checkbox, { borderRadius: 50 }]}
|
||||||
@ -133,7 +139,11 @@ const ToDoItem = (props: {
|
|||||||
borderRadius={50}
|
borderRadius={50}
|
||||||
color="#fd1575"
|
color="#fd1575"
|
||||||
onValueChange={() => {
|
onValueChange={() => {
|
||||||
const updatedTodos = props.localTodos?.map((item) => item.id === props.item.id ? { ...item, done: !props.item.done } : item);
|
const updatedTodos = props.localTodos?.map((item) =>
|
||||||
|
item.id === props.item.id
|
||||||
|
? { ...item, done: !props.item.done }
|
||||||
|
: item
|
||||||
|
);
|
||||||
props.setLocalTodos(updatedTodos);
|
props.setLocalTodos(updatedTodos);
|
||||||
updateToDo({ id: props.item.id, done: !props.item.done });
|
updateToDo({ id: props.item.id, done: !props.item.done });
|
||||||
if (!props.item.done && isChild) {
|
if (!props.item.done && isChild) {
|
||||||
@ -209,11 +219,11 @@ const ToDoItem = (props: {
|
|||||||
</View>
|
</View>
|
||||||
<View row centerV marginL-5 marginT-2>
|
<View row centerV marginL-5 marginT-2>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontFamily: "Manrope_500Medium",
|
fontFamily: "Manrope_500Medium",
|
||||||
color: "#858585",
|
color: "#858585",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Created by: {creator}
|
Created by: {creator}
|
||||||
</Text>
|
</Text>
|
||||||
@ -231,7 +241,7 @@ const ToDoItem = (props: {
|
|||||||
borderRadius: 22,
|
borderRadius: 22,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
borderColor: member.eventColor || 'transparent'
|
borderColor: member.eventColor || "transparent",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@ -242,7 +252,7 @@ const ToDoItem = (props: {
|
|||||||
aspectRatio: 1,
|
aspectRatio: 1,
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
borderRadius: 100,
|
borderRadius: 100,
|
||||||
borderColor: member.eventColor || '#ccc',
|
borderColor: member.eventColor || "#ccc",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
|
@ -3,11 +3,15 @@ import { useDeleteNote } from "@/hooks/firebase/useDeleteNote";
|
|||||||
import { useGetNotes } from "@/hooks/firebase/useGetNotes";
|
import { useGetNotes } from "@/hooks/firebase/useGetNotes";
|
||||||
import { useUpdateNote } from "@/hooks/firebase/useUpdateNote";
|
import { useUpdateNote } from "@/hooks/firebase/useUpdateNote";
|
||||||
import { createContext, useContext, useState } from "react";
|
import { createContext, useContext, useState } from "react";
|
||||||
|
import firestore, { FirebaseFirestoreTypes } from '@react-native-firebase/firestore';
|
||||||
|
|
||||||
export interface IBrainDump {
|
export interface IBrainDump {
|
||||||
id: number;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
createdAt?: FirebaseFirestoreTypes.Timestamp;
|
||||||
|
updatedAt?: FirebaseFirestoreTypes.Timestamp;
|
||||||
|
creatorId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IBrainDumpContext {
|
interface IBrainDumpContext {
|
||||||
|
@ -43,4 +43,6 @@ export interface UserProfile {
|
|||||||
googleAccounts?: { [email: string]: GoogleAccount };
|
googleAccounts?: { [email: string]: GoogleAccount };
|
||||||
microsoftAccounts?: { [email: string]: MicrosoftAccount };
|
microsoftAccounts?: { [email: string]: MicrosoftAccount };
|
||||||
appleAccounts?: { [email: string]: AppleAccount };
|
appleAccounts?: { [email: string]: AppleAccount };
|
||||||
|
weeklyPoints?: number;
|
||||||
|
allTimePoints?: number;
|
||||||
}
|
}
|
@ -12,6 +12,8 @@ export const useCreateNote = () => {
|
|||||||
mutationKey: ["createNote"],
|
mutationKey: ["createNote"],
|
||||||
mutationFn: async (note: Partial<IBrainDump>) => {
|
mutationFn: async (note: Partial<IBrainDump>) => {
|
||||||
try {
|
try {
|
||||||
|
const timestamp = firestore.FieldValue.serverTimestamp();
|
||||||
|
|
||||||
if (note.id) {
|
if (note.id) {
|
||||||
const snapshot = await firestore()
|
const snapshot = await firestore()
|
||||||
.collection("BrainDumps")
|
.collection("BrainDumps")
|
||||||
@ -27,16 +29,22 @@ export const useCreateNote = () => {
|
|||||||
{
|
{
|
||||||
...note,
|
...note,
|
||||||
creatorId: currentUser?.uid,
|
creatorId: currentUser?.uid,
|
||||||
|
updatedAt: timestamp
|
||||||
},
|
},
|
||||||
{ merge: true }
|
{ merge: true }
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newDoc = firestore().collection("BrainDumps").doc();
|
const newDoc = firestore().collection("BrainDumps").doc();
|
||||||
await firestore()
|
await newDoc.set({
|
||||||
.collection("BrainDumps")
|
...note,
|
||||||
.add({ ...note, id: newDoc.id, creatorId: currentUser?.uid });
|
id: newDoc.id,
|
||||||
|
creatorId: currentUser?.uid,
|
||||||
|
updatedAt: timestamp,
|
||||||
|
createdAt: timestamp
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,19 @@ export const daysOfWeek = [
|
|||||||
DAYS_OF_WEEK_ENUM.SATURDAY,
|
DAYS_OF_WEEK_ENUM.SATURDAY,
|
||||||
DAYS_OF_WEEK_ENUM.SUNDAY];
|
DAYS_OF_WEEK_ENUM.SUNDAY];
|
||||||
|
|
||||||
export const getNextDailyDates = (date) => {
|
export const getNextDailyDates = (date, includeToday) => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const dates = [];
|
const dates = [];
|
||||||
|
|
||||||
for (let weekOffset = 0; weekOffset < 52; weekOffset++) {
|
for (let weekOffset = 0; weekOffset < 52; weekOffset++) {
|
||||||
const targetDate = addWeeks(date, weekOffset);
|
const targetDate = addWeeks(date, weekOffset);
|
||||||
if (targetDate > today) {
|
|
||||||
|
if (includeToday) {
|
||||||
dates.push(targetDate);
|
dates.push(targetDate);
|
||||||
|
} else {
|
||||||
|
if (targetDate > today) {
|
||||||
|
dates.push(targetDate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,28 +51,36 @@ export const getNextWeeklyDates = (selectedDays, date) => {
|
|||||||
return dates;
|
return dates;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getNextMonthlyDates = (date) => {
|
export const getNextMonthlyDates = (date, includeToday) => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const dates = [];
|
const dates = [];
|
||||||
|
|
||||||
for (let monthOffset = 0; monthOffset < 12; monthOffset++) {
|
for (let monthOffset = 0; monthOffset < 12; monthOffset++) {
|
||||||
const targetDate = addMonths(date, monthOffset);
|
const targetDate = addMonths(date, monthOffset);
|
||||||
if (targetDate > today) {
|
if (includeToday) {
|
||||||
dates.push(targetDate);
|
dates.push(targetDate);
|
||||||
|
} else {
|
||||||
|
if (targetDate > today) {
|
||||||
|
dates.push(targetDate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dates;
|
return dates;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getNextYearlyDates = (date) => {
|
export const getNextYearlyDates = (date, includeToday) => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const dates = [];
|
const dates = [];
|
||||||
|
|
||||||
for (let yearOffset = 0; yearOffset < 5; yearOffset++) {
|
for (let yearOffset = 0; yearOffset < 5; yearOffset++) {
|
||||||
const nextYear = addYears(date, yearOffset);
|
const nextYear = addYears(date, yearOffset);
|
||||||
if (nextYear > today) {
|
if (includeToday) {
|
||||||
dates.push(nextYear);
|
dates.push(nextYear);
|
||||||
|
} else {
|
||||||
|
if (nextYear > today) {
|
||||||
|
dates.push(nextYear);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,13 +105,13 @@ export const useCreateTodo = () => {
|
|||||||
|
|
||||||
let nextDates;
|
let nextDates;
|
||||||
if (todoData.repeatType === REPEAT_TYPE.DAILY) {
|
if (todoData.repeatType === REPEAT_TYPE.DAILY) {
|
||||||
nextDates = getNextDailyDates(todoData.date);
|
nextDates = getNextDailyDates(todoData.date, false);
|
||||||
} else if (todoData.repeatType === REPEAT_TYPE.EVERY_WEEK) {
|
} else if (todoData.repeatType === REPEAT_TYPE.EVERY_WEEK) {
|
||||||
nextDates = getNextWeeklyDates(todoData.repeatDays, todoData.date);
|
nextDates = getNextWeeklyDates(todoData.repeatDays, todoData.date);
|
||||||
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_MONTH) {
|
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_MONTH) {
|
||||||
nextDates = getNextMonthlyDates(todoData.date);
|
nextDates = getNextMonthlyDates(todoData.date, false);
|
||||||
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) {
|
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) {
|
||||||
nextDates = getNextYearlyDates(todoData.date);
|
nextDates = getNextYearlyDates(todoData.date, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const todosRef = firestore().collection("Todos");
|
const todosRef = firestore().collection("Todos");
|
||||||
|
@ -18,6 +18,9 @@ export const useGetNotes = () => {
|
|||||||
|
|
||||||
return snapshot.docs.map((doc) => ({
|
return snapshot.docs.map((doc) => ({
|
||||||
...doc.data(),
|
...doc.data(),
|
||||||
|
id: doc.id,
|
||||||
|
createdAt: doc.data().createdAt,
|
||||||
|
updatedAt: doc.data().updatedAt,
|
||||||
})) as IBrainDump[];
|
})) as IBrainDump[];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching braindumps:", error);
|
console.error("Error fetching braindumps:", error);
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
import firestore from "@react-native-firebase/firestore";
|
import firestore from "@react-native-firebase/firestore";
|
||||||
import {IToDo, REPEAT_TYPE} from "@/hooks/firebase/types/todoData";
|
import { IToDo, REPEAT_TYPE } from "@/hooks/firebase/types/todoData";
|
||||||
import {addDays, addMonths, addWeeks, addYears, compareAsc, format, subDays} from "date-fns";
|
import { compareAsc, format } from "date-fns";
|
||||||
import {daysOfWeek, resolveTodoAlternatingAssignees} from "@/hooks/firebase/useCreateTodo";
|
import {
|
||||||
import {useAuthContext} from "@/contexts/AuthContext";
|
getNextDailyDates,
|
||||||
|
getNextMonthlyDates,
|
||||||
|
getNextWeeklyDates,
|
||||||
|
getNextYearlyDates
|
||||||
|
} from "@/hooks/firebase/useCreateTodo";
|
||||||
|
import { useAuthContext } from "@/contexts/AuthContext";
|
||||||
|
import {UserProfile} from "@/hooks/firebase/types/profileTypes";
|
||||||
|
|
||||||
export const useUpdateTodo = () => {
|
export const useUpdateTodo = () => {
|
||||||
const { user: currentUser, profileData } = useAuthContext();
|
const { user: currentUser, profileData } = useAuthContext();
|
||||||
@ -14,9 +20,22 @@ export const useUpdateTodo = () => {
|
|||||||
mutationFn: async (todoData: Partial<IToDo>) => {
|
mutationFn: async (todoData: Partial<IToDo>) => {
|
||||||
try {
|
try {
|
||||||
if (todoData.connectedTodoId) {
|
if (todoData.connectedTodoId) {
|
||||||
console.log("CONNECTED")
|
|
||||||
const snapshot = await firestore()
|
let nextDates;
|
||||||
.collection("Todos")
|
if (todoData.repeatType === REPEAT_TYPE.DAILY) {
|
||||||
|
nextDates = getNextDailyDates(todoData.date, true);
|
||||||
|
} 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, true);
|
||||||
|
} else if (todoData.repeatType === REPEAT_TYPE.ONCE_A_YEAR) {
|
||||||
|
nextDates = getNextYearlyDates(todoData.date, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const todosRef = firestore().collection("Todos");
|
||||||
|
const batch = firestore().batch();
|
||||||
|
|
||||||
|
const snapshot = await todosRef
|
||||||
.where("connectedTodoId", "==", todoData.connectedTodoId)
|
.where("connectedTodoId", "==", todoData.connectedTodoId)
|
||||||
.get();
|
.get();
|
||||||
const connectedTodos = snapshot.docs.map((doc) => {
|
const connectedTodos = snapshot.docs.map((doc) => {
|
||||||
@ -30,135 +49,109 @@ export const useUpdateTodo = () => {
|
|||||||
};
|
};
|
||||||
}) as IToDo[];
|
}) 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 ||
|
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) =>{
|
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();
|
||||||
});
|
});
|
||||||
|
|
||||||
let firstTodo = filteredTodos?.[0];
|
// Update existing todos or create new ones
|
||||||
const batch = firestore().batch();
|
filteredTodos?.map((todo, index) => {
|
||||||
if (compareAsc(format(firstTodo?.date, 'yyyy-MM-dd'), format(todoData.date, 'yyyy-MM-dd')) !== 0 || firstTodo?.repeatType !== todoData.repeatType) {
|
const newDate = nextDates[index];
|
||||||
|
let assignee;
|
||||||
console.log("DELETE");
|
if (todoData.assignees && todoData.rotate && todoData?.assignees?.length !== 0) {
|
||||||
filteredTodos?.forEach((item) => {
|
assignee = todoData.assignees[index % todoData.assignees.length];
|
||||||
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();
|
if (newDate) {
|
||||||
} else if (firstTodo?.repeatDays !== todoData.repeatDays) {
|
const nextTodo = {
|
||||||
|
...todoData,
|
||||||
|
date: newDate,
|
||||||
|
assignees: assignee ? [assignee] : todoData.assignees
|
||||||
|
}
|
||||||
|
let docRef = todo.ref;
|
||||||
|
batch.update(docRef, nextTodo)
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
console.log("UPDATE REPEAT DAYS");
|
const existingDates = filteredTodos?.map((todo) => todo.date);
|
||||||
await updateRepeatDaysTodos(batch, todoData, firstTodo, filteredTodos)
|
nextDates
|
||||||
} else {
|
.filter((date) => !existingDates.includes(date))
|
||||||
filteredTodos?.forEach((item) => {
|
.map((date, index) => {
|
||||||
|
const newDocRef = todosRef.doc();
|
||||||
|
|
||||||
console.log("UPDATE");
|
let assignee;
|
||||||
batch.update(item.ref, {...todoData, date: item.date});
|
if (todoData.assignees && todoData.rotate && todoData?.assignees?.length !== 0) {
|
||||||
})
|
assignee = todoData.assignees[index % todoData.assignees.length];
|
||||||
await batch.commit();
|
}
|
||||||
}
|
|
||||||
|
const nextTodo = {
|
||||||
|
...todoData,
|
||||||
|
date: date,
|
||||||
|
id: newDocRef.id,
|
||||||
|
familyId: profileData?.familyId,
|
||||||
|
creatorId: currentUser?.uid,
|
||||||
|
connectedTodoId: todoData.connectedTodoId,
|
||||||
|
assignees: assignee ? [assignee] : todoData.assignees
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.set(newDocRef, nextTodo)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove unmatched todos
|
||||||
|
const unmatchedTodos = filteredTodos?.filter(
|
||||||
|
(item) => !nextDates.includes(item.date)
|
||||||
|
);
|
||||||
|
unmatchedTodos.map((item) =>
|
||||||
|
batch.delete(item.ref)
|
||||||
|
);
|
||||||
|
|
||||||
|
await batch.commit();
|
||||||
} else {
|
} else {
|
||||||
console.log("REGULAR UPDATE");
|
|
||||||
console.log(todoData);
|
let documentSnapshot = await firestore().collection("Todos").doc(todoData.id).get();
|
||||||
await firestore()
|
if (documentSnapshot.exists) {
|
||||||
.collection("Todos")
|
let todoUpdate = documentSnapshot.data() as IToDo;
|
||||||
.doc(todoData.id)
|
|
||||||
.update(todoData);
|
const userBatch = firestore().batch();
|
||||||
|
if (todoUpdate.done !== todoData.done) {
|
||||||
|
|
||||||
|
todoUpdate.assignees?.map(async (userId) => {
|
||||||
|
const userRef = firestore().collection("Profiles").doc(userId);
|
||||||
|
let userSnapshot = await userRef.get();
|
||||||
|
let userData = userSnapshot.data() as UserProfile;
|
||||||
|
|
||||||
|
if (!userData) return;
|
||||||
|
|
||||||
|
// Calculate new points
|
||||||
|
let userWeeklyPoints = userData.weeklyPoints ?? 0;
|
||||||
|
const weeklyPoints = todoData.done
|
||||||
|
? userWeeklyPoints + todoUpdate.points
|
||||||
|
: userWeeklyPoints - todoUpdate.points;
|
||||||
|
|
||||||
|
let userAllTimePoints = userData.allTimePoints ?? 0;
|
||||||
|
const allTimePoints = todoData.done
|
||||||
|
? userAllTimePoints + todoUpdate.points
|
||||||
|
: userAllTimePoints - todoUpdate.points;
|
||||||
|
|
||||||
|
// Update the user's points in Firestore
|
||||||
|
userData = {
|
||||||
|
...userData,
|
||||||
|
weeklyPoints: weeklyPoints >= 0 ? weeklyPoints : 0,
|
||||||
|
allTimePoints: allTimePoints >= 0 ? allTimePoints : 0
|
||||||
|
}
|
||||||
|
userBatch.update(userRef, userData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await firestore()
|
||||||
|
.collection("Todos")
|
||||||
|
.doc(todoData.id)
|
||||||
|
.update(todoData);
|
||||||
|
|
||||||
|
await userBatch.commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
@ -168,62 +161,4 @@ export const useUpdateTodo = () => {
|
|||||||
queryClients.invalidateQueries({queryKey: ["todos"]})
|
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();
|
|
||||||
}
|
|
Reference in New Issue
Block a user