116 lines
3.7 KiB
TypeScript
116 lines
3.7 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { StyleSheet, Alert, Image, TouchableOpacity } from 'react-native';
|
|
import { ThemedText, ThemedView } from '@/components/theme/Theme';
|
|
import { getUser, updateUser } from '@/components/services/SecureStore';
|
|
import { manipulateAsync, SaveFormat } from 'expo-image-manipulator';
|
|
import * as ImagePicker from 'expo-image-picker';
|
|
import { updateProfilePicture } from '@/constants/APIs';
|
|
import type { User } from '@/constants/Types';
|
|
|
|
type UserInfoProps = {
|
|
onPfpUpdate: (url: string) => void;
|
|
};
|
|
|
|
const UserInfo: React.FC<UserInfoProps> = ({ onPfpUpdate }) => {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
|
|
useEffect(() => {
|
|
const fetchUserData = async () => {
|
|
try {
|
|
const user: User = await getUser() as User;
|
|
setUser(user);
|
|
if (user.pfpUrl)
|
|
onPfpUpdate(user.pfpUrl);
|
|
} catch (error) {
|
|
console.error('Error fetching user data:', error);
|
|
Alert.alert('Error', 'Failed to fetch user data.');
|
|
}
|
|
};
|
|
fetchUserData();
|
|
}, [onPfpUpdate]);
|
|
|
|
const handleUpdateProfilePicture = async () => {
|
|
const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
|
if (permissionResult.granted === false) {
|
|
Alert.alert(
|
|
'Permission Required',
|
|
'You need to grant permission to access your photo library.'
|
|
);
|
|
return;
|
|
}
|
|
const result = await ImagePicker.launchImageLibraryAsync({
|
|
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
|
allowsEditing: true,
|
|
aspect: [4, 3],
|
|
quality: 1,
|
|
});
|
|
if (!result.canceled && result.assets[0].uri) {
|
|
try {
|
|
const manipulateResult = await manipulateAsync(
|
|
result.assets[0].uri,
|
|
[{resize: {width: 300, height: 300}}],
|
|
{compress: 0.7, format: SaveFormat.JPEG}
|
|
);
|
|
const user = await getUser() as User;
|
|
const updatedUser = await updateProfilePicture(user.id, manipulateResult.uri);
|
|
if (!updatedUser || !updatedUser.pfpUrl) throw new Error('Failed to update user profile picture.');
|
|
setUser(prevData => prevData ? {...prevData, pfpUrl: updatedUser.pfpUrl} as User : updatedUser as User);
|
|
await updateUser({pfpUrl: updatedUser.pfpUrl});
|
|
onPfpUpdate(updatedUser.pfpUrl);
|
|
} catch (error) {
|
|
console.error('Error updating profile picture:', error);
|
|
Alert.alert('Error', 'Failed to update profile picture.');
|
|
}
|
|
} else {
|
|
Alert.alert('Error', 'Failed to select an image.');
|
|
}
|
|
};
|
|
return (
|
|
<ThemedView style={styles.container}>
|
|
{user ? (
|
|
<ThemedView style={styles.profileContainer}>
|
|
<TouchableOpacity onPress={handleUpdateProfilePicture}>
|
|
<Image
|
|
source={user.pfpUrl ? {
|
|
uri: `${process.env.EXPO_PUBLIC_API_URL}${user.pfpUrl}`} :
|
|
require('@/assets/images/default-profile.png')}
|
|
style={styles.profilePicture}
|
|
/>
|
|
</TouchableOpacity>
|
|
<ThemedText style={styles.name}>{user.fullName}</ThemedText>
|
|
<ThemedText style={styles.email}>{user.email}</ThemedText>
|
|
</ThemedView>
|
|
) : (
|
|
<ThemedText>Loading user data...</ThemedText>
|
|
)}
|
|
</ThemedView>
|
|
);
|
|
};
|
|
export default UserInfo;
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
marginTop: 40,
|
|
},
|
|
profileContainer: {
|
|
alignItems: 'center',
|
|
marginTop: 20,
|
|
},
|
|
profilePicture: {
|
|
width: 100,
|
|
height: 100,
|
|
borderRadius: 50,
|
|
marginBottom: 10,
|
|
},
|
|
name: {
|
|
fontSize: 24,
|
|
fontWeight: 'bold',
|
|
marginBottom: 5,
|
|
},
|
|
email: {
|
|
fontSize: 16,
|
|
},
|
|
});
|