additional hooks

This commit is contained in:
ivic00
2024-08-22 22:02:43 +02:00
parent 55a3091023
commit 0a862e7a8c
14 changed files with 3376 additions and 2999 deletions

View File

@ -1,47 +1,26 @@
import React, {useEffect, useState} from "react"; import React, { useEffect, useState } from "react";
import {Button, TextInput} from "react-native"; import { Button, TextInput } from "react-native";
import {Checkbox, Picker, TextField, View, Text} from "react-native-ui-lib"; import { Checkbox, Picker, TextField, View, Text } from "react-native-ui-lib";
import useAuth from "@/hooks/firebase/useAuth"; import { useCreateSubUser } from "@/hooks/firebase/useCreateSubUser";
import useChildren from "@/hooks/firebase/useChildren"; import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import useCaregivers from "@/hooks/firebase/useCaregivers"; import { uuidv4 } from "@firebase/util";
import {useCreateSubUser} from "@/hooks/firebase/useCreateSubUser"; import { useGetChildrenByParentId } from "@/hooks/firebase/useGetChildrenByParentId";
import {UserProfile} from "@/hooks/firebase/types/profileTypes"; import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import {uuidv4} from "@firebase/util"; import SignInPage from "../../../components/pages/main/SignInPage";
import {useGetChildrenByParentId} from "@/hooks/firebase/useGetChildrenByParentId"; import Entry from "@/components/pages/main/Entry";
import {ProfileType, useAuthContext} from "@/contexts/AuthContext"; import { useSignUp } from "@/hooks/firebase/useSignUp";
import { useSignOut } from "@/hooks/firebase/useSignOut";
const Screen: React.FC = () => { const Screen: React.FC = () => {
const {user, profileType, profileData} = useAuthContext() const { user, profileType, profileData } = useAuthContext();
const { const { data: children } = useGetChildrenByParentId();
email,
setEmail,
password,
setPassword,
handleLogin,
handleSignOut,
handleProfileTypeSelection,
handleRegister,
} = useAuth();
const { const { mutateAsync: createSubUser } = useCreateSubUser();
child, const { mutateAsync: signOut } = useSignOut();
setChild,
} = useChildren(user);
const {data: children} = useGetChildrenByParentId()
const {
caregivers,
caregiver,
setCaregiver,
fetchCaregivers,
} = useCaregivers();
const {mutateAsync: createSubUser} = useCreateSubUser()
const createNewSubUser = async (userProfile: UserProfile) => { const createNewSubUser = async (userProfile: UserProfile) => {
await createSubUser({...userProfile, email: `${uuidv4()}@test.com`}) await createSubUser({ ...userProfile, email: `${uuidv4()}@test.com` });
// createSubUser({ // createSubUser({
// email, // email,
// password, // password,
@ -50,75 +29,7 @@ const Screen: React.FC = () => {
// contact: "+381628334", // contact: "+381628334",
// ...child // ...child
// }) // })
await fetchCaregivers(); };
}
useEffect(() => {
if (user) {
fetchCaregivers();
}
}, [user]);
const [isParent, setIsParent] = useState<boolean>(false);
const [isChild, setIsChild] = useState<boolean>(false);
const [isCaregiver, setIsCaregiver] = useState<boolean>(false);
useEffect(() => {
if (isParent) handleProfileTypeSelection("parent");
if (isChild) handleProfileTypeSelection("child");
if (isCaregiver) handleProfileTypeSelection("caregiver");
}, [isParent, isChild, isCaregiver]);
const renderLogin = () => (
<View marginH-20>
<TextInput placeholder="Email" value={email} onChangeText={setEmail}/>
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button title="Login" onPress={handleLogin}/>
<Button title="Register" onPress={handleRegister}/>
<Text>Choose Profile Type:</Text>
<Checkbox
label="Parent"
value={isParent}
onValueChange={(value) => {
setIsParent(value);
if (value) {
setIsChild(false);
setIsCaregiver(false);
}
}}
/>
<Checkbox
label="Child"
value={isChild}
onValueChange={(value) => {
setIsChild(value);
if (value) {
setIsParent(false);
setIsCaregiver(false);
}
}}
/>
<Checkbox
label="Caregiver"
value={isCaregiver}
onValueChange={(value) => {
setIsCaregiver(value);
if (value) {
setIsParent(false);
setIsChild(false);
}
}}
/>
</View>
);
console.log(profileType, profileData)
return ( return (
<View> <View>
@ -127,94 +38,10 @@ const Screen: React.FC = () => {
{profileType === ProfileType.PARENT && <Text>Parent</Text>} {profileType === ProfileType.PARENT && <Text>Parent</Text>}
{profileType === ProfileType.CHILD && <Text>Child</Text>} {profileType === ProfileType.CHILD && <Text>Child</Text>}
{profileType === ProfileType.CAREGIVER && <Text>Caregiver</Text>} {profileType === ProfileType.CAREGIVER && <Text>Caregiver</Text>}
<Button title="Sign Out" onPress={handleSignOut}/> <Button title="Sign Out" onPress={async() => {await signOut()}} />
<TextField
placeholder={"Child Name"}
floatingPlaceholder
value={child.name}
onChangeText={(value) =>
setChild((prevChild) => ({
...prevChild,
name: value,
}))
}
enableErrors
validate={["required", (value: string) => value.length > 6]}
validationMessage={[
"Field is required",
"Name is too short",
]}
showCharCounter
maxLength={30}
/>
<Button
title="Add Child"
onPress={() => {
createNewSubUser(child);
}}
/>
<TextField
placeholder={"Caregiver Name"}
floatingPlaceholder
value={caregiver.name}
onChangeText={(value) =>
setCaregiver((prevCaregiver) => ({
...prevCaregiver,
name: value,
}))
}
enableErrors
validate={["required", (value: string) => value.length > 6]}
validationMessage={["Field is required"]}
showCharCounter
maxLength={30}
/>
<TextField
placeholder={"Caregiver Contact"}
floatingPlaceholder
value={caregiver.contact}
onChangeText={(value) =>
setCaregiver((prevCaregiver) => ({
...prevCaregiver,
contact: value,
}))
}
enableErrors
validate={[
"number",
"required",
(value: string) => value.length > 9,
]}
validationMessage={["Field is required"]}
showCharCounter
maxLength={30}
/>
<Button
title="Add Caregiver"
onPress={() => {
createNewSubUser(caregiver);
}}
/>
<View margin-20>
<Text>Children:</Text>
{children?.map((child) => (
<View key={child.name} row>
<Text>Name: {child.name} </Text>
<Picker label="Pick Caregiver">
{caregivers.map((item) => (
<Picker.Item
key={item.name}
label={item.name}
value={item.name}
/>
))}
</Picker>
</View>
))}
</View>
</View> </View>
) : ( ) : (
renderLogin() <Entry />
)} )}
</View> </View>
); );

