Profile picture upload added, QR code scan fix

This commit is contained in:
Milan Paunovic
2024-11-01 04:34:59 +01:00
parent 0fbf89644f
commit 909a4344dc
7 changed files with 784 additions and 695 deletions

View File

@ -1,33 +1,36 @@
import {SafeAreaView} from "react-native-safe-area-context"; import {SafeAreaView} from "react-native-safe-area-context";
import {Button, Colors, Dialog, LoaderScreen, Text, View} from "react-native-ui-lib"; import {Button, Colors, Dialog, LoaderScreen, Text, View} from "react-native-ui-lib";
import React, {useState} from "react"; import React, {useCallback, useState} from "react";
import {useRouter} from "expo-router"; import {useRouter} from "expo-router";
import QRIcon from "@/assets/svgs/QRIcon"; import QRIcon from "@/assets/svgs/QRIcon";
import Toast from "react-native-toast-message";
import {Camera, CameraView} from "expo-camera"; import {Camera, CameraView} from "expo-camera";
import {useLoginWithQrCode} from "@/hooks/firebase/useLoginWithQrCode"; import {useLoginWithQrCode} from "@/hooks/firebase/useLoginWithQrCode";
import {useAuthContext} from "@/contexts/AuthContext";
import debounce from "debounce";
export default function Screen() { export default function Screen() {
const router = useRouter() const router = useRouter()
const {setRedirectOverride} = useAuthContext()
const [hasPermission, setHasPermission] = useState<boolean | null>(null); const [hasPermission, setHasPermission] = useState<boolean | null>(null);
const [showCameraDialog, setShowCameraDialog] = useState<boolean>(false); const [showCameraDialog, setShowCameraDialog] = useState<boolean>(false);
const {mutateAsync: signInWithQrCode, isLoading} = useLoginWithQrCode(); const {mutateAsync: signInWithQrCode, isLoading} = useLoginWithQrCode();
const debouncedRouterReplace = useCallback(
debounce(() => {
router.push("/(unauth)/cal_sync");
}, 300),
[]
);
const handleQrCodeScanned = async ({data}: { data: string }) => { const handleQrCodeScanned = async ({data}: { data: string }) => {
setShowCameraDialog(false); setShowCameraDialog(false);
setRedirectOverride(true);
try { try {
await signInWithQrCode({userId: data}); await signInWithQrCode({userId: data});
Toast.show({ debouncedRouterReplace()
type: "success",
text1: "Login successful with QR code!",
});
} catch (err) { } catch (err) {
Toast.show({ console.log(err)
type: "error",
text1: "Error logging in with QR code",
text2: `${err}`,
});
} }
}; };

View File

@ -225,7 +225,7 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
mode={mode} mode={mode}
enableEnrichedEvents={true} enableEnrichedEvents={true}
sortedMonthView sortedMonthView
enrichedEventsByDate={enrichedEvents} // enrichedEventsByDate={enrichedEvents}
events={filteredEvents} events={filteredEvents}
// eventCellStyle={memoizedEventCellStyle} // eventCellStyle={memoizedEventCellStyle}
onPressEvent={handlePressEvent} onPressEvent={handlePressEvent}

View File

@ -1,27 +1,21 @@
import { import {FloatingButton, Text, TouchableOpacity, View,} from "react-native-ui-lib";
FloatingButton, import React, {useState} from "react";
Text, import {Ionicons} from "@expo/vector-icons";
TouchableOpacity, import {ScrollView, StyleSheet} from "react-native";
View,
} from "react-native-ui-lib";
import React, { useState } from "react";
import { Ionicons } from "@expo/vector-icons";
import { ScrollView, StyleSheet } from "react-native";
import MyProfile from "./user_settings_views/MyProfile"; import MyProfile from "./user_settings_views/MyProfile";
import MyGroup from "./user_settings_views/MyGroup"; import MyGroup from "./user_settings_views/MyGroup";
import { useAtom } from "jotai"; import {useAtom, useSetAtom} from "jotai";
import { settingsPageIndex, userSettingsView } from "../calendar/atoms"; import {settingsPageIndex, userSettingsView} from "../calendar/atoms";
import { AuthContextProvider } from "@/contexts/AuthContext";
import PlusIcon from "@/assets/svgs/PlusIcon"; import PlusIcon from "@/assets/svgs/PlusIcon";
const UserSettings = () => { const UserSettings = () => {
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex); const setPageIndex = useSetAtom(settingsPageIndex);
const [userView, setUserView] = useAtom(userSettingsView); const [userView, setUserView] = useAtom(userSettingsView);
const [onNewUserClick, setOnNewUserClick] = useState<(boolean)>(false); const [onNewUserClick, setOnNewUserClick] = useState<(boolean)>(false);
return ( return (
<AuthContextProvider>
<View flexG> <View flexG>
<ScrollView style={{ paddingBottom: 20, minHeight: "100%" }}> <ScrollView style={{paddingBottom: 20, minHeight: "100%"}}>
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={() => {
setPageIndex(0); setPageIndex(0);
@ -33,17 +27,17 @@ const UserSettings = () => {
name="chevron-back" name="chevron-back"
size={14} size={14}
color="#979797" color="#979797"
style={{ paddingBottom: 3 }} style={{paddingBottom: 3}}
/> />
<Text <Text
style={{ fontFamily: "Poppins_400Regular", fontSize: 14.71 }} style={{fontFamily: "Poppins_400Regular", fontSize: 14.71}}
color="#979797" color="#979797"
> >
Return to main settings Return to main settings
</Text> </Text>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
<View marginH-26 flexG style={{ minHeight: "90%" }}> <View marginH-26 flexG style={{minHeight: "90%"}}>
<Text text60R marginB-25> <Text text60R marginB-25>
User Management User Management
</Text> </Text>
@ -79,7 +73,7 @@ const UserSettings = () => {
</View> </View>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
{userView && <MyProfile />} {userView && <MyProfile/>}
{!userView && <MyGroup onNewUserClick={onNewUserClick} setOnNewUserClick={setOnNewUserClick}/>} {!userView && <MyGroup onNewUserClick={onNewUserClick} setOnNewUserClick={setOnNewUserClick}/>}
</View> </View>
</ScrollView> </ScrollView>
@ -90,15 +84,14 @@ const UserSettings = () => {
visible visible
button={{ button={{
label: " Add a user device", label: " Add a user device",
iconSource: () => <PlusIcon height={13} width={14} />, iconSource: () => <PlusIcon height={13} width={14}/>,
onPress: () => setOnNewUserClick(true), onPress: () => setOnNewUserClick(true),
style: styles.bottomButton, style: styles.bottomButton,
labelStyle: { fontFamily: "Manrope_600SemiBold", fontSize: 15 }, labelStyle: {fontFamily: "Manrope_600SemiBold", fontSize: 15},
}} }}
/> />
)} )}
</View> </View>
</AuthContextProvider>
); );
}; };
@ -132,7 +125,7 @@ const styles = StyleSheet.create({
width: "50%", width: "50%",
borderRadius: 50, borderRadius: 50,
}, },
title: { fontFamily: "Manrope_600SemiBold", fontSize: 18 }, title: {fontFamily: "Manrope_600SemiBold", fontSize: 18},
}); });
export default UserSettings; export default UserSettings;

