mirror of
https://github.com/urosran/cally.git
synced 2025-07-15 09:45:20 +00:00
Added creating family devices, refetch calendar on notification received
This commit is contained in:
@ -12,13 +12,14 @@ import {
|
|||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
} from "react-native-ui-lib";
|
} from "react-native-ui-lib";
|
||||||
import React, { useState } from "react";
|
import React, {useState} from "react";
|
||||||
import { ScrollView, StyleSheet } from "react-native";
|
import {ScrollView, StyleSheet} from "react-native";
|
||||||
import { PickerSingleValue } from "react-native-ui-lib/src/components/picker/types";
|
import {PickerSingleValue} from "react-native-ui-lib/src/components/picker/types";
|
||||||
import { useCreateSubUser } from "@/hooks/firebase/useCreateSubUser";
|
import {useCreateSubUser} from "@/hooks/firebase/useCreateSubUser";
|
||||||
import { ProfileType } from "@/contexts/AuthContext";
|
import {ProfileType} from "@/contexts/AuthContext";
|
||||||
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
|
import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
|
||||||
import UserMenu from "@/components/pages/settings/user_settings_views/UserMenu";
|
import UserMenu from "@/components/pages/settings/user_settings_views/UserMenu";
|
||||||
|
import {uuidv4} from "@firebase/util";
|
||||||
|
|
||||||
const MyGroup = () => {
|
const MyGroup = () => {
|
||||||
const [showAddUserDialog, setShowAddUserDialog] = useState(false);
|
const [showAddUserDialog, setShowAddUserDialog] = useState(false);
|
||||||
@ -30,8 +31,10 @@ const MyGroup = () => {
|
|||||||
const [lastName, setLastName] = useState("");
|
const [lastName, setLastName] = useState("");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
|
|
||||||
const { mutateAsync: createSubUser, isLoading, isError } = useCreateSubUser();
|
const [showQRCodeDialog, setShowQRCodeDialog] = useState("");
|
||||||
const { data: familyMembers } = useGetFamilyMembers(true);
|
|
||||||
|
const {mutateAsync: createSubUser, isLoading, isError} = useCreateSubUser();
|
||||||
|
const {data: familyMembers} = useGetFamilyMembers(true);
|
||||||
|
|
||||||
const parents =
|
const parents =
|
||||||
familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? [];
|
familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? [];
|
||||||
@ -39,35 +42,49 @@ const MyGroup = () => {
|
|||||||
familyMembers?.filter((x) => x.userType === ProfileType.CHILD) ?? [];
|
familyMembers?.filter((x) => x.userType === ProfileType.CHILD) ?? [];
|
||||||
const caregivers =
|
const caregivers =
|
||||||
familyMembers?.filter((x) => x.userType === ProfileType.CAREGIVER) ?? [];
|
familyMembers?.filter((x) => x.userType === ProfileType.CAREGIVER) ?? [];
|
||||||
|
const familyDevices =
|
||||||
|
familyMembers?.filter((x) => x.userType === ProfileType.FAMILY_DEVICE) ?? [];
|
||||||
|
|
||||||
const handleCreateSubUser = async () => {
|
const handleCreateSubUser = async () => {
|
||||||
if (!firstName || !lastName || !email) {
|
if (!firstName || (selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName)) {
|
||||||
console.error("All fields are required");
|
console.error("First name and last name are required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!email.includes("@")) {
|
if (selectedStatus !== ProfileType.FAMILY_DEVICE && !email) {
|
||||||
|
console.error("Email is required for non-family device users");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (email && !email.includes("@")) {
|
||||||
console.error("Invalid email address");
|
console.error("Invalid email address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await createSubUser({
|
const res = await createSubUser({
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName: selectedStatus === ProfileType.FAMILY_DEVICE ? "" : lastName,
|
||||||
email,
|
email: email || `placeholder_${uuidv4().split("-")[0]}@family.device`,
|
||||||
password: email,
|
password: uuidv4(),
|
||||||
userType: selectedStatus as ProfileType,
|
userType: selectedStatus as ProfileType,
|
||||||
});
|
});
|
||||||
|
console.log(res)
|
||||||
|
|
||||||
if (!isError) {
|
if (!isError) {
|
||||||
setShowNewUserInfoDialog(false);
|
setShowNewUserInfoDialog(false);
|
||||||
|
|
||||||
|
if(res?.data?.userId) {
|
||||||
|
setTimeout(() => {
|
||||||
|
setShowQRCodeDialog(res.data.userId)
|
||||||
|
}, 500)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(familyMembers);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{flex: 1}}>
|
||||||
<View>
|
<View>
|
||||||
<ScrollView style={styles.card}>
|
<ScrollView style={styles.card}>
|
||||||
{!parents.length && !children.length && !caregivers.length && (
|
{!parents.length && !children.length && !caregivers.length && (
|
||||||
@ -81,18 +98,18 @@ const MyGroup = () => {
|
|||||||
<Text text70 marginV-10>
|
<Text text70 marginV-10>
|
||||||
Family
|
Family
|
||||||
</Text>
|
</Text>
|
||||||
{[...parents, ...children]?.map((member) => (
|
{[...parents, ...children]?.map((member, index) => (
|
||||||
<Card
|
<Card
|
||||||
enableShadow={false}
|
enableShadow={false}
|
||||||
elevation={0}
|
elevation={0}
|
||||||
key={`${member.firstName}_${member.lastName}`}
|
key={`${member.firstName}_${member.lastName}_${index}`}
|
||||||
style={styles.familyCard}
|
style={styles.familyCard}
|
||||||
row
|
row
|
||||||
centerV
|
centerV
|
||||||
padding-10
|
padding-10
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
source={{ uri: "https://via.placeholder.com/60" }}
|
source={{uri: "https://via.placeholder.com/60"}}
|
||||||
size={40}
|
size={40}
|
||||||
backgroundColor={Colors.grey60}
|
backgroundColor={Colors.grey60}
|
||||||
/>
|
/>
|
||||||
@ -107,9 +124,9 @@ const MyGroup = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View flex-1 />
|
<View flex-1/>
|
||||||
|
|
||||||
<UserMenu userId={member?.uid!} />
|
<UserMenu setShowQRCodeDialog={(val) => setShowQRCodeDialog("")} showQRCodeDialog={showQRCodeDialog === member?.uid} userId={member?.uid!}/>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
@ -131,7 +148,7 @@ const MyGroup = () => {
|
|||||||
padding-10
|
padding-10
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
source={{ uri: "https://via.placeholder.com/60" }}
|
source={{uri: "https://via.placeholder.com/60"}}
|
||||||
size={40}
|
size={40}
|
||||||
backgroundColor={Colors.grey60}
|
backgroundColor={Colors.grey60}
|
||||||
/>
|
/>
|
||||||
@ -143,6 +160,43 @@ const MyGroup = () => {
|
|||||||
Caregiver
|
Caregiver
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<UserMenu setShowQRCodeDialog={(val) => setShowQRCodeDialog("")} showQRCodeDialog={showQRCodeDialog === member?.uid} userId={member?.uid!}/>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!!familyDevices.length && (
|
||||||
|
<>
|
||||||
|
<Text text70 marginB-10 marginT-15>
|
||||||
|
Family Devices
|
||||||
|
</Text>
|
||||||
|
{familyDevices?.map((member, index) => (
|
||||||
|
<Card
|
||||||
|
enableShadow={false}
|
||||||
|
elevation={0}
|
||||||
|
key={`${member.firstName}_${member.lastName}_${index}`}
|
||||||
|
style={styles.familyCard}
|
||||||
|
row
|
||||||
|
centerV
|
||||||
|
padding-10
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
source={{uri: "https://via.placeholder.com/60"}}
|
||||||
|
size={40}
|
||||||
|
backgroundColor={Colors.grey60}
|
||||||
|
/>
|
||||||
|
<View marginL-10>
|
||||||
|
<Text text70M>
|
||||||
|
{member.firstName}
|
||||||
|
</Text>
|
||||||
|
<Text text90 grey40>
|
||||||
|
Family Device
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<UserMenu setShowQRCodeDialog={(val) => setShowQRCodeDialog("")} showQRCodeDialog={showQRCodeDialog === member?.uid} userId={member?.uid!}/>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
@ -204,13 +258,14 @@ const MyGroup = () => {
|
|||||||
|
|
||||||
<View row centerV gap-20 marginV-20>
|
<View row centerV gap-20 marginV-20>
|
||||||
<Avatar
|
<Avatar
|
||||||
imageStyle={{ borderRadius: 10 }}
|
imageStyle={{borderRadius: 10}}
|
||||||
containerStyle={{ borderRadius: 10 }}
|
containerStyle={{borderRadius: 10}}
|
||||||
size={60}
|
size={60}
|
||||||
backgroundColor={Colors.grey60}
|
backgroundColor={Colors.grey60}
|
||||||
/>
|
/>
|
||||||
<TouchableOpacity onPress={() => {}}>
|
<TouchableOpacity onPress={() => {
|
||||||
<Text style={{ color: Colors.green10 }}>
|
}}>
|
||||||
|
<Text style={{color: Colors.green10}}>
|
||||||
Upload User Profile Photo
|
Upload User Profile Photo
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@ -226,20 +281,25 @@ const MyGroup = () => {
|
|||||||
showSearch
|
showSearch
|
||||||
floatingPlaceholder
|
floatingPlaceholder
|
||||||
>
|
>
|
||||||
<Picker.Item label="Child" value={ProfileType.CHILD} />
|
<Picker.Item label="Child" value={ProfileType.CHILD}/>
|
||||||
<Picker.Item label="Parent" value={ProfileType.PARENT} />
|
<Picker.Item label="Parent" value={ProfileType.PARENT}/>
|
||||||
<Picker.Item label="Caregiver" value={ProfileType.CAREGIVER} />
|
<Picker.Item label="Caregiver" value={ProfileType.CAREGIVER}/>
|
||||||
|
<Picker.Item label="Family Device" value={ProfileType.FAMILY_DEVICE}/>
|
||||||
</Picker>
|
</Picker>
|
||||||
|
|
||||||
<Text style={styles.label}>First Name</Text>
|
<Text style={styles.label}>
|
||||||
|
{selectedStatus === ProfileType.FAMILY_DEVICE ? "Device Name" : "First Name"}
|
||||||
|
</Text>
|
||||||
<TextField
|
<TextField
|
||||||
editable={!isLoading}
|
editable={!isLoading}
|
||||||
placeholder="First name"
|
placeholder={selectedStatus === ProfileType.FAMILY_DEVICE ? "Device name" : "First name"}
|
||||||
value={firstName}
|
value={firstName}
|
||||||
onChangeText={setFirstName}
|
onChangeText={setFirstName}
|
||||||
style={styles.inputField}
|
style={styles.inputField}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
|
||||||
|
<>
|
||||||
<Text style={styles.label}>Last Name</Text>
|
<Text style={styles.label}>Last Name</Text>
|
||||||
<TextField
|
<TextField
|
||||||
editable={!isLoading}
|
editable={!isLoading}
|
||||||
@ -248,8 +308,12 @@ const MyGroup = () => {
|
|||||||
onChangeText={setLastName}
|
onChangeText={setLastName}
|
||||||
style={styles.inputField}
|
style={styles.inputField}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Text style={styles.label}>Email Address</Text>
|
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
|
||||||
|
<>
|
||||||
|
<Text style={styles.label}>Email Address (Optional)</Text>
|
||||||
<TextField
|
<TextField
|
||||||
editable={!isLoading}
|
editable={!isLoading}
|
||||||
placeholder="Email address"
|
placeholder="Email address"
|
||||||
@ -259,12 +323,14 @@ const MyGroup = () => {
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
style={styles.inputField}
|
style={styles.inputField}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
disabled={!firstName || !lastName || !email || isLoading}
|
disabled={!firstName || (selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName) || isLoading}
|
||||||
label={isLoading ? "Adding..." : "Add group member"}
|
label={isLoading ? "Adding..." : "Add group member"}
|
||||||
backgroundColor="#FD1775"
|
backgroundColor="#FD1775"
|
||||||
style={{ marginTop: 20 }}
|
style={{marginTop: 20}}
|
||||||
onPress={handleCreateSubUser}
|
onPress={handleCreateSubUser}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import { View, Text, TextField } from "react-native-ui-lib";
|
import {Text, TextField, View} from "react-native-ui-lib";
|
||||||
import React, { useState } from "react";
|
import React, {useState} from "react";
|
||||||
import { StyleSheet } from "react-native";
|
import {StyleSheet} from "react-native";
|
||||||
import { ScrollView } from "react-native-gesture-handler";
|
import {ScrollView} from "react-native-gesture-handler";
|
||||||
import { useAuthContext } from "@/contexts/AuthContext";
|
import {useAuthContext} from "@/contexts/AuthContext";
|
||||||
import { useSettingsContext } from "@/contexts/SettingsContext";
|
import {useUpdateUserData} from "@/hooks/firebase/useUpdateUserData";
|
||||||
import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
|
|
||||||
const MyProfile = () => {
|
const MyProfile = () => {
|
||||||
const { user, profileData } = useAuthContext();
|
const {user, profileData} = useAuthContext();
|
||||||
|
|
||||||
const [lastName, setLastName] = useState<string>(profileData?.lastName || "");
|
const [lastName, setLastName] = useState<string>(profileData?.lastName || "");
|
||||||
const [firstName, setFirstName] = useState<string>(
|
const [firstName, setFirstName] = useState<string>(
|
||||||
profileData?.firstName || ""
|
profileData?.firstName || ""
|
||||||
);
|
);
|
||||||
|
|
||||||
const { mutateAsync: updateUserData } = useUpdateUserData();
|
const {mutateAsync: updateUserData} = useUpdateUserData();
|
||||||
return (
|
return (
|
||||||
<ScrollView style={{paddingBottom: 100, flex: 1}}>
|
<ScrollView style={{paddingBottom: 100, flex: 1}}>
|
||||||
<View style={styles.card}>
|
<View style={styles.card}>
|
||||||
@ -36,7 +36,7 @@ const MyProfile = () => {
|
|||||||
value={firstName}
|
value={firstName}
|
||||||
onChangeText={async (value) => {
|
onChangeText={async (value) => {
|
||||||
setFirstName(value);
|
setFirstName(value);
|
||||||
await updateUserData({ newUserData: { firstName: value } });
|
await updateUserData({newUserData: {firstName: value}});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Text text80 marginT-10 marginB-7 color="#a1a1a1">
|
<Text text80 marginT-10 marginB-7 color="#a1a1a1">
|
||||||
@ -49,7 +49,7 @@ const MyProfile = () => {
|
|||||||
value={lastName}
|
value={lastName}
|
||||||
onChangeText={async (value) => {
|
onChangeText={async (value) => {
|
||||||
setLastName(value);
|
setLastName(value);
|
||||||
await updateUserData({ newUserData: { lastName: value } });
|
await updateUserData({newUserData: {lastName: value}});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Text text80 marginT-10 marginB-7 color="#a1a1a1">
|
<Text text80 marginT-10 marginB-7 color="#a1a1a1">
|
||||||
@ -69,7 +69,7 @@ const MyProfile = () => {
|
|||||||
<Text text80 marginT-20 marginB-7 color="#a1a1a1">
|
<Text text80 marginT-20 marginB-7 color="#a1a1a1">
|
||||||
Time Zone
|
Time Zone
|
||||||
</Text>
|
</Text>
|
||||||
<TextField text70 placeholder="Time Zone" style={styles.txtBox} />
|
<TextField text70 placeholder="Time Zone" style={styles.txtBox}/>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
@ -3,15 +3,22 @@ import {Button, Card, Colors, Dialog, Hint, ListItem, Text, View} from 'react-na
|
|||||||
import QRCode from 'react-native-qrcode-svg';
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
import {PanningDirectionsEnum} from "react-native-ui-lib/src/components/panningViews/panningProvider";
|
import {PanningDirectionsEnum} from "react-native-ui-lib/src/components/panningViews/panningProvider";
|
||||||
|
|
||||||
const UserMenu = ({userId}:{userId: string}) => {
|
const UserMenu = ({
|
||||||
|
userId,
|
||||||
|
showQRCodeDialog,
|
||||||
|
setShowQRCodeDialog
|
||||||
|
}: {
|
||||||
|
userId: string,
|
||||||
|
showQRCodeDialog: boolean,
|
||||||
|
setShowQRCodeDialog: (value: boolean) => void
|
||||||
|
}) => {
|
||||||
const [showHint, setShowHint] = useState(false);
|
const [showHint, setShowHint] = useState(false);
|
||||||
const [showQRCodeDialog, setShowQRCodeDialog] = useState(false);
|
|
||||||
|
|
||||||
const handleShowQRCode = () => {
|
const handleShowQRCode = () => {
|
||||||
setShowHint(false);
|
setShowHint(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setShowQRCodeDialog(true);
|
setShowQRCodeDialog(true);
|
||||||
}, 500)
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -22,9 +29,7 @@ const UserMenu = ({userId}:{userId: string}) => {
|
|||||||
color={Colors.white}
|
color={Colors.white}
|
||||||
customContent={
|
customContent={
|
||||||
<View height={18}>
|
<View height={18}>
|
||||||
<ListItem
|
<ListItem onPress={handleShowQRCode}>
|
||||||
onPress={handleShowQRCode}
|
|
||||||
>
|
|
||||||
<Text>Show Login QR Code</Text>
|
<Text>Show Login QR Code</Text>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</View>
|
</View>
|
||||||
@ -34,7 +39,7 @@ const UserMenu = ({userId}:{userId: string}) => {
|
|||||||
backdropColor="transparent"
|
backdropColor="transparent"
|
||||||
>
|
>
|
||||||
<View>
|
<View>
|
||||||
<Button link onPress={() => setShowHint(x => !x)}>
|
<Button link onPress={() => setShowHint(!showHint)}>
|
||||||
<Text>...</Text>
|
<Text>...</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
@ -47,7 +52,7 @@ const UserMenu = ({userId}:{userId: string}) => {
|
|||||||
>
|
>
|
||||||
<Card padding-20 center>
|
<Card padding-20 center>
|
||||||
<Text marginB-10>Scan this QR Code to Login:</Text>
|
<Text marginB-10>Scan this QR Code to Login:</Text>
|
||||||
<QRCode value={userId} size={150} />
|
<QRCode value={userId} size={150}/>
|
||||||
<Button
|
<Button
|
||||||
marginT-20
|
marginT-20
|
||||||
label="Close"
|
label="Close"
|
||||||
|
@ -9,11 +9,14 @@ import * as Notifications from 'expo-notifications';
|
|||||||
import * as Device from 'expo-device';
|
import * as Device from 'expo-device';
|
||||||
import Constants from 'expo-constants';
|
import Constants from 'expo-constants';
|
||||||
import { Platform } from 'react-native';
|
import { Platform } from 'react-native';
|
||||||
|
import {useQueryClient} from "react-query";
|
||||||
|
|
||||||
|
|
||||||
export enum ProfileType {
|
export enum ProfileType {
|
||||||
"PARENT" = "parent",
|
"PARENT" = "parent",
|
||||||
"CHILD" = "child",
|
"CHILD" = "child",
|
||||||
"CAREGIVER" = "caregiver"
|
"CAREGIVER" = "caregiver",
|
||||||
|
FAMILY_DEVICE = "FAMILY_DEVICE"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IAuthContext {
|
interface IAuthContext {
|
||||||
@ -91,6 +94,8 @@ export const AuthContextProvider: FC<{ children: ReactNode }> = ({children}) =>
|
|||||||
const {replace} = useRouter();
|
const {replace} = useRouter();
|
||||||
const ready = !initializing;
|
const ready = !initializing;
|
||||||
|
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const onAuthStateChangedHandler = async (authUser: FirebaseAuthTypes.User | null) => {
|
const onAuthStateChangedHandler = async (authUser: FirebaseAuthTypes.User | null) => {
|
||||||
setUser(authUser);
|
setUser(authUser);
|
||||||
|
|
||||||
@ -153,6 +158,17 @@ export const AuthContextProvider: FC<{ children: ReactNode }> = ({children}) =>
|
|||||||
}
|
}
|
||||||
}, [user, ready]);
|
}, [user, ready]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = Notifications.addNotificationReceivedListener(notification => {
|
||||||
|
const eventId = notification?.request?.content?.data?.eventId;
|
||||||
|
|
||||||
|
if (eventId) {
|
||||||
|
queryClient.invalidateQueries(['events']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return () => sub.remove()
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (!ready) {
|
if (!ready) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ exports.createSubUser = onRequest(async (request, response) => {
|
|||||||
|
|
||||||
const {userType, firstName, lastName, email, password, familyId} = request.body.data;
|
const {userType, firstName, lastName, email, password, familyId} = request.body.data;
|
||||||
|
|
||||||
if (!email || !password || !firstName || !lastName || !userType || !familyId) {
|
if (!email || !password || !firstName || !userType || !familyId) {
|
||||||
logger.warn("Missing required fields in request body", {requestBody: request.body.data});
|
logger.warn("Missing required fields in request body", {requestBody: request.body.data});
|
||||||
response.status(400).json({error: "Missing required fields"});
|
response.status(400).json({error: "Missing required fields"});
|
||||||
return;
|
return;
|
||||||
|
@ -2,6 +2,7 @@ import {useMutation, useQueryClient} from "react-query";
|
|||||||
import {UserProfile} from "@/hooks/firebase/types/profileTypes";
|
import {UserProfile} from "@/hooks/firebase/types/profileTypes";
|
||||||
import functions from '@react-native-firebase/functions';
|
import functions from '@react-native-firebase/functions';
|
||||||
import {ProfileType, useAuthContext} from "@/contexts/AuthContext";
|
import {ProfileType, useAuthContext} from "@/contexts/AuthContext";
|
||||||
|
import {HttpsCallableResult} from "@firebase/functions";
|
||||||
|
|
||||||
export const useCreateSubUser = () => {
|
export const useCreateSubUser = () => {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@ -9,13 +10,13 @@ export const useCreateSubUser = () => {
|
|||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationKey: ["createSubUser"],
|
mutationKey: ["createSubUser"],
|
||||||
mutationFn: async ({email, ...userProfile}: { email: string } & UserProfile) => {
|
mutationFn: async ({email, ...userProfile}: { email?: string } & UserProfile) => {
|
||||||
if (profileType === ProfileType.PARENT) {
|
if (profileType === ProfileType.PARENT) {
|
||||||
return await functions().httpsCallable("createSubUser")({
|
return await functions().httpsCallable("createSubUser")({
|
||||||
...userProfile,
|
...userProfile,
|
||||||
email,
|
email,
|
||||||
familyId: profileData?.familyId
|
familyId: profileData?.familyId
|
||||||
})
|
}) as HttpsCallableResult<{ userId: string }>
|
||||||
} else {
|
} else {
|
||||||
throw Error("Can't create sub-users as a non-parent.")
|
throw Error("Can't create sub-users as a non-parent.")
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user