View File

@ -0,0 +1,30 @@
import { View, Text } from "react-native-ui-lib";
import React, { useState } from "react";
import SignUpPage from "./SignUpPage";
import SignInPage from "./SignInPage";
import { useSignUp } from "@/hooks/firebase/useSignUp";
const Entry = () => {
const [isRegister, setIsRegister] = useState<boolean>(false);
const {mutateAsync: signUp} = useSignUp();
const setRegister = () => {
setIsRegister(true);
};
const unsetRegister = () => {
setIsRegister(false);
};
return (
<View>
{isRegister ? (
<SignUpPage
unsetRegister={unsetRegister}
/>
) : (
<SignInPage setRegister={setRegister} />
)}
</View>
);
};
export default Entry;

View File

@ -0,0 +1,41 @@
import { View, Text, Button } from "react-native-ui-lib";
import { TextInput } from "react-native";
import React, { useState } from "react";
import { useSignIn } from "@/hooks/firebase/useSignIn";
const SignInPage = (props: {
setRegister: () => any;
}) => {
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const { mutateAsync: signIn } = useSignIn();
const handleSignIn = async () => {
await signIn({email, password});
}
return (
<View marginH-20>
<TextInput placeholder="Email" value={email} onChangeText={setEmail} />
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button label="Login" onPress={handleSignIn} />
<Text>Don't have an account?</Text>
<Button
onPress={props.setRegister}
label="Sign Up"
link
padding-0
margin-0
left
/>
</View>
);
};
export default SignInPage;