View File

@ -3,8 +3,7 @@ import {
Button, Button,
Card, Card,
Colors, Colors,
Dialog, Dialog, Image,
FloatingButton,
KeyboardAwareScrollView, KeyboardAwareScrollView,
PanningProvider, PanningProvider,
Picker, Picker,
@ -14,31 +13,31 @@ import {
TouchableOpacity, TouchableOpacity,
View, View,
} from "react-native-ui-lib"; } from "react-native-ui-lib";
import React, { useEffect, useRef, useState } from "react"; import React, {useEffect, useRef, useState} from "react";
import { ImageBackground, Platform, StyleSheet } from "react-native"; import {ImageBackground, Platform, 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, useAuthContext } from "@/contexts/AuthContext"; import {ProfileType, useAuthContext} 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"; import {uuidv4} from "@firebase/util";
import QRIcon from "@/assets/svgs/QRIcon"; import QRIcon from "@/assets/svgs/QRIcon";
import EmailIcon from "@/assets/svgs/EmailIcon"; import EmailIcon from "@/assets/svgs/EmailIcon";
import CircledXIcon from "@/assets/svgs/CircledXIcon"; import CircledXIcon from "@/assets/svgs/CircledXIcon";
import ProfileIcon from "@/assets/svgs/ProfileIcon"; import ProfileIcon from "@/assets/svgs/ProfileIcon";
import NavToDosIcon from "@/assets/svgs/NavToDosIcon"; import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
import Ionicons from "@expo/vector-icons/Ionicons"; import Ionicons from "@expo/vector-icons/Ionicons";
import KeyboardManager, { import KeyboardManager, {PreviousNextView,} from "react-native-keyboard-manager";
PreviousNextView, import {ScrollView} from "react-native-gesture-handler";
} from "react-native-keyboard-manager"; import {useUploadProfilePicture} from "@/hooks/useUploadProfilePicture";
import { ScrollView } from "react-native-gesture-handler"; import {ImagePickerAsset} from "expo-image-picker";
type MyGroupProps = { type MyGroupProps = {
onNewUserClick: boolean; onNewUserClick: boolean;
setOnNewUserClick: React.Dispatch<React.SetStateAction<boolean>>; setOnNewUserClick: React.Dispatch<React.SetStateAction<boolean>>;
}; };
const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick }) => { const MyGroup: React.FC<MyGroupProps> = ({onNewUserClick, setOnNewUserClick}) => {
const [showAddUserDialog, setShowAddUserDialog] = useState(false); const [showAddUserDialog, setShowAddUserDialog] = useState(false);
const [selectedStatus, setSelectedStatus] = useState< const [selectedStatus, setSelectedStatus] = useState<
string | PickerSingleValue string | PickerSingleValue
@ -47,6 +46,8 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
const [lastName, setLastName] = useState(""); const [lastName, setLastName] = useState("");
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const [newUserId, setNewUserId] = useState("")
const lNameRef = useRef<TextFieldRef>(null); const lNameRef = useRef<TextFieldRef>(null);
const emailRef = useRef<TextFieldRef>(null); const emailRef = useRef<TextFieldRef>(null);
@ -54,9 +55,10 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
false false
); );
const { mutateAsync: createSubUser, isLoading, isError } = useCreateSubUser(); const {mutateAsync: createSubUser, isLoading, isError} = useCreateSubUser();
const { data: familyMembers } = useGetFamilyMembers(true); const {data: familyMembers} = useGetFamilyMembers(true);
const { user } = useAuthContext(); const {user} = useAuthContext();
const {pickImage, changeProfilePicture, handleClearImage, pfpUri, profileImageAsset} = useUploadProfilePicture(newUserId)
const parents = const parents =
familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? []; familyMembers?.filter((x) => x.userType === ProfileType.PARENT) ?? [];
@ -100,10 +102,17 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
setOnNewUserClick(false); setOnNewUserClick(false);
if (res?.data?.userId) { if (res?.data?.userId) {
if (profileImageAsset) {
await changeProfilePicture(profileImageAsset)
setShowQRCodeDialog(res.data.userId);
} else {
setTimeout(() => { setTimeout(() => {
setShowQRCodeDialog(res.data.userId); setShowQRCodeDialog(res.data.userId);
}, 500); }, 500);
} }
handleClearImage()
}
} }
}; };
@ -147,11 +156,11 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
<ImageBackground <ImageBackground
style={styles.pfp} style={styles.pfp}
borderRadius={10.56} borderRadius={10.56}
source={{ uri: member.pfp || undefined }} source={{uri: member.pfp || undefined}}
/> />
) : ( ) : (
<View <View
style={[styles.pfp, { backgroundColor: "#ea156d" }]} style={[styles.pfp, {backgroundColor: "#ea156d"}]}
/> />
)} )}
<View row marginL-10 centerV> <View row marginL-10 centerV>
@ -159,7 +168,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
{member.firstName} {member.lastName} {member.firstName} {member.lastName}
</Text> </Text>
</View> </View>
<View flexG /> <View flexG/>
<View row centerV gap-10> <View row centerV gap-10>
<Text style={styles.userType}> <Text style={styles.userType}>
{member.userType === ProfileType.PARENT {member.userType === ProfileType.PARENT
@ -193,7 +202,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
padding-10 padding-10
> >
<Avatar <Avatar
source={{ uri: member?.pfp ?? undefined }} source={{uri: member?.pfp ?? undefined}}
size={40} size={40}
backgroundColor={Colors.grey60} backgroundColor={Colors.grey60}
/> />
@ -206,7 +215,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
</Text> </Text>
</View> </View>
<View flex-1 /> <View flex-1/>
<UserMenu <UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)} setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)}
@ -234,7 +243,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
padding-10 padding-10
> >
<Avatar <Avatar
source={{ uri: member?.pfp ?? undefined }} source={{uri: member?.pfp ?? undefined}}
size={40} size={40}
backgroundColor={Colors.grey60} backgroundColor={Colors.grey60}
/> />
@ -245,7 +254,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
</Text> </Text>
</View> </View>
<View flex-1 /> <View flex-1/>
<UserMenu <UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)} setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)}
@ -277,7 +286,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
</Text> </Text>
<Button backgroundColor={"#FD1775"} style={styles.dialogBtn}> <Button backgroundColor={"#FD1775"} style={styles.dialogBtn}>
<QRIcon /> <QRIcon/>
<Text style={styles.dialogBtnLbl} marginL-7> <Text style={styles.dialogBtnLbl} marginL-7>
Show a QR Code Show a QR Code
</Text> </Text>
@ -292,7 +301,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
}, 500); }, 500);
}} }}
> >
<EmailIcon /> <EmailIcon/>
<Text style={styles.dialogBtnLbl} marginL-7> <Text style={styles.dialogBtnLbl} marginL-7>
Enter email address Enter email address
</Text> </Text>
@ -317,7 +326,7 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
<KeyboardAwareScrollView> <KeyboardAwareScrollView>
<Card padding-25 style={styles.dialogCard}> <Card padding-25 style={styles.dialogCard}>
<View row spread> <View row spread>
<Text style={{ fontFamily: "Manrope_500Medium", fontSize: 16 }}> <Text style={{fontFamily: "Manrope_500Medium", fontSize: 16}}>
New User Information New User Information
</Text> </Text>
<TouchableOpacity <TouchableOpacity
@ -325,27 +334,46 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
setOnNewUserClick(false); setOnNewUserClick(false);
}} }}
> >
<CircledXIcon /> <CircledXIcon/>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<View style={styles.divider} spread /> <View style={styles.divider} spread/>
<View row centerV gap-20 marginV-20> <View row centerV gap-20 marginV-20>
{pfpUri ? (
<Image
height={65.54}
width={65.54}
style={{borderRadius: 25}}
source={{uri: pfpUri}}
/>
) : (
<View <View
height={65.54} height={65.54}
width={65.54} width={65.54}
children={ children={
<ProfileIcon color={"#d6d6d6"} width={37} height={37} /> <ProfileIcon color={"#d6d6d6"} width={37} height={37}/>
} }
backgroundColor={Colors.grey60} backgroundColor={Colors.grey60}
style={{ borderRadius: 25 }} style={{borderRadius: 25}}
center center
/> />
<TouchableOpacity onPress={() => {}}> )}
{pfpUri ? (
<TouchableOpacity onPress={handleClearImage}>
<Text color={Colors.red40} style={styles.jakarta13} marginL-15>
Clear user photo
</Text>
</TouchableOpacity>
) : (
<TouchableOpacity onPress={pickImage}>
<Text color="#50be0c" style={styles.jakarta13} marginL-15> <Text color="#50be0c" style={styles.jakarta13} marginL-15>
Upload User Profile Photo Upload User Profile Photo
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
)}
</View> </View>
<Text style={styles.jakarta12}>Member Status</Text> <Text style={styles.jakarta12}>Member Status</Text>
@ -369,15 +397,15 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
> >
<Ionicons <Ionicons
name={"chevron-down"} name={"chevron-down"}
style={{ alignSelf: "center" }} style={{alignSelf: "center"}}
size={20} size={20}
color={"#000000"} color={"#000000"}
/> />
</View> </View>
} }
> >
<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 <Picker.Item
label="Caregiver" label="Caregiver"
value={ProfileType.CAREGIVER} value={ProfileType.CAREGIVER}
@ -460,8 +488,8 @@ const MyGroup: React.FC<MyGroupProps> = ({ onNewUserClick, setOnNewUserClick })
fontSize: 15, fontSize: 15,
marginLeft: 7, marginLeft: 7,
}} }}
style={{ marginTop: 20, backgroundColor: "#fd1775" }} style={{marginTop: 20, backgroundColor: "#fd1775"}}
iconSource={() => <NavToDosIcon width={22} color={"white"} />} iconSource={() => <NavToDosIcon width={22} color={"white"}/>}
onPress={handleCreateSubUser} onPress={handleCreateSubUser}
/> />
</Card> </Card>
@ -477,7 +505,7 @@ const styles = StyleSheet.create({
height: 47, height: 47,
width: 279, width: 279,
}, },
dialogTitle: { fontFamily: "Manrope_600SemiBold", fontSize: 22 }, dialogTitle: {fontFamily: "Manrope_600SemiBold", fontSize: 22},
dialogBackBtn: { dialogBackBtn: {
fontFamily: "PlusJakartaSans_500Medium", fontFamily: "PlusJakartaSans_500Medium",
fontSize: 15, fontSize: 15,
@ -565,7 +593,7 @@ const styles = StyleSheet.create({
fontSize: 15, fontSize: 15,
color: "white", color: "white",
}, },
divider: { height: 0.7, backgroundColor: "#e6e6e6", width: "100%" }, divider: {height: 0.7, backgroundColor: "#e6e6e6", width: "100%"},
jakarta12: { jakarta12: {
fontFamily: "PlusJakartaSans_500Medium", fontFamily: "PlusJakartaSans_500Medium",
fontSize: 12, fontSize: 12,
@ -575,7 +603,7 @@ const styles = StyleSheet.create({
fontFamily: "PlusJakartaSans_500Medium", fontFamily: "PlusJakartaSans_500Medium",
fontSize: 13, fontSize: 13,
}, },
pfp: { aspectRatio: 1, width: 37.03, borderRadius: 10.56 }, pfp: {aspectRatio: 1, width: 37.03, borderRadius: 10.56},
userType: { userType: {
fontFamily: "Manrope_500Medium", fontFamily: "Manrope_500Medium",
fontSize: 12, fontSize: 12,

View File

@ -65,7 +65,6 @@ const MyProfile = () => {
if (profileData) { if (profileData) {
setFirstName(profileData.firstName || ""); setFirstName(profileData.firstName || "");
setLastName(profileData.lastName || ""); setLastName(profileData.lastName || "");
// setProfileImage(profileData.pfp || null);
setTimeZone( setTimeZone(
profileData.timeZone || Localization.getCalendars()[0].timeZone! profileData.timeZone || Localization.getCalendars()[0].timeZone!
); );

View File

@ -1,13 +1,13 @@
import { useMutation, useQueryClient } from "react-query"; import {useMutation, useQueryClient} from "react-query";
import firestore from "@react-native-firebase/firestore"; import firestore from "@react-native-firebase/firestore";
import storage from "@react-native-firebase/storage"; import storage from "@react-native-firebase/storage";
import { useAuthContext } from "@/contexts/AuthContext"; import {useAuthContext} from "@/contexts/AuthContext";
import * as ImagePicker from "expo-image-picker"; import * as ImagePicker from "expo-image-picker";
import { Platform } from "react-native"; import {Platform} from "react-native";
export const useChangeProfilePicture = () => { export const useChangeProfilePicture = (customUserId?: string) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { user, refreshProfileData } = useAuthContext(); const {user, refreshProfileData} = useAuthContext();
return useMutation({ return useMutation({
mutationKey: ["changeProfilePicture"], mutationKey: ["changeProfilePicture"],
@ -38,10 +38,12 @@ export const useChangeProfilePicture = () => {
const downloadURL = await reference.getDownloadURL(); const downloadURL = await reference.getDownloadURL();
console.log("Download URL:", downloadURL); console.log("Download URL:", downloadURL);
if(!customUserId) {
await firestore() await firestore()
.collection("Profiles") .collection("Profiles")
.doc(user?.uid) .doc(user?.uid)
.update({ pfp: downloadURL }); .update({pfp: downloadURL});
}
} catch (e) { } catch (e) {
console.error("Error uploading profile picture:", e); console.error("Error uploading profile picture:", e);
@ -50,8 +52,10 @@ export const useChangeProfilePicture = () => {
}, },
onSuccess: () => { onSuccess: () => {
// Invalidate queries to refresh profile data // Invalidate queries to refresh profile data
if (!customUserId) {
queryClient.invalidateQueries("Profiles"); queryClient.invalidateQueries("Profiles");
refreshProfileData(); refreshProfileData();
}
}, },
}); });
}; };

View File

@ -0,0 +1,62 @@
import {useState} from "react";
import * as ImagePicker from "expo-image-picker";
import {useChangeProfilePicture} from "@/hooks/firebase/useChangeProfilePicture";
import {useUpdateUserData} from "@/hooks/firebase/useUpdateUserData";
export const useUploadProfilePicture = (customUserId?: string, existingPfp?: string) => {
const [profileImage, setProfileImage] = useState<
string | ImagePicker.ImagePickerAsset | null
>(existingPfp || null);
const [profileImageAsset, setProfileImageAsset] = useState<
ImagePicker.ImagePickerAsset | null
>(null);
const {mutateAsync: updateUserData} = useUpdateUserData();
const {mutateAsync: changeProfilePicture} = useChangeProfilePicture(customUserId);
const pickImage = async () => {
const permissionResult =
await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!permissionResult.granted) {
alert("Permission to access camera roll is required!");
return;
}
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});
if (!result.canceled) {
setProfileImage(result.assets[0].uri);
setProfileImageAsset(result.assets[0]);
if (!customUserId) {
await changeProfilePicture(result.assets[0]);
}
}
};
const handleClearImage = async () => {
if (!customUserId) {
await updateUserData({newUserData: {pfp: null}});
}
setProfileImage(null);
};
const pfpUri =
profileImage && typeof profileImage === "object" && "uri" in profileImage
? profileImage.uri
: profileImage;
return {
pfpUri,
profileImage,
profileImageAsset,
handleClearImage,
pickImage,
changeProfilePicture
}
}