added profile hooks

This commit is contained in:
ivic00
2024-08-09 19:38:46 +02:00
parent f6bbc94285
commit 0b6199989b
6 changed files with 390 additions and 233 deletions

View File

@ -1,211 +1,58 @@
import React, { useEffect, useState } from "react";
import { Text, Button, TextInput } from "react-native";
import firestore from "@react-native-firebase/firestore";
import auth from "@react-native-firebase/auth";
import {} from "@react-native-firebase/auth/";
import { View, TextField, ListItem, Picker } from "react-native-ui-lib";
type ProfileType = "Parent" | "Child" | "Caregiver" | null;
interface User {
uid: string;
email: string | null;
}
interface UserProfile {
userType: "parent" | "child" | "caregiver";
name: string;
}
interface ParentProfile extends UserProfile {
userType: "parent";
}
interface ChildProfile extends UserProfile {
userType: "child";
birthday: Date;
parentId: string;
}
interface CaregiverProfile extends UserProfile {
userType: "caregiver";
//assignedChildrenId: string[];
contact: string;
}
import { View, TextField, Picker, Checkbox } from "react-native-ui-lib";
import useAuth from "@/hooks/firebase/useAuth";
import useChildren from "@/hooks/firebase/useChildren";
import useCaregivers from "@/hooks/firebase/useCaregivers";
const Screen: React.FC = () => {
const [user, setUser] = useState<User | null>(null);
const [profileType, setProfileType] = useState<ProfileType>(null);
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [child, setChild] = useState<ChildProfile>({
name: "",
birthday: new Date(),
userType: "child" as const,
parentId: "",
});
const [caregiver, setCaregiver] = useState<CaregiverProfile>({
name: "",
contact: "",
userType: "caregiver",
});
const {
user,
profileType,
email,
setEmail,
password,
setPassword,
handleLogin,
handleSignOut,
handleProfileTypeSelection,
handleRegister,
} = useAuth();
const [children, setChildren] = useState<ChildProfile[]>([]);
const [caregivers, setCaregivers] = useState<CaregiverProfile[]>([]);
const {
children,
child,
setChild,
fetchChildren,
handleNewChild,
} = useChildren(user);
const {
caregivers,
caregiver,
setCaregiver,
fetchCaregivers,
handleNewCaregiver,
} = useCaregivers();
useEffect(() => {
const isDevelopment = __DEV__;
if (isDevelopment) {
firestore().useEmulator("localhost", 8080);
auth().useEmulator("http://127.0.0.1:9099");
}
const unsubscribe = auth().onAuthStateChanged(async (firebaseUser) => {
if (firebaseUser) {
const userObj: User = {
uid: firebaseUser.uid,
email: firebaseUser.email,
};
setUser(userObj);
try {
const documentSnapshot = await firestore()
.collection("Users")
.doc(firebaseUser.uid)
.get();
if (documentSnapshot.exists) {
setProfileType(documentSnapshot.data()?.profileType || null);
}
} catch (error) {
console.error("Error fetching user profile type:", error);
setProfileType(null);
}
} else {
setUser(null);
setProfileType(null);
}
});
return unsubscribe;
}, []);
const fetchChildren = async () => {
if (user) {
const childrenProfiles = await getChildrenByParentId(user.uid);
setChildren(childrenProfiles);
fetchChildren();
fetchCaregivers();
}
};
const fetchCaregivers = async () => {
const caregiverProfiles = await getCaregivers();
setCaregivers(caregiverProfiles);
};
useEffect(() => {
fetchChildren();
fetchCaregivers();
}, []);
useEffect(() => {
fetchChildren();
fetchCaregivers();
}, [user]);
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 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 handleLogin = async () => {
try {
await auth().signInWithEmailAndPassword(email, password);
console.log("User signed in!");
} catch (error) {
console.error("Error during sign in:", error);
}
};
const handleSignOut = async () => {
try {
await auth().signOut();
} catch (error) {
console.error("error during Sign out: ", error);
}
};
const handleProfileTypeSelection = (type: ProfileType) => {
if (user) {
setProfileType(type);
firestore()
.collection("Users")
.doc(user.uid)
.set({ profileType: type }, { merge: true });
}
};
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: "" }));
}
};
const handleNewCaregiver = async (newCaregiver: CaregiverProfile) => {
try {
await firestore().collection("Profiles").add(newCaregiver);
} catch (error) {
console.error(error);
} finally {
setCaregiver((prev) => ({ ...prev, name: "", contact: "" }));
}
};
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} />
@ -216,48 +63,52 @@ const Screen: React.FC = () => {
secureTextEntry
/>
<Button title="Login" onPress={handleLogin} />
<Button title="Register" onPress={handleRegister} />
<Text>Choose Profile Type:</Text>
<Button
title="Parent"
onPress={() => handleProfileTypeSelection("Parent")}
<Checkbox
label="Parent"
value={isParent}
onValueChange={(value) => {
setIsParent(value);
if (value) {
setIsChild(false);
setIsCaregiver(false);
}
}}
/>
<Button
title="Child"
onPress={() => handleProfileTypeSelection("Child")}
<Checkbox
label="Child"
value={isChild}
onValueChange={(value) => {
setIsChild(value);
if (value) {
setIsParent(false);
setIsCaregiver(false);
}
}}
/>
<Button
title="Caregiver"
onPress={() => handleProfileTypeSelection("Caregiver")}
<Checkbox
label="Caregiver"
value={isCaregiver}
onValueChange={(value) => {
setIsCaregiver(value);
if (value) {
setIsParent(false);
setIsChild(false);
}
}}
/>
</View>
);
const renderParentControls = () => (
<View>
<Text>Parent Dashboard</Text>
</View>
);
const renderChildControls = () => (
<View>
<Text>Child Dashboard</Text>
</View>
);
const renderCaregiverControls = () => (
<View>
<Text>Caregiver Dashboard</Text>
</View>
);
return (
<View>
{user ? (
<View paddingH-20>
{profileType === "Parent" && renderParentControls()}
{profileType === "Child" && renderChildControls()}
{profileType === "Caregiver" && renderCaregiverControls()}
<Button title="sign out" onPress={handleSignOut} />
{profileType === "parent" && <Text>Parent</Text>}
{profileType === "child" && <Text>Child</Text>}
{profileType === "caregiver" && <Text>Caregiver</Text>}
<Button title="Sign Out" onPress={handleSignOut} />
<TextField
placeholder={"Child Name"}
floatingPlaceholder
@ -272,8 +123,7 @@ const Screen: React.FC = () => {
validate={["required", (value: string) => value.length > 6]}
validationMessage={[
"Field is required",
"Email is invalid",
"Password is too short",
"Name is too short",
]}
showCharCounter
maxLength={30}
@ -335,9 +185,11 @@ const Screen: React.FC = () => {
<Text>Name: {child.name} </Text>
<Picker label="Pick Caregiver">
{caregivers.map((item) => (
<Picker.Item key={item.name} label={item.name} value={item.name}>
</Picker.Item>
<Picker.Item
key={item.name}
label={item.name}
value={item.name}
/>
))}
</Picker>
</View>

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,26 @@
export interface User {
uid: string;
email: string | null;
}
export interface UserProfile {
userType: "parent" | "child" | "caregiver";
name: string;
}
export interface ParentProfile extends UserProfile {
userType: "parent";
childrenIds: string[];
}
export interface ChildProfile extends UserProfile {
userType: "child";
birthday: Date;
parentId: string;
}
export interface CaregiverProfile extends UserProfile {
userType: "caregiver";
//assignedChildrenId: string[];
contact: string;
}

152
hooks/firebase/useAuth.ts Normal file
View File

@ -0,0 +1,152 @@
import { useState, useEffect } from "react";
import auth from "@react-native-firebase/auth";
import firestore from "@react-native-firebase/firestore";
import {
User,
CaregiverProfile,
ChildProfile,
ParentProfile,
} from "./types/profileTypes";
type ProfileType = "parent" | "child" | "caregiver" | null;
const useAuth = () => {
const [user, setUser] = useState<User | null>(null);
const [profileType, setProfileType] = useState<ProfileType>(null);
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
useEffect(() => {
const isDevelopment = __DEV__;
if (isDevelopment) {
firestore().useEmulator("localhost", 8080);
auth().useEmulator("http://127.0.0.1:9099");
}
const unsubscribe = auth().onAuthStateChanged(async (firebaseUser) => {
if (firebaseUser) {
const userObj: User = {
uid: firebaseUser.uid,
email: firebaseUser.email,
};
setUser(userObj);
try {
const documentSnapshot = await firestore()
.collection("Users")
.doc(firebaseUser.uid)
.get();
if (documentSnapshot.exists) {
setProfileType(documentSnapshot.data()?.profileType || null);
}
} catch (error) {
console.error("Error fetching user profile type:", error);
setProfileType(null);
}
} else {
setUser(null);
setProfileType(null);
}
});
return unsubscribe;
}, []);
const handleRegister = async () => {
try {
await auth().createUserWithEmailAndPassword(email, password);
console.log("user registered!");
await auth().signInWithEmailAndPassword(email, password);
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 auth().signInWithEmailAndPassword(email, password);
console.log("User signed in!");
} catch (error) {
console.error("Error during sign in:", error);
}
};
const handleSignOut = async () => {
try {
await auth().signOut();
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("Users")
.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

@ -0,0 +1,59 @@
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",
});
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

@ -0,0 +1,67 @@
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: "",
});
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;