View File

@ -0,0 +1,83 @@
import { TextInput } from "react-native";
import React, { useState } from "react";
import { Checkbox, Button, View, Text } from "react-native-ui-lib";
import { useSignUp } from "@/hooks/firebase/useSignUp";
import { ProfileType } from "@/contexts/AuthContext";
const SignUpPage = (props: { unsetRegister: () => any }) => {
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [isParent, setIsParent] = useState<boolean>(true);
const [isChild, setIsChild] = useState<boolean>(false);
const [isCaregiver, setIsCaregiver] = useState<boolean>(false);
const [profileType, setProfileType] = useState<ProfileType>(
ProfileType.PARENT
);
const { mutateAsync: signUp } = useSignUp();
const handleSignUp = async () => {
await signUp({ email, password });
};
return (
<View marginH-20>
<TextInput placeholder="Email" value={email} onChangeText={setEmail} />
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button label="Register" onPress={handleSignUp} />
<Text>Choose Profile Type:</Text>
<Checkbox
label="Parent"
value={isParent}
onValueChange={(value) => {
setIsParent(value);
setProfileType(ProfileType.PARENT);
if (value) {
setIsChild(false);
setIsCaregiver(false);
}
}}
/>
<Checkbox
label="Child"
value={isChild}
onValueChange={(value) => {
setIsChild(value);
setProfileType(ProfileType.CHILD);
if (value) {
setIsParent(false);
setIsCaregiver(false);
}
}}
/>
<Checkbox
label="Caregiver"
value={isCaregiver}
onValueChange={(value) => {
setIsCaregiver(value);
setProfileType(ProfileType.CAREGIVER);
if (value) {
setIsParent(false);
setIsChild(false);
}
}}
/>
<Text>
Already have an account?
<Button
label="Sign In"
margin-0
link
text200
onPress={props.unsetRegister}
/>
</Text>
</View>
);
};
export default SignUpPage;

View File

