mirror of
https://github.com/urosran/cally.git
synced 2025-07-10 15:17:17 +00:00
Merge branch 'dev'
# Conflicts: # firebase/functions/index.js
This commit is contained in:
117
app/(unauth)/birthday_page.tsx
Normal file
117
app/(unauth)/birthday_page.tsx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import { Button, Text, View, DateTimePicker } from "react-native-ui-lib";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useRouter } from "expo-router";
|
||||||
|
import { Platform, StyleSheet } from "react-native";
|
||||||
|
import { useAuthContext } from "@/contexts/AuthContext";
|
||||||
|
import firestore from "@react-native-firebase/firestore";
|
||||||
|
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
|
||||||
|
|
||||||
|
export default function BirthdayScreen() {
|
||||||
|
const router = useRouter();
|
||||||
|
const { user } = useAuthContext();
|
||||||
|
const [date, setDate] = useState(new Date());
|
||||||
|
const { mutateAsync: updateUserData } = useUpdateUserData();
|
||||||
|
|
||||||
|
const onDateChange = (event: any, selectedDate?: Date) => {
|
||||||
|
const currentDate = selectedDate || date;
|
||||||
|
setDate(currentDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleContinue = async () => {
|
||||||
|
try {
|
||||||
|
updateUserData({
|
||||||
|
newUserData: {
|
||||||
|
birthday: date,
|
||||||
|
},
|
||||||
|
}).then(() => router.push("/(unauth)/cal_sync"));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error saving birthday:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMaxDate = () => {
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 3); // Minimum age: 3 years
|
||||||
|
return date;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMinDate = () => {
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 18); // Maximum age: 18 years
|
||||||
|
return date;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView style={{ flex: 1 }}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
padding: 21,
|
||||||
|
paddingBottom: 45,
|
||||||
|
paddingTop: "20%",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View gap-13 width={"100%"} marginB-20>
|
||||||
|
<Text style={{ fontSize: 40, fontFamily: "Manrope_600SemiBold" }}>
|
||||||
|
When's your birthday?
|
||||||
|
</Text>
|
||||||
|
<Text color={"#919191"} style={{ fontSize: 20 }}>
|
||||||
|
We'll use this to celebrate your special day!
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View width={"100%"} flexG>
|
||||||
|
<DateTimePicker
|
||||||
|
value={date}
|
||||||
|
mode="date"
|
||||||
|
minimumDate={getMinDate()}
|
||||||
|
maximumDate={getMaxDate()}
|
||||||
|
onChange={(date) => {
|
||||||
|
if (date) {
|
||||||
|
const validDate = new Date(date);
|
||||||
|
if (!isNaN(validDate.getTime())) {
|
||||||
|
setDate(validDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={styles.textfield}
|
||||||
|
textAlign="center"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View flexG />
|
||||||
|
|
||||||
|
<View width={"100%"}>
|
||||||
|
<Button
|
||||||
|
label="Continue"
|
||||||
|
onPress={handleContinue}
|
||||||
|
style={{
|
||||||
|
height: 50,
|
||||||
|
}}
|
||||||
|
backgroundColor="#fd1775"
|
||||||
|
labelStyle={{
|
||||||
|
fontFamily: "PlusJakartaSans_600SemiBold",
|
||||||
|
fontSize: 16,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
textfield: {
|
||||||
|
backgroundColor: "white",
|
||||||
|
marginVertical: 100,
|
||||||
|
padding: 30,
|
||||||
|
height: 44,
|
||||||
|
borderRadius: 50,
|
||||||
|
fontFamily: "PlusJakartaSans_300Light",
|
||||||
|
fontSize: 15,
|
||||||
|
color: "#919191",
|
||||||
|
alignContent: "center",
|
||||||
|
},
|
||||||
|
});
|
@ -49,7 +49,7 @@ export default function Screen() {
|
|||||||
|
|
||||||
const debouncedRouterReplace = useCallback(
|
const debouncedRouterReplace = useCallback(
|
||||||
debounce(() => {
|
debounce(() => {
|
||||||
router.push("/(unauth)/cal_sync");
|
router.push("/(unauth)/birthday_page");
|
||||||
}, 300),
|
}, 300),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -80,11 +80,11 @@ export const DetailedCalendar: React.FC<EventCalendarProps> = React.memo(({
|
|||||||
const renderEvent = useCallback((event: any) => {
|
const renderEvent = useCallback((event: any) => {
|
||||||
const attendees = getAttendees(event);
|
const attendees = getAttendees(event);
|
||||||
return (
|
return (
|
||||||
<MemoizedEventCell
|
<MemoizedEventCell
|
||||||
event={event}
|
event={event}
|
||||||
onPress={handlePressEvent}
|
onPress={handlePressEvent}
|
||||||
attendees={attendees}
|
attendees={attendees}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}, [getAttendees, handlePressEvent]);
|
}, [getAttendees, handlePressEvent]);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
ButtonSize,
|
ButtonSize,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Colors,
|
Colors,
|
||||||
|
DateTimePicker,
|
||||||
KeyboardAwareScrollView,
|
KeyboardAwareScrollView,
|
||||||
LoaderScreen,
|
LoaderScreen,
|
||||||
Text,
|
Text,
|
||||||
@ -66,10 +67,25 @@ const SignUpPage = () => {
|
|||||||
return "20%"; // non-tablet case, regardless of orientation
|
return "20%"; // non-tablet case, regardless of orientation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getMaxDate = () => {
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 3); // Minimum age: 3 years
|
||||||
|
return date;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMinDate = () => {
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 18); // Maximum age: 18 years
|
||||||
|
return date;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const [birthday, setBirthday] = useState<Date>(getMinDate());
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const handleSignUp = async () => {
|
const handleSignUp = async () => {
|
||||||
await signUp({ email, password, firstName, lastName });
|
await signUp({ email, password, firstName, lastName, birthday });
|
||||||
|
|
||||||
if (profileData?.userType === ProfileType.FAMILY_DEVICE) {
|
if (profileData?.userType === ProfileType.FAMILY_DEVICE) {
|
||||||
router.replace("/(auth)/calendar");
|
router.replace("/(auth)/calendar");
|
||||||
@ -110,7 +126,7 @@ const SignUpPage = () => {
|
|||||||
|
|
||||||
<KeyboardAvoidingView style={{ width: "100%" }}>
|
<KeyboardAvoidingView style={{ width: "100%" }}>
|
||||||
<TextField
|
<TextField
|
||||||
marginT-30
|
marginT-17
|
||||||
autoFocus
|
autoFocus
|
||||||
placeholder="First name"
|
placeholder="First name"
|
||||||
value={firstName}
|
value={firstName}
|
||||||
@ -160,6 +176,16 @@ const SignUpPage = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<DateTimePicker
|
||||||
|
placeholder="Birthday"
|
||||||
|
value={birthday}
|
||||||
|
mode="date"
|
||||||
|
minimumDate={getMinDate()}
|
||||||
|
maximumDate={getMaxDate()}
|
||||||
|
onChange={(value) => setBirthday(value)}
|
||||||
|
style={styles.textfield}
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
centerV
|
centerV
|
||||||
style={[styles.textfield, { padding: 0, paddingHorizontal: 30 }]}
|
style={[styles.textfield, { padding: 0, paddingHorizontal: 30 }]}
|
||||||
@ -241,7 +267,7 @@ const SignUpPage = () => {
|
|||||||
{isTablet ? (
|
{isTablet ? (
|
||||||
<View height={50} />
|
<View height={50} />
|
||||||
) : (
|
) : (
|
||||||
<View flexG style={{ minHeight: 50 }} />
|
<View flexG style={{ minHeight: 65 }} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View>
|
<View>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Dialog, Button, Text, View } from "react-native-ui-lib";
|
import { Dialog, Button, Text, View, TextField } from "react-native-ui-lib";
|
||||||
import { StyleSheet } from "react-native";
|
import { StyleSheet } from "react-native";
|
||||||
import { Feather } from "@expo/vector-icons";
|
import { Feather } from "@expo/vector-icons";
|
||||||
|
|
||||||
@ -8,6 +8,8 @@ interface ConfirmationDialogProps {
|
|||||||
onDismiss: () => void;
|
onDismiss: () => void;
|
||||||
onFirstYes: () => void;
|
onFirstYes: () => void;
|
||||||
onConfirm: () => void;
|
onConfirm: () => void;
|
||||||
|
isDeleteFamily?: boolean;
|
||||||
|
householdName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
|
const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
|
||||||
@ -15,8 +17,21 @@ const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
|
|||||||
onDismiss,
|
onDismiss,
|
||||||
onFirstYes,
|
onFirstYes,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
|
isDeleteFamily,
|
||||||
|
householdName,
|
||||||
}) => {
|
}) => {
|
||||||
const [confirmationDialog, setConfirmationDialog] = useState<boolean>(false);
|
const [confirmationDialog, setConfirmationDialog] = useState<boolean>(false);
|
||||||
|
const [input, setInput] = useState<string>("");
|
||||||
|
const [isCorrect, setIsCorrect] = useState<boolean>(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInput("");
|
||||||
|
}, [onDismiss, onConfirm])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsCorrect(input === householdName);
|
||||||
|
}, [input])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -31,18 +46,33 @@ const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
|
|||||||
<Text center style={styles.title}>
|
<Text center style={styles.title}>
|
||||||
Are you sure?
|
Are you sure?
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
{isDeleteFamily ? (
|
||||||
style={{
|
<Text
|
||||||
fontSize: 18,
|
style={{
|
||||||
fontFamily: "PlusJakartaSans_700Bold",
|
fontSize: 18,
|
||||||
color: "#979797",
|
fontFamily: "PlusJakartaSans_700Bold",
|
||||||
marginBottom: 20,
|
color: "#979797",
|
||||||
}}
|
marginBottom: 20,
|
||||||
center
|
}}
|
||||||
>
|
center
|
||||||
This action will permanently delete all your data, you won't be able
|
>
|
||||||
to recover it!
|
This action will permanently delete all your family profiles and
|
||||||
</Text>
|
data, you won't be able to recover it!
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 18,
|
||||||
|
fontFamily: "PlusJakartaSans_700Bold",
|
||||||
|
color: "#979797",
|
||||||
|
marginBottom: 20,
|
||||||
|
}}
|
||||||
|
center
|
||||||
|
>
|
||||||
|
This action will permanently delete all your data, you won't be able
|
||||||
|
to recover it!
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
<View centerV></View>
|
<View centerV></View>
|
||||||
<View row right gap-8>
|
<View row right gap-8>
|
||||||
<Button
|
<Button
|
||||||
@ -69,10 +99,30 @@ const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
|
|||||||
containerStyle={styles.dialog}
|
containerStyle={styles.dialog}
|
||||||
>
|
>
|
||||||
<View center paddingH-10 paddingT-15 paddingB-5>
|
<View center paddingH-10 paddingT-15 paddingB-5>
|
||||||
<Text style={styles.title}>
|
{isDeleteFamily ? (
|
||||||
We're sorry to see you go, are you really sure you want to delete
|
<View>
|
||||||
everything?
|
<Text style={styles.title}>Deleting family</Text>
|
||||||
</Text>
|
<Text style={styles.text}>
|
||||||
|
Deleting the family will remove all profiles and data. This
|
||||||
|
cannot be undone.
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.subText}>
|
||||||
|
Type the name of your household to confirm.
|
||||||
|
</Text>
|
||||||
|
<TextField
|
||||||
|
value={input}
|
||||||
|
onChangeText={(value) => {
|
||||||
|
setInput(value);
|
||||||
|
}}
|
||||||
|
style={[styles.txtBox, { marginTop: 5 }]}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<Text style={styles.title}>
|
||||||
|
We're sorry to see you go, are you really sure you want to delete
|
||||||
|
everything?
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
<View row right gap-8 marginT-15>
|
<View row right gap-8 marginT-15>
|
||||||
<Button
|
<Button
|
||||||
label="Cancel"
|
label="Cancel"
|
||||||
@ -85,11 +135,14 @@ const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
|
|||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
label="Yes"
|
label="Yes"
|
||||||
|
disabled={!isDeleteFamily ? false : !isCorrect}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
onConfirm();
|
if(input === householdName)
|
||||||
|
onConfirm();
|
||||||
|
|
||||||
setConfirmationDialog(false);
|
setConfirmationDialog(false);
|
||||||
}}
|
}}
|
||||||
style={styles.confirmBtn}
|
style={!isDeleteFamily ? styles.confirmBtn : (isCorrect ? styles.confirmBtn : styles.confirmDisabled)}
|
||||||
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium" }}
|
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium" }}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
@ -106,6 +159,9 @@ const styles = StyleSheet.create({
|
|||||||
cancelBtn: {
|
cancelBtn: {
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
},
|
},
|
||||||
|
confirmDisabled: {
|
||||||
|
backgroundColor: "#999999"
|
||||||
|
},
|
||||||
dialog: {
|
dialog: {
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
paddingHorizontal: 25,
|
paddingHorizontal: 25,
|
||||||
@ -123,6 +179,23 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
},
|
},
|
||||||
|
subText: {
|
||||||
|
fontFamily: "PlusJakartaSans_400Regular",
|
||||||
|
fontSize: 12,
|
||||||
|
marginBottom: 0,
|
||||||
|
color: "#999999",
|
||||||
|
marginTop: 15,
|
||||||
|
},
|
||||||
|
txtBox: {
|
||||||
|
backgroundColor: "#fafafa",
|
||||||
|
borderRadius: 10,
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: "#cecece",
|
||||||
|
padding: 15,
|
||||||
|
height: 45,
|
||||||
|
fontFamily: "PlusJakartaSans_500Medium",
|
||||||
|
fontSize: 13,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default DeleteProfileDialogs;
|
export default DeleteProfileDialogs;
|
||||||
|
@ -3,6 +3,7 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Colors,
|
Colors,
|
||||||
|
DateTimePicker,
|
||||||
Dialog,
|
Dialog,
|
||||||
Image,
|
Image,
|
||||||
KeyboardAwareScrollView,
|
KeyboardAwareScrollView,
|
||||||
@ -53,6 +54,11 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
|||||||
const [firstName, setFirstName] = useState("");
|
const [firstName, setFirstName] = useState("");
|
||||||
const [lastName, setLastName] = useState("");
|
const [lastName, setLastName] = useState("");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
|
const [birthday, setBirthday] = useState<Date>(() => {
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 3);
|
||||||
|
return date;
|
||||||
|
});
|
||||||
|
|
||||||
const { profileData } = useAuthContext();
|
const { profileData } = useAuthContext();
|
||||||
|
|
||||||
@ -66,7 +72,8 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { mutateAsync: createSubUser, isLoading, isError } = useCreateSubUser();
|
const { mutateAsync: createSubUser, isLoading, isError } = useCreateSubUser();
|
||||||
const { data: familyMembers, refetch: refetchFamilyMembers } = useGetFamilyMembers(true);
|
const { data: familyMembers, refetch: refetchFamilyMembers } =
|
||||||
|
useGetFamilyMembers(true);
|
||||||
const { user } = useAuthContext();
|
const { user } = useAuthContext();
|
||||||
const {
|
const {
|
||||||
pickImage,
|
pickImage,
|
||||||
@ -77,9 +84,9 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
|||||||
} = useUploadProfilePicture(newUserId);
|
} = useUploadProfilePicture(newUserId);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
refetchFamilyMembers();
|
refetchFamilyMembers();
|
||||||
}, [refetchFamilyMembers])
|
}, [refetchFamilyMembers])
|
||||||
);
|
);
|
||||||
|
|
||||||
const parents =
|
const parents =
|
||||||
@ -115,6 +122,7 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
|||||||
firstName,
|
firstName,
|
||||||
lastName: selectedStatus === ProfileType.FAMILY_DEVICE ? "" : lastName,
|
lastName: selectedStatus === ProfileType.FAMILY_DEVICE ? "" : lastName,
|
||||||
email: email || `placeholder_${uuidv4().split("-")[0]}@family.device`,
|
email: email || `placeholder_${uuidv4().split("-")[0]}@family.device`,
|
||||||
|
birthday: birthday,
|
||||||
password: uuidv4(),
|
password: uuidv4(),
|
||||||
userType: selectedStatus as ProfileType,
|
userType: selectedStatus as ProfileType,
|
||||||
});
|
});
|
||||||
@ -146,8 +154,24 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
|||||||
setFirstName("");
|
setFirstName("");
|
||||||
setLastName("");
|
setLastName("");
|
||||||
setEmail("");
|
setEmail("");
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 3);
|
||||||
|
setBirthday(date);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const getMaxDate = () => {
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 3); // Minimum age: 3 years
|
||||||
|
return date;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMinDate = () => {
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(date.getFullYear() - 18); // Maximum age: 18 years
|
||||||
|
return date;
|
||||||
|
};
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return (
|
return (
|
||||||
<View marginB-70>
|
<View marginB-70>
|
||||||
@ -524,6 +548,24 @@ const MyGroup: React.FC<MyGroupProps> = ({
|
|||||||
blurOnSubmit={false}
|
blurOnSubmit={false}
|
||||||
returnKeyType="next"
|
returnKeyType="next"
|
||||||
/>
|
/>
|
||||||
|
<Text style={styles.jakarta12}>Birthday</Text>
|
||||||
|
{/*<DateTimePicker
|
||||||
|
editable={!isLoading}
|
||||||
|
mode="date"
|
||||||
|
minimumDate={getMinDate()}
|
||||||
|
maximumDate={getMaxDate()}
|
||||||
|
style={[styles.inputField, { paddingVertical: 0 }]}
|
||||||
|
value={birthday}
|
||||||
|
onChange={(date) => {
|
||||||
|
if (date) {
|
||||||
|
const validDate = new Date(date);
|
||||||
|
if (!isNaN(validDate.getTime())) {
|
||||||
|
setBirthday(validDate);
|
||||||
|
console.log("Selected birthday:", validDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>*/}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import * as ImagePicker from "expo-image-picker";
|
|||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Colors,
|
Colors,
|
||||||
|
DateTimePicker,
|
||||||
Image,
|
Image,
|
||||||
Picker,
|
Picker,
|
||||||
Text,
|
Text,
|
||||||
@ -25,11 +26,13 @@ import { useDeleteUser } from "@/hooks/firebase/useDeleteUser";
|
|||||||
import { useUpdateHouseholdName } from "@/hooks/firebase/useUpdateHouseholdName";
|
import { useUpdateHouseholdName } from "@/hooks/firebase/useUpdateHouseholdName";
|
||||||
import { useGetHouseholdName } from "@/hooks/firebase/useGetHouseholdName";
|
import { useGetHouseholdName } from "@/hooks/firebase/useGetHouseholdName";
|
||||||
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
|
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
|
||||||
|
import { useDeleteFamily } from "@/hooks/firebase/useDeleteFamily";
|
||||||
|
|
||||||
const MyProfile = () => {
|
const MyProfile = () => {
|
||||||
const { user, profileData } = useAuthContext();
|
const { user, profileData } = useAuthContext();
|
||||||
const { data: familyMembers } = useGetFamilyMembers();
|
const { data: familyMembers } = useGetFamilyMembers();
|
||||||
const [takenColors, setTakenColors] = useState<string[]>([]);
|
const [takenColors, setTakenColors] = useState<string[]>([]);
|
||||||
|
const { mutate: deleteFamily, isLoading } = useDeleteFamily();
|
||||||
|
|
||||||
const { data: hhName, refetch: refetchHHName } = useGetHouseholdName(
|
const { data: hhName, refetch: refetchHHName } = useGetHouseholdName(
|
||||||
profileData.familyId
|
profileData.familyId
|
||||||
@ -52,13 +55,26 @@ const MyProfile = () => {
|
|||||||
const [previousSelectedColor, setPreviousSelectedColor] = useState<string>(
|
const [previousSelectedColor, setPreviousSelectedColor] = useState<string>(
|
||||||
profileData?.eventColor ?? colorMap.pink
|
profileData?.eventColor ?? colorMap.pink
|
||||||
);
|
);
|
||||||
|
const [birthday, setBirthday] = useState<Date>(() => {
|
||||||
|
if (profileData?.birthday) {
|
||||||
|
if (profileData.birthday.toDate) {
|
||||||
|
return profileData.birthday.toDate();
|
||||||
|
}
|
||||||
|
const date = new Date(profileData.birthday);
|
||||||
|
return isNaN(date.getTime()) ? new Date() : date;
|
||||||
|
}
|
||||||
|
return new Date();
|
||||||
|
});
|
||||||
|
|
||||||
const [showDeleteDialog, setShowDeleteDialog] = useState<boolean>(false);
|
const [showDeleteDialog, setShowDeleteDialog] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [isDeleteFamily, setIsDeleteFamily] = useState<boolean>(false);
|
||||||
|
|
||||||
const handleHideDeleteDialog = () => {
|
const handleHideDeleteDialog = () => {
|
||||||
setShowDeleteDialog(false);
|
setShowDeleteDialog(false);
|
||||||
};
|
};
|
||||||
const handleShowDeleteDialog = () => {
|
const handleShowDeleteDialog = (isFamily: boolean) => {
|
||||||
|
setIsDeleteFamily(isFamily);
|
||||||
setShowDeleteDialog(true);
|
setShowDeleteDialog(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -91,18 +107,14 @@ const MyProfile = () => {
|
|||||||
debouncedUserDataUpdate();
|
debouncedUserDataUpdate();
|
||||||
}, [timeZone, lastName, firstName]);
|
}, [timeZone, lastName, firstName]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
handleUpdateHouseholdName();
|
|
||||||
}, [householdName]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (familyMembers) {
|
if (familyMembers) {
|
||||||
const colors = familyMembers
|
const colors = familyMembers
|
||||||
.filter(member => member?.eventColor && member.uid !== user?.uid)
|
.filter((member) => member?.eventColor && member.uid !== user?.uid)
|
||||||
.map(member => member.eventColor!);
|
.map((member) => member.eventColor!);
|
||||||
setTakenColors(colors);
|
setTakenColors(colors);
|
||||||
}
|
}
|
||||||
}, [familyMembers]);
|
}, [familyMembers]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (profileData) {
|
if (profileData) {
|
||||||
@ -111,6 +123,16 @@ const MyProfile = () => {
|
|||||||
setTimeZone(
|
setTimeZone(
|
||||||
profileData.timeZone || Localization.getCalendars()[0].timeZone!
|
profileData.timeZone || Localization.getCalendars()[0].timeZone!
|
||||||
);
|
);
|
||||||
|
if (profileData?.birthday) {
|
||||||
|
if (profileData.birthday.toDate) {
|
||||||
|
setBirthday(profileData.birthday.toDate());
|
||||||
|
} else {
|
||||||
|
const date = new Date(profileData.birthday);
|
||||||
|
if (!isNaN(date.getTime())) {
|
||||||
|
setBirthday(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [profileData]);
|
}, [profileData]);
|
||||||
|
|
||||||
@ -161,6 +183,19 @@ const MyProfile = () => {
|
|||||||
debouncedUpdateUserData(color);
|
debouncedUpdateUserData(color);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteFamily = () => {
|
||||||
|
if(profileData?.familyId){
|
||||||
|
deleteFamily({familyId: profileData?.familyId}, {
|
||||||
|
onSuccess: () => {
|
||||||
|
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.log("from delete fam:\n" + error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const debouncedUpdateUserData = useCallback(
|
const debouncedUpdateUserData = useCallback(
|
||||||
debounce(async (color: string) => {
|
debounce(async (color: string) => {
|
||||||
try {
|
try {
|
||||||
@ -240,6 +275,7 @@ const MyProfile = () => {
|
|||||||
onChangeText={async (value) => {
|
onChangeText={async (value) => {
|
||||||
setHouseholdName(value);
|
setHouseholdName(value);
|
||||||
}}
|
}}
|
||||||
|
onEndEditing={() => handleUpdateHouseholdName()}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -267,6 +303,27 @@ const MyProfile = () => {
|
|||||||
setLastName(value);
|
setLastName(value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Text text80 marginT-10 marginB-7 style={styles.label}>
|
||||||
|
Birthday
|
||||||
|
</Text>
|
||||||
|
<DateTimePicker
|
||||||
|
style={styles.txtBox}
|
||||||
|
mode="date"
|
||||||
|
value={birthday}
|
||||||
|
onChange={(date) => {
|
||||||
|
if (date) {
|
||||||
|
const validDate = new Date(date);
|
||||||
|
if (!isNaN(validDate.getTime())) {
|
||||||
|
setBirthday(validDate);
|
||||||
|
updateUserData({
|
||||||
|
newUserData: {
|
||||||
|
birthday: validDate,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Text text80 marginT-10 marginB-7 style={styles.label}>
|
<Text text80 marginT-10 marginB-7 style={styles.label}>
|
||||||
Email address
|
Email address
|
||||||
</Text>
|
</Text>
|
||||||
@ -284,36 +341,83 @@ const MyProfile = () => {
|
|||||||
Color Preference
|
Color Preference
|
||||||
</Text>
|
</Text>
|
||||||
<View row spread>
|
<View row spread>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.pink)} disabled={takenColors.includes(colorMap.pink)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.pink) ? 0.1 : 1}]} backgroundColor={colorMap.pink}>
|
onPress={() => handleChangeColor(colorMap.pink)}
|
||||||
|
disabled={takenColors.includes(colorMap.pink)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{ opacity: takenColors.includes(colorMap.pink) ? 0.1 : 1 },
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.pink}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.pink && (
|
{selectedColor == colorMap.pink && (
|
||||||
<AntDesign name="check" size={30} color="white" />
|
<AntDesign name="check" size={30} color="white" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightPink)} disabled={takenColors.includes(colorMap.lightPink)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightPink) ? 0.1 : 1}]} backgroundColor={colorMap.lightPink}>
|
onPress={() => handleChangeColor(colorMap.lightPink)}
|
||||||
|
disabled={takenColors.includes(colorMap.lightPink)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{ opacity: takenColors.includes(colorMap.lightPink) ? 0.1 : 1 },
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.lightPink}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.lightPink && (
|
{selectedColor == colorMap.lightPink && (
|
||||||
<AntDesign name="check" size={30} color="black" />
|
<AntDesign name="check" size={30} color="black" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.orange)} disabled={takenColors.includes(colorMap.orange)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.orange) ? 0.1 : 1}]} backgroundColor={colorMap.orange}>
|
onPress={() => handleChangeColor(colorMap.orange)}
|
||||||
|
disabled={takenColors.includes(colorMap.orange)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{ opacity: takenColors.includes(colorMap.orange) ? 0.1 : 1 },
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.orange}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.orange && (
|
{selectedColor == colorMap.orange && (
|
||||||
<AntDesign name="check" size={30} color="white" />
|
<AntDesign name="check" size={30} color="white" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightOrange)} disabled={takenColors.includes(colorMap.lightOrange)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightOrange) ? 0.1 : 1}]} backgroundColor={colorMap.lightOrange}>
|
onPress={() => handleChangeColor(colorMap.lightOrange)}
|
||||||
|
disabled={takenColors.includes(colorMap.lightOrange)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{
|
||||||
|
opacity: takenColors.includes(colorMap.lightOrange) ? 0.1 : 1,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.lightOrange}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.lightOrange && (
|
{selectedColor == colorMap.lightOrange && (
|
||||||
<AntDesign name="check" size={30} color="black" />
|
<AntDesign name="check" size={30} color="black" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.green)}disabled={takenColors.includes(colorMap.green)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.green) ? 0.1 : 1}]} backgroundColor={colorMap.green}>
|
onPress={() => handleChangeColor(colorMap.green)}
|
||||||
|
disabled={takenColors.includes(colorMap.green)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{ opacity: takenColors.includes(colorMap.green) ? 0.1 : 1 },
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.green}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.green && (
|
{selectedColor == colorMap.green && (
|
||||||
<AntDesign name="check" size={30} color="white" />
|
<AntDesign name="check" size={30} color="white" />
|
||||||
)}
|
)}
|
||||||
@ -321,36 +425,85 @@ const MyProfile = () => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<View row spread marginT-10>
|
<View row spread marginT-10>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightGreen)} disabled={takenColors.includes(colorMap.lightGreen)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightGreen) ? 0.1 : 1}]} backgroundColor={colorMap.lightGreen}>
|
onPress={() => handleChangeColor(colorMap.lightGreen)}
|
||||||
|
disabled={takenColors.includes(colorMap.lightGreen)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{
|
||||||
|
opacity: takenColors.includes(colorMap.lightGreen) ? 0.1 : 1,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.lightGreen}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.lightGreen && (
|
{selectedColor == colorMap.lightGreen && (
|
||||||
<AntDesign name="check" size={30} color="black" />
|
<AntDesign name="check" size={30} color="black" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.teal)} disabled={takenColors.includes(colorMap.teal)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.teal) ? 0.1 : 1}]} backgroundColor={colorMap.teal}>
|
onPress={() => handleChangeColor(colorMap.teal)}
|
||||||
|
disabled={takenColors.includes(colorMap.teal)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{ opacity: takenColors.includes(colorMap.teal) ? 0.1 : 1 },
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.teal}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.teal && (
|
{selectedColor == colorMap.teal && (
|
||||||
<AntDesign name="check" size={30} color="white" />
|
<AntDesign name="check" size={30} color="white" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightTeal)} disabled={takenColors.includes(colorMap.lightTeal)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightTeal) ? 0.1 : 1}]} backgroundColor={colorMap.lightTeal}>
|
onPress={() => handleChangeColor(colorMap.lightTeal)}
|
||||||
|
disabled={takenColors.includes(colorMap.lightTeal)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{ opacity: takenColors.includes(colorMap.lightTeal) ? 0.1 : 1 },
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.lightTeal}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.lightTeal && (
|
{selectedColor == colorMap.lightTeal && (
|
||||||
<AntDesign name="check" size={30} color="black" />
|
<AntDesign name="check" size={30} color="black" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.purple)} disabled={takenColors.includes(colorMap.purple)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.purple) ? 0.1 : 1}]} backgroundColor={colorMap.purple}>
|
onPress={() => handleChangeColor(colorMap.purple)}
|
||||||
|
disabled={takenColors.includes(colorMap.purple)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{ opacity: takenColors.includes(colorMap.purple) ? 0.1 : 1 },
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.purple}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.purple && (
|
{selectedColor == colorMap.purple && (
|
||||||
<AntDesign name="check" size={30} color="white" />
|
<AntDesign name="check" size={30} color="white" />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => handleChangeColor(colorMap.lightPurple)} disabled={takenColors.includes(colorMap.lightPurple)}>
|
<TouchableOpacity
|
||||||
<View style={[styles.colorBox, {opacity: takenColors.includes(colorMap.lightPurple) ? 0.1 : 1}]} backgroundColor={colorMap.lightPurple}>
|
onPress={() => handleChangeColor(colorMap.lightPurple)}
|
||||||
|
disabled={takenColors.includes(colorMap.lightPurple)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.colorBox,
|
||||||
|
{
|
||||||
|
opacity: takenColors.includes(colorMap.lightPurple) ? 0.1 : 1,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
backgroundColor={colorMap.lightPurple}
|
||||||
|
>
|
||||||
{selectedColor == colorMap.lightPurple && (
|
{selectedColor == colorMap.lightPurple && (
|
||||||
<AntDesign name="check" size={30} color="black" />
|
<AntDesign name="check" size={30} color="black" />
|
||||||
)}
|
)}
|
||||||
@ -393,7 +546,7 @@ const MyProfile = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={handleShowDeleteDialog}
|
onPress={() => handleShowDeleteDialog(false)}
|
||||||
style={{ marginTop: 10, alignSelf: "center" }}
|
style={{ marginTop: 10, alignSelf: "center" }}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
@ -406,13 +559,40 @@ const MyProfile = () => {
|
|||||||
Delete Profile
|
Delete Profile
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
{profileData?.userType === ProfileType.PARENT && (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => handleShowDeleteDialog(true)}
|
||||||
|
style={{ marginTop: 20, alignSelf: "center" }}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "#ff1637",
|
||||||
|
fontFamily: "PlusJakartaSans_500Medium",
|
||||||
|
fontSize: 15,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete Family
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
<DeleteProfileDialogs
|
<DeleteProfileDialogs
|
||||||
onFirstYes={() => {
|
onFirstYes={() => {
|
||||||
setShowDeleteDialog(false);
|
setShowDeleteDialog(false);
|
||||||
}}
|
}}
|
||||||
visible={showDeleteDialog}
|
visible={showDeleteDialog}
|
||||||
onDismiss={handleHideDeleteDialog}
|
onDismiss={handleHideDeleteDialog}
|
||||||
onConfirm={() => deleteAsync({})}
|
onConfirm={() => {
|
||||||
|
if(isDeleteFamily)
|
||||||
|
//deletes family
|
||||||
|
handleDeleteFamily();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//deletes profile
|
||||||
|
deleteAsync({});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
isDeleteFamily={isDeleteFamily}
|
||||||
|
householdName={householdName}
|
||||||
/>
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
@ -60,7 +60,6 @@ const styles = StyleSheet.create({
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
},
|
},
|
||||||
initialsCircle: {
|
initialsCircle: {
|
||||||
backgroundColor: '#ccc',
|
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
borderRadius: 100, // Circular shape
|
borderRadius: 100, // Circular shape
|
||||||
|
32
hooks/firebase/useDeleteFamily.ts
Normal file
32
hooks/firebase/useDeleteFamily.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { useAuthContext } from "@/contexts/AuthContext";
|
||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import functions from '@react-native-firebase/functions';
|
||||||
|
import { Alert } from 'react-native';
|
||||||
|
|
||||||
|
export const useDeleteFamily = () => {
|
||||||
|
const { user } = useAuthContext();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationKey: ["deleteFamily"],
|
||||||
|
mutationFn: async ({ familyId }: { familyId: string }) => {
|
||||||
|
if (!user) {
|
||||||
|
throw new Error('User must be logged in');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const deleteFamilyFunction = functions().httpsCallable('deleteFamily');
|
||||||
|
const result = await deleteFamilyFunction({ familyId });
|
||||||
|
return result.data;
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.code === 'permission-denied') {
|
||||||
|
Alert.alert('Error', 'Only parents can delete families');
|
||||||
|
} else if (error.code === 'unauthenticated') {
|
||||||
|
Alert.alert('Error', 'Please log in to perform this action');
|
||||||
|
} else {
|
||||||
|
Alert.alert('Error', 'Failed to delete family. Please try again.');
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
@ -16,11 +16,13 @@ export const useSignUp = () => {
|
|||||||
password,
|
password,
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
|
birthday
|
||||||
}: {
|
}: {
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
birthday: Date;
|
||||||
}) => {
|
}) => {
|
||||||
setRedirectOverride(true)
|
setRedirectOverride(true)
|
||||||
|
|
||||||
@ -35,6 +37,7 @@ export const useSignUp = () => {
|
|||||||
lastName: lastName,
|
lastName: lastName,
|
||||||
familyId: uuidv4(),
|
familyId: uuidv4(),
|
||||||
timeZone: Localization.getCalendars()[0].timeZone,
|
timeZone: Localization.getCalendars()[0].timeZone,
|
||||||
|
birthday: birthday
|
||||||
},
|
},
|
||||||
customUser: res.user,
|
customUser: res.user,
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,6 @@ export const useUpdateHouseholdName = () => {
|
|||||||
familyId: string;
|
familyId: string;
|
||||||
name: string;
|
name: string;
|
||||||
}) => {
|
}) => {
|
||||||
console.log("Mutation function called with data:", { familyId, name });
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Reference to the Households collection
|
// Reference to the Households collection
|
||||||
@ -25,11 +24,9 @@ export const useUpdateHouseholdName = () => {
|
|||||||
if (!snapshot.empty) {
|
if (!snapshot.empty) {
|
||||||
// If a household with the familyId exists, update the name
|
// If a household with the familyId exists, update the name
|
||||||
const docId = snapshot.docs[0].id;
|
const docId = snapshot.docs[0].id;
|
||||||
console.log(`Household found with ID ${docId}, updating name...`);
|
|
||||||
|
|
||||||
await householdRef.doc(docId).update({ name });
|
await householdRef.doc(docId).update({ name });
|
||||||
|
|
||||||
console.log("Household name updated successfully.");
|
|
||||||
} else {
|
} else {
|
||||||
// If no household exists, create a new one with familyId and name
|
// If no household exists, create a new one with familyId and name
|
||||||
console.log("No household found, creating a new one...");
|
console.log("No household found, creating a new one...");
|
||||||
|
Reference in New Issue
Block a user