306 lines
7.5 KiB
JavaScript
306 lines
7.5 KiB
JavaScript
import * as ImagePicker from "expo-image-picker";
|
|
import { Pressable, Text } from "react-native";
|
|
import useMinuit from "react-native-minuit/src/hooks/useMinuit.js";
|
|
import React, { useGlobal } from "reactn";
|
|
|
|
import { responsiveWidth } from "../actions/responsiveSizes.js";
|
|
import Page from "../layouts/Page";
|
|
|
|
import alert from "../components/Alert.js";
|
|
import Avatar from "../components/Avatar";
|
|
import InputRow from "../components/InputRow";
|
|
import ItemRowList from "../components/ItemRowList.js";
|
|
|
|
import firebase, { usersRef } from "../config/firebase";
|
|
|
|
import { uploadFileToFirebase } from "../helpers/uploadToFirebase";
|
|
import { Routes } from "../navigation/Routes.js";
|
|
import { Fonts, gutters, Palette, Style } from "../styles";
|
|
|
|
import { useUserData } from "../providers/UserDataProvider.js";
|
|
|
|
export default ({ navigation }) => {
|
|
const { setIsLoading, setTooltip } = useMinuit();
|
|
const { onSignOut } = useUserData();
|
|
|
|
const [currentUID] = useGlobal("currentUID");
|
|
const [currentUserData] = useGlobal("currentUserData");
|
|
|
|
const settingsList = [
|
|
{
|
|
title: "Nom du compte",
|
|
key: "name",
|
|
value: currentUserData?.name || "",
|
|
type: "string",
|
|
},
|
|
{
|
|
title: "Adresse email",
|
|
key: "email",
|
|
value: currentUserData?.email || "",
|
|
type: "string",
|
|
},
|
|
{
|
|
title: "Mot de passe",
|
|
key: "password",
|
|
value: "",
|
|
type: "string",
|
|
},
|
|
{
|
|
title: "Notifications push",
|
|
key: "notifications",
|
|
value: !!currentUserData?.notifications,
|
|
type: "boolean",
|
|
},
|
|
{
|
|
title: "Notifications par email",
|
|
key: "emailNotifications",
|
|
value: !!currentUserData?.emailNotifications,
|
|
type: "boolean",
|
|
},
|
|
{
|
|
title: "Langue",
|
|
key: "language",
|
|
value: currentUserData?.language || "",
|
|
type: "string",
|
|
},
|
|
];
|
|
|
|
const destructiveSettingsList = [
|
|
{
|
|
title: "Supprimer mon compte",
|
|
action: () => onDeleteUserAccount(),
|
|
textStyle: {
|
|
color: Palette.red,
|
|
},
|
|
},
|
|
].filter(({ condition = true }) => condition);
|
|
|
|
const onChangePicture = async () => {
|
|
try {
|
|
setIsLoading(true);
|
|
|
|
let result = await ImagePicker.launchImageLibraryAsync({
|
|
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
|
allowsEditing: true,
|
|
aspect: [4, 4],
|
|
quality: 1,
|
|
});
|
|
|
|
if (result?.assets?.[0]?.uri) {
|
|
const { resultURI = null } = await uploadFileToFirebase({
|
|
uri: result?.assets?.[0]?.uri,
|
|
path: `users/${currentUID}/profilePicture.png`,
|
|
});
|
|
|
|
if (resultURI) {
|
|
await usersRef.doc(currentUID).update({
|
|
profilePictureURL: resultURI,
|
|
});
|
|
|
|
await firebase.auth().currentUser.updateProfile({
|
|
photoURL: resultURI,
|
|
});
|
|
|
|
setTooltip({
|
|
type: "success",
|
|
text: "Photo de profil mise à jour",
|
|
});
|
|
} else {
|
|
throw new Error("Erreur changement photo de profil");
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
|
|
setTooltip({
|
|
type: "error",
|
|
text: error.message,
|
|
});
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const onUpdateValue = async ({
|
|
key,
|
|
value = null,
|
|
currentPassword = null,
|
|
}) => {
|
|
try {
|
|
setIsLoading(true);
|
|
const user = firebase.auth().currentUser;
|
|
|
|
const reauthenticateUser = async () => {
|
|
try {
|
|
const credential = firebase.auth.EmailAuthProvider.credential(
|
|
user?.email,
|
|
currentPassword
|
|
);
|
|
|
|
await user.reauthenticateWithCredential(credential);
|
|
} catch (error) {
|
|
throw new Error("Erreur authentification");
|
|
}
|
|
};
|
|
|
|
// Validate input except for booleans where false is allowed
|
|
const isInvalidString =
|
|
typeof value === "string" && value.trim().length === 0;
|
|
const isNullish = value === null || value === undefined;
|
|
if (isNullish || isInvalidString) {
|
|
throw new Error("Vérifiez les informations saisies");
|
|
}
|
|
|
|
if (key === "name") {
|
|
await user.updateProfile({
|
|
displayName: value,
|
|
});
|
|
}
|
|
|
|
if (["email", "password"].includes(key)) {
|
|
await reauthenticateUser();
|
|
|
|
if (key === "email") {
|
|
try {
|
|
await user.updateEmail(value);
|
|
} catch (e) {
|
|
throw new Error("Erreur changement email");
|
|
}
|
|
}
|
|
|
|
if (key === "password") {
|
|
try {
|
|
await user.updatePassword(value);
|
|
} catch (e) {
|
|
throw new Error("Erreur changement mot de passe");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (key !== "password") {
|
|
await usersRef.doc(currentUID).update({
|
|
[key]: value,
|
|
});
|
|
}
|
|
|
|
setTooltip({
|
|
type: "success",
|
|
text: "Modifications enregistrées",
|
|
});
|
|
} catch (error) {
|
|
console.log(error);
|
|
|
|
setTooltip({
|
|
type: "error",
|
|
text: error.message,
|
|
});
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const onDeleteUserAccount = async () => {
|
|
alert(
|
|
"Êtes-vous sûr?",
|
|
"La suppression de votre compte entraînera la suppression de toutes les données liées.",
|
|
[
|
|
{
|
|
text: "Annuler",
|
|
onPress: () => {},
|
|
style: "cancel",
|
|
},
|
|
{
|
|
text: "Confirmer",
|
|
onPress: async () => {
|
|
try {
|
|
setIsLoading(true);
|
|
|
|
await firebase
|
|
.functions()
|
|
.httpsCallable("users-deleteUserAccount")();
|
|
|
|
await onSignOut();
|
|
|
|
setTooltip({
|
|
type: "success",
|
|
text: "Compte supprimé avec succès!",
|
|
});
|
|
|
|
navigation.reset({
|
|
index: 0,
|
|
routes: [
|
|
{
|
|
name: Routes.Login,
|
|
},
|
|
],
|
|
});
|
|
} catch (error) {
|
|
setTooltip({
|
|
type: "error",
|
|
text: error.message,
|
|
});
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
},
|
|
style: "confirm",
|
|
},
|
|
],
|
|
{ cancelable: false }
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Page headerType="NAVIGATE" title={"Paramètres du compte"} scrollEnabled>
|
|
<Pressable
|
|
onPress={onChangePicture}
|
|
style={[Style.containerCenter, { marginBottom: gutters }]}
|
|
>
|
|
<Avatar
|
|
name={currentUserData?.name}
|
|
url={currentUserData?.profilePictureURL || null}
|
|
forceRawImage
|
|
size={responsiveWidth(30)}
|
|
containerStyle={{
|
|
marginBottom: gutters / 2,
|
|
...Style.defaultShadows,
|
|
}}
|
|
/>
|
|
<Text
|
|
style={Fonts({
|
|
type: "section",
|
|
style: { color: Palette.primary, textDecorationLine: "underline" },
|
|
})}
|
|
>
|
|
Modifier
|
|
</Text>
|
|
</Pressable>
|
|
|
|
{settingsList.map((setting) => {
|
|
const { title, key, value, type } = setting;
|
|
|
|
return (
|
|
<InputRow
|
|
key={key}
|
|
itemKey={key}
|
|
value={value}
|
|
type={type}
|
|
title={title}
|
|
onUpdateValue={onUpdateValue}
|
|
/>
|
|
);
|
|
})}
|
|
|
|
<ItemRowList
|
|
title={"Gérer mon abonnement"}
|
|
action={() => {}}
|
|
containerStyle={{}}
|
|
/>
|
|
|
|
{destructiveSettingsList.map((setting, index) => (
|
|
<ItemRowList key={index} {...setting} containerStyle={{}} />
|
|
))}
|
|
</Page>
|
|
);
|
|
};
|