mirror of
https://github.com/urosran/cally.git
synced 2025-07-15 17:47:08 +00:00
389 lines
15 KiB
TypeScript
389 lines
15 KiB
TypeScript
import {
|
|
Avatar,
|
|
Button,
|
|
Card,
|
|
Colors,
|
|
Dialog,
|
|
FloatingButton,
|
|
PanningProvider,
|
|
Picker,
|
|
Text,
|
|
TextField,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native-ui-lib";
|
|
import React, {useState} from "react";
|
|
import {ScrollView, StyleSheet} from "react-native";
|
|
import {PickerSingleValue} from "react-native-ui-lib/src/components/picker/types";
|
|
import {useCreateSubUser} from "@/hooks/firebase/useCreateSubUser";
|
|
import {ProfileType} from "@/contexts/AuthContext";
|
|
import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
|
|
import UserMenu from "@/components/pages/settings/user_settings_views/UserMenu";
|
|
import {uuidv4} from "@firebase/util";
|
|
|
|
const MyGroup = () => {
|
|
const [showAddUserDialog, setShowAddUserDialog] = useState(false);
|
|
const [showNewUserInfoDialog, setShowNewUserInfoDialog] = useState(false);
|
|
const [selectedStatus, setSelectedStatus] = useState<
|
|
string | PickerSingleValue
|
|
>(ProfileType.CHILD);
|
|
const [firstName, setFirstName] = useState("");
|
|
const [lastName, setLastName] = useState("");
|
|
const [email, setEmail] = useState("");
|
|
|
|
const [showQRCodeDialog, setShowQRCodeDialog] = useState("");
|
|
|
|
const {mutateAsync: createSubUser, isLoading, isError} = useCreateSubUser();
|
|
const {data: familyMembers} = useGetFamilyMembers(true);
|
|
|
|
const parents =
|
|
familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? [];
|
|
const children =
|
|
familyMembers?.filter((x) => x.userType === ProfileType.CHILD) ?? [];
|
|
const caregivers =
|
|
familyMembers?.filter((x) => x.userType === ProfileType.CAREGIVER) ?? [];
|
|
const familyDevices =
|
|
familyMembers?.filter((x) => x.userType === ProfileType.FAMILY_DEVICE) ?? [];
|
|
|
|
const handleCreateSubUser = async () => {
|
|
if (!firstName || (selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName)) {
|
|
console.error("First name and last name are required");
|
|
return;
|
|
}
|
|
|
|
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");
|
|
return;
|
|
}
|
|
|
|
const res = await createSubUser({
|
|
firstName,
|
|
lastName: selectedStatus === ProfileType.FAMILY_DEVICE ? "" : lastName,
|
|
email: email || `placeholder_${uuidv4().split("-")[0]}@family.device`,
|
|
password: uuidv4(),
|
|
userType: selectedStatus as ProfileType,
|
|
});
|
|
console.log(res)
|
|
|
|
if (!isError) {
|
|
setShowNewUserInfoDialog(false);
|
|
|
|
if(res?.data?.userId) {
|
|
setTimeout(() => {
|
|
setShowQRCodeDialog(res.data.userId)
|
|
}, 500)
|
|
}
|
|
}
|
|
|
|
|
|
};
|
|
|
|
return (
|
|
<View style={{flex: 1}}>
|
|
<View>
|
|
<ScrollView style={styles.card}>
|
|
{!parents.length && !children.length && !caregivers.length && (
|
|
<Text text70 marginV-10>
|
|
{isLoading ? "Loading...." : "No user devices added"}
|
|
</Text>
|
|
)}
|
|
|
|
{(!!parents.length || !!children.length) && (
|
|
<>
|
|
<Text text70 marginV-10>
|
|
Family
|
|
</Text>
|
|
{[...parents, ...children]?.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} {member.lastName}
|
|
</Text>
|
|
<Text text90 grey40>
|
|
{member.userType === ProfileType.PARENT
|
|
? "Admin (You)"
|
|
: "Child"}
|
|
</Text>
|
|
</View>
|
|
|
|
<View flex-1/>
|
|
|
|
<UserMenu setShowQRCodeDialog={(val) => setShowQRCodeDialog("")} showQRCodeDialog={showQRCodeDialog === member?.uid} userId={member?.uid!}/>
|
|
</Card>
|
|
))}
|
|
</>
|
|
)}
|
|
|
|
{!!caregivers.length && (
|
|
<>
|
|
<Text text70 marginB-10 marginT-15>
|
|
Caregivers
|
|
</Text>
|
|
{caregivers?.map((member) => (
|
|
<Card
|
|
enableShadow={false}
|
|
elevation={0}
|
|
key={`${member.firstName}_${member.lastName}`}
|
|
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} {member.lastName}
|
|
</Text>
|
|
<Text text90 grey40>
|
|
Caregiver
|
|
</Text>
|
|
</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>
|
|
))}
|
|
</>
|
|
)}
|
|
</ScrollView>
|
|
</View>
|
|
|
|
<FloatingButton
|
|
fullWidth
|
|
hideBackgroundOverlay
|
|
visible
|
|
button={{
|
|
label: "+ Add a user device",
|
|
onPress: () => setShowAddUserDialog(true),
|
|
}}
|
|
/>
|
|
|
|
<Dialog
|
|
visible={showAddUserDialog}
|
|
onDismiss={() => setShowAddUserDialog(false)}
|
|
panDirection={PanningProvider.Directions.DOWN}
|
|
>
|
|
<Card padding-25 gap-10>
|
|
<Text>Add a new user device</Text>
|
|
|
|
<Button backgroundColor={"#FD1775"}>
|
|
<Text white>Show a QR Code</Text>
|
|
</Button>
|
|
<Button
|
|
backgroundColor={"#05A8B6"}
|
|
onPress={() => {
|
|
setShowAddUserDialog(false);
|
|
setTimeout(() => {
|
|
setShowNewUserInfoDialog(true);
|
|
}, 500);
|
|
}}
|
|
>
|
|
<Text white>Enter email address</Text>
|
|
</Button>
|
|
|
|
<TouchableOpacity onPress={() => setShowAddUserDialog(false)} center>
|
|
<Text>Return to user settings</Text>
|
|
</TouchableOpacity>
|
|
</Card>
|
|
</Dialog>
|
|
|
|
<Dialog
|
|
panDirection={PanningProvider.Directions.DOWN}
|
|
visible={showNewUserInfoDialog}
|
|
onDismiss={() => setShowNewUserInfoDialog(false)}
|
|
>
|
|
<Card padding-25 style={styles.dialogCard}>
|
|
<View row spread>
|
|
<Text text60M>New User Information</Text>
|
|
<TouchableOpacity onPress={() => setShowAddUserDialog(false)}>
|
|
<Text>X</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
<View row centerV gap-20 marginV-20>
|
|
<Avatar
|
|
imageStyle={{borderRadius: 10}}
|
|
containerStyle={{borderRadius: 10}}
|
|
size={60}
|
|
backgroundColor={Colors.grey60}
|
|
/>
|
|
<TouchableOpacity onPress={() => {
|
|
}}>
|
|
<Text style={{color: Colors.green10}}>
|
|
Upload User Profile Photo
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
<Text style={styles.label}>Member Status</Text>
|
|
<Picker
|
|
editable={!isLoading}
|
|
value={selectedStatus}
|
|
//@ts-ignore
|
|
onChange={(item) => setSelectedStatus(item)}
|
|
style={styles.picker}
|
|
showSearch
|
|
floatingPlaceholder
|
|
>
|
|
<Picker.Item label="Child" value={ProfileType.CHILD}/>
|
|
<Picker.Item label="Parent" value={ProfileType.PARENT}/>
|
|
<Picker.Item label="Caregiver" value={ProfileType.CAREGIVER}/>
|
|
<Picker.Item label="Family Device" value={ProfileType.FAMILY_DEVICE}/>
|
|
</Picker>
|
|
|
|
<Text style={styles.label}>
|
|
{selectedStatus === ProfileType.FAMILY_DEVICE ? "Device Name" : "First Name"}
|
|
</Text>
|
|
<TextField
|
|
editable={!isLoading}
|
|
placeholder={selectedStatus === ProfileType.FAMILY_DEVICE ? "Device name" : "First name"}
|
|
value={firstName}
|
|
onChangeText={setFirstName}
|
|
style={styles.inputField}
|
|
/>
|
|
|
|
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
|
|
<>
|
|
<Text style={styles.label}>Last Name</Text>
|
|
<TextField
|
|
editable={!isLoading}
|
|
placeholder="Last name"
|
|
value={lastName}
|
|
onChangeText={setLastName}
|
|
style={styles.inputField}
|
|
/>
|
|
</>
|
|
)}
|
|
|
|
{selectedStatus !== ProfileType.FAMILY_DEVICE && (
|
|
<>
|
|
<Text style={styles.label}>Email Address (Optional)</Text>
|
|
<TextField
|
|
editable={!isLoading}
|
|
placeholder="Email address"
|
|
value={email}
|
|
onChangeText={setEmail}
|
|
keyboardType="email-address"
|
|
autoCapitalize="none"
|
|
style={styles.inputField}
|
|
/>
|
|
</>
|
|
)}
|
|
|
|
<Button
|
|
disabled={!firstName || (selectedStatus !== ProfileType.FAMILY_DEVICE && !lastName) || isLoading}
|
|
label={isLoading ? "Adding..." : "Add group member"}
|
|
backgroundColor="#FD1775"
|
|
style={{marginTop: 20}}
|
|
onPress={handleCreateSubUser}
|
|
/>
|
|
</Card>
|
|
</Dialog>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
card: {
|
|
marginVertical: 15,
|
|
backgroundColor: "white",
|
|
width: "100%",
|
|
borderRadius: 15,
|
|
padding: 20,
|
|
},
|
|
familyCard: {
|
|
marginBottom: 10,
|
|
borderRadius: 10,
|
|
backgroundColor: Colors.white,
|
|
width: "100%",
|
|
},
|
|
inputField: {
|
|
borderRadius: 50,
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 16,
|
|
backgroundColor: Colors.grey80,
|
|
marginBottom: 16,
|
|
borderColor: Colors.grey50,
|
|
borderWidth: 1,
|
|
height: 40,
|
|
},
|
|
picker: {
|
|
borderRadius: 50,
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 16,
|
|
backgroundColor: Colors.grey80,
|
|
marginBottom: 16,
|
|
borderColor: Colors.grey50,
|
|
borderWidth: 1,
|
|
marginTop: -20,
|
|
height: 40,
|
|
},
|
|
label: {
|
|
marginBottom: 5,
|
|
fontSize: 12,
|
|
color: Colors.grey40,
|
|
},
|
|
dialogCard: {
|
|
borderRadius: 10,
|
|
gap: 10,
|
|
},
|
|
});
|
|
|
|
export default MyGroup;
|