@ -1,136 +0,0 @@
import {useState} from "react";
import {useMutation} from "react-query";
import auth from "@react-native-firebase/auth";
import firestore from "@react-native-firebase/firestore";
import {User,} from "./types/profileTypes";
import {useSignUp} from "@/hooks/firebase/useSignUp";
type ProfileType = "parent" | "child" | "caregiver" | null;
const useAuth = () => {
const createUserMutation = useMutation(() =>
auth().createUserWithEmailAndPassword(email, password)
);
const signInMutation = useMutation(() =>
auth().signInWithEmailAndPassword(email, password)
);
const loginMutation = useMutation(() =>
auth().signInWithEmailAndPassword(email, password)
);
const signOutMutation = useMutation(() => auth().signOut());
const {mutateAsync: signUp } = useSignUp()
/*const setProfileDataMutation = useMutation((profileData) => {
const currentUser = auth().currentUser;
if (currentUser) {
return firestore()
.collection("Profiles")
.doc(currentUser.uid)
.set(profileData);
}
});*/
const [user, setUser] = useState<User | null>(null);
const [profileType, setProfileType] = useState<ProfileType>(null);
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const handleRegister = async () => {
try {
await signUp({email, password})
// await createUserMutation.mutateAsync();
console.log("User registered!");
// await signInMutation.mutateAsync();
// console.log("User signed in!");
/*let profileData: ParentProfile | ChildProfile | CaregiverProfile;
switch (profileType) {
case "parent":
profileData = {
userType: "parent",
name: "",
childrenIds: [],
} as ParentProfile;
break;
case "child":
profileData = {
userType: "child",
name: "",
birthday: new Date(),
parentId: "X",
} as ChildProfile;
break;
case "caregiver":
profileData = {
userType: "caregiver",
name: "Nanny Nannersen",
contact: "5523123",
} as CaregiverProfile;
break;
default:
throw new Error("Invalid profile type");
}
const currentUser = auth().currentUser;
if (currentUser) {
await firestore()
.collection("Profiles")
.doc(currentUser.uid)
.set(profileData);
console.log("Profile document added!");
}*/
} catch (error) {
console.error("Error during registration: ", error);
}
};
const handleLogin = async () => {
try {
await loginMutation.mutateAsync();
console.log("User signed in!");
} catch (error) {
console.error("Error during sign in:", error);
}
};
const handleSignOut = async () => {
try {
await signOutMutation.mutateAsync();
console.log("User signed out!");
} catch (error) {
console.error("Error during sign out:", error);
}
};
const handleProfileTypeSelection = async (type: ProfileType) => {
if (user) {
setProfileType(type);
try {
await firestore()
.collection("Profiles")
.doc(user.uid)
.set({profileType: type}, {merge: true});
} catch (error) {
console.error("Error saving profile type:", error);
}
}
};
return {
user,
profileType,
email,
setEmail,
password,
setPassword,
handleLogin,
handleSignOut,
handleProfileTypeSelection,
handleRegister,
};
};
export default useAuth;

View File

@ -1,61 +0,0 @@
import { useState } from "react";
import firestore from "@react-native-firebase/firestore";
import { CaregiverProfile } from "./types/profileTypes";
const useCaregivers = () => {
const [caregivers, setCaregivers] = useState<CaregiverProfile[]>([]);
const [caregiver, setCaregiver] = useState<CaregiverProfile>({
name: "",
contact: "",
userType: "caregiver",
email: "test@test.com",
password: "test@test.com"
});
const fetchCaregivers = async () => {
const caregiverProfiles = await getCaregivers();
setCaregivers(caregiverProfiles);
};
const getCaregivers = async (): Promise<CaregiverProfile[]> => {
try {
const snapshot = await firestore()
.collection("Profiles")
.where("userType", "==", "caregiver")
.get();
const caregivers: CaregiverProfile[] = snapshot.docs.map((doc) => {
const data = doc.data();
return {
...data,
} as CaregiverProfile;
});
return caregivers;
} catch (error) {
console.error("Error retrieving caregivers:", error);
return [];
}
};
const handleNewCaregiver = async (newCaregiver: CaregiverProfile) => {
try {
await firestore().collection("Profiles").add(newCaregiver);
} catch (error) {
console.error(error);
} finally {
setCaregiver((prev) => ({ ...prev, name: "", contact: "" }));
fetchCaregivers();
}
};
return {
caregivers,
caregiver,
setCaregiver,
fetchCaregivers,
handleNewCaregiver,
};
};
export default useCaregivers;

View File

@ -1,69 +0,0 @@
import { useState } from "react";
import firestore from "@react-native-firebase/firestore";
import { ChildProfile } from "./types/profileTypes";
const useChildren = (user: any) => {
const [children, setChildren] = useState<ChildProfile[]>([]);
const [child, setChild] = useState<ChildProfile>({
name: "",
birthday: new Date(),
userType: "child",
parentId: "",
password: "",
email: ""
});
const fetchChildren = async () => {
if (user) {
const childrenProfiles = await getChildrenByParentId(user.uid);
setChildren(childrenProfiles);
}
};
const getChildrenByParentId = async (
parentId: string
): Promise<ChildProfile[]> => {
try {
const snapshot = await firestore()
.collection("Profiles")
.where("userType", "==", "child")
.where("parentId", "==", parentId)
.get();
const children: ChildProfile[] = snapshot.docs.map((doc) => {
const data = doc.data();
return {
...data,
birthday: data.birthday.toDate(),
} as ChildProfile;
});
return children;
} catch (error) {
console.error("Error retrieving child users:", error);
return [];
}
};
const handleNewChild = async (newChild: ChildProfile) => {
try {
if (user) newChild.parentId = user.uid;
await firestore().collection("Profiles").add(newChild);
} catch (error) {
console.error(error);
} finally {
setChild((prev) => ({ ...prev, name: "" }));
fetchChildren();
}
};
return {
children,
child,
setChild,
fetchChildren,
handleNewChild,
};
};
export default useChildren;

View File

@ -9,9 +9,9 @@ export const useCreateSubUser = () => {
return useMutation({ return useMutation({
mutationKey: ["createSubUser"], mutationKey: ["createSubUser"],
mutationFn: async ({email, password, ...userProfile}: { email: string, password: string } & UserProfile) => { mutationFn: async ({email, ...userProfile}: { email: string } & UserProfile) => {
if(profileType === ProfileType.parent) { if(profileType === ProfileType.PARENT) {
return await functions().httpsCallable("createSubUser")({email, password, ...userProfile}) return await functions().httpsCallable("createSubUser")({email, ...userProfile})
} else { } else {
throw Error("Can't create sub-users as a non-parent.") throw Error("Can't create sub-users as a non-parent.")
} }

View File

@ -0,0 +1,14 @@
import { useMutation } from "react-query";
import firestore from "@react-native-firebase/firestore";
export const useSignUp = () => {
return useMutation({
mutationKey: ["getCaregivers"],
mutationFn: async () => {
const snapshot = await firestore()
.collection("Profiles")
.where("userType", "==", "caregiver")
.get();
},
});
};

View File

@ -0,0 +1,20 @@
import { useMutation } from "react-query";
import auth from "@react-native-firebase/auth";
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
import { ProfileType } from "@/contexts/AuthContext";
export const useSignIn = () => {
return useMutation({
mutationKey: ["signIn"],
mutationFn: async ({
email,
password,
}: {
email: string;
password: string;
}) => {
await auth().signInWithEmailAndPassword(email, password);
},
});
};

View File

@ -9,8 +9,8 @@ export const useSignUp = () => {
return useMutation({ return useMutation({
mutationKey: ["signUp"], mutationKey: ["signUp"],
mutationFn: async ({email, password}: { email: string, password: string }) => { mutationFn: async ({email, password}: { email: string, password: string }) => {
await auth().createUserWithEmailAndPassword(email, password) await auth().createUserWithEmailAndPassword(email, password);
await updateUserData({userType: ProfileType.PARENT, email, password}) await updateUserData({userType: ProfileType.PARENT, email, password});
} }
}); });
} }

View File

@ -11,6 +11,7 @@ export const useUpdateUserData = () => {
mutationFn: async (newProfileData: Partial<UserProfile>) => { mutationFn: async (newProfileData: Partial<UserProfile>) => {
if (user) { if (user) {
try { try {
console.log("yall don't even");
await firestore() await firestore()
.collection("Profiles") .collection("Profiles")
.doc(user.uid) .doc(user.uid)
@ -20,7 +21,7 @@ export const useUpdateUserData = () => {
setProfileData(profileData.data() as UserProfile) setProfileData(profileData.data() as UserProfile)
} catch (e) { } catch (e) {
console.log(e) console.error(e)
} }
} }
} }

1636
package-lock.json generated

File diff suppressed because it is too large Load Diff

4019
yarn.lock

File diff suppressed because it is too large Load Diff