389 lines
10 KiB
JavaScript
389 lines
10 KiB
JavaScript
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||
import * as AppleAuthentication from "expo-apple-authentication";
|
||
import React, { useCallback, useEffect, useState } from "react";
|
||
import {
|
||
ActivityIndicator,
|
||
KeyboardAvoidingView,
|
||
Platform,
|
||
Pressable,
|
||
StyleSheet,
|
||
Text,
|
||
View,
|
||
} from "react-native";
|
||
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
|
||
import Svg, { Path } from "react-native-svg";
|
||
import { background } from "../assets";
|
||
import BorderGradientButton from "../components/BorderGradientButton";
|
||
import { Input } from "../components/Input";
|
||
import ItemContainer from "../components/ItemContainer/ItemContainer";
|
||
import firebase from "../config/firebase";
|
||
import { isWeb } from "../hooks/useLayoutType";
|
||
import useSocialAuth from "../hooks/useSocialAuth";
|
||
import Page from "../layouts/Page";
|
||
import { Routes } from "../navigation";
|
||
import { navigate, reset } from "../navigation/NavigationService";
|
||
import { Palette } from "../styles";
|
||
import { FONT_FAMILY } from "../styles/Fonts";
|
||
|
||
const LANGUAGE_STORAGE_KEY = "preferredLanguage";
|
||
|
||
const Register = () => {
|
||
const [email, setEmail] = useState("");
|
||
const [firstName, setFirstName] = useState("");
|
||
const [preferredLanguage, setPreferredLanguage] = useState(null);
|
||
|
||
const afterSocialAuth = useCallback(async () => {
|
||
const uid = firebase.auth().currentUser?.uid;
|
||
if (!uid) throw new Error("Aucun utilisateur après connexion");
|
||
reset({ index: 0, routes: [{ name: Routes.BottomTab }] });
|
||
}, []);
|
||
|
||
const {
|
||
signInWithGoogle,
|
||
signInWithApple,
|
||
isAppleSignInAvailable,
|
||
isLoading: socialLoading,
|
||
} = useSocialAuth({
|
||
onSuccess: afterSocialAuth,
|
||
});
|
||
|
||
const isBusy = socialLoading;
|
||
|
||
useEffect(() => {
|
||
AsyncStorage.getItem(LANGUAGE_STORAGE_KEY)
|
||
.then((storedLanguage) => {
|
||
if (storedLanguage) {
|
||
setPreferredLanguage(storedLanguage);
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.warn("Register: failed to load preferred language", error);
|
||
});
|
||
}, []);
|
||
|
||
const isFormValid = email.trim().length > 0 && firstName.trim().length > 0;
|
||
|
||
const renderFormContent = () => (
|
||
<View style={styles.formContent}>
|
||
<Text style={styles.title}>Renseigne tes informations</Text>
|
||
{preferredLanguage && !isWeb ? (
|
||
<Text style={styles.languageInfo}>
|
||
Langue choisie :{" "}
|
||
<Text style={styles.languageInfoValue}>
|
||
{preferredLanguage === "fr" ? "Français" : "English"}
|
||
</Text>
|
||
</Text>
|
||
) : null}
|
||
<View style={{ gap: 16 }}>
|
||
<Input
|
||
placeholder="Prénom"
|
||
label="Prénom"
|
||
isBlur
|
||
value={firstName}
|
||
setValue={setFirstName}
|
||
/>
|
||
<Input
|
||
placeholder="Adresse mail"
|
||
label="Adresse mail"
|
||
isBlur
|
||
type="email"
|
||
value={email}
|
||
setValue={setEmail}
|
||
/>
|
||
</View>
|
||
<BorderGradientButton
|
||
title="Créer mon compte"
|
||
containerStyle={{
|
||
width: "90%",
|
||
alignSelf: "center",
|
||
}}
|
||
onPress={() =>
|
||
navigate(Routes.CreatePassword, {
|
||
email: email.trim(),
|
||
firstName: firstName.trim(),
|
||
preferredLanguage,
|
||
})
|
||
}
|
||
disabled={!isFormValid || isBusy}
|
||
/>
|
||
<View style={styles.socialWrapper}>
|
||
{isAppleSignInAvailable ? (
|
||
<AppleAuthButton
|
||
onPress={signInWithApple}
|
||
disabled={isBusy}
|
||
loading={socialLoading}
|
||
/>
|
||
) : null}
|
||
<GoogleAuthButton
|
||
onPress={signInWithGoogle}
|
||
disabled={isBusy}
|
||
loading={socialLoading}
|
||
/>
|
||
</View>
|
||
<View style={styles.footer}>
|
||
<Text style={styles.terms}>
|
||
En t’inscrivant, tu acceptes nos conditions générales{"\n"}
|
||
d’utilisation et notre politique de confidentialité.
|
||
</Text>
|
||
</View>
|
||
<Text style={styles.bottomFooterText}>
|
||
Tu as déjà un compte ?{" "}
|
||
<Text
|
||
style={styles.bottomFooterLink}
|
||
onPress={() => navigate(Routes.Login)}
|
||
>
|
||
Se connecter
|
||
</Text>
|
||
</Text>
|
||
</View>
|
||
);
|
||
|
||
return (
|
||
<Page
|
||
width={isWeb ? 600 : null}
|
||
backgroundImg={isWeb ? background.loginBgWeb : background.homeBG}
|
||
headerType="NAVIGATION"
|
||
title="Inscription"
|
||
>
|
||
<View style={styles.pageContent}>
|
||
<ItemContainer
|
||
height={isWeb ? 720 : undefined}
|
||
disableKeyboardHeight
|
||
style={!isWeb ? styles.mobileItemContainer : styles.webItemContainer}
|
||
>
|
||
{isWeb ? (
|
||
renderFormContent()
|
||
) : (
|
||
<KeyboardAvoidingView
|
||
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
||
style={styles.mobileAvoider}
|
||
>
|
||
<KeyboardAwareScrollView
|
||
contentContainerStyle={styles.mobileScrollContent}
|
||
showsVerticalScrollIndicator={false}
|
||
keyboardShouldPersistTaps="handled"
|
||
>
|
||
{renderFormContent()}
|
||
</KeyboardAwareScrollView>
|
||
</KeyboardAvoidingView>
|
||
)}
|
||
</ItemContainer>
|
||
</View>
|
||
</Page>
|
||
);
|
||
};
|
||
|
||
const AppleAuthButton = ({ onPress, disabled, loading }) => {
|
||
if (isWeb) {
|
||
return null;
|
||
}
|
||
|
||
return (
|
||
<View style={styles.nativeButtonWrapper}>
|
||
<AppleAuthentication.AppleAuthenticationButton
|
||
buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_UP}
|
||
buttonStyle={AppleAuthentication.AppleAuthenticationButtonStyle.WHITE}
|
||
style={styles.nativeButton}
|
||
cornerRadius={12}
|
||
onPress={onPress}
|
||
disabled={disabled}
|
||
/>
|
||
{loading ? (
|
||
<View style={styles.nativeLoadingOverlay}>
|
||
<ActivityIndicator size="small" color={Palette.black} />
|
||
</View>
|
||
) : null}
|
||
</View>
|
||
);
|
||
};
|
||
|
||
const GoogleAuthButton = ({ onPress, disabled, loading }) => (
|
||
<Pressable
|
||
accessibilityRole="button"
|
||
onPress={onPress}
|
||
disabled={disabled}
|
||
style={({ pressed }) => [
|
||
styles.socialButton,
|
||
pressed && !disabled ? styles.socialButtonPressed : null,
|
||
disabled ? styles.socialButtonDisabled : null,
|
||
]}
|
||
>
|
||
<View style={styles.socialButtonContent}>
|
||
<View style={styles.socialIconContainer}>
|
||
<GoogleLogo />
|
||
</View>
|
||
<Text style={styles.socialButtonText}>Continuer avec Google</Text>
|
||
{loading ? (
|
||
<ActivityIndicator size="small" color="#4285F4" />
|
||
) : (
|
||
<View style={styles.socialRightSpacer} />
|
||
)}
|
||
</View>
|
||
</Pressable>
|
||
);
|
||
|
||
const GoogleLogo = () => (
|
||
<Svg width={24} height={24} viewBox="0 0 18 18">
|
||
<Path
|
||
fill="#4285F4"
|
||
d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.71v2.26h2.9c1.68-1.55 2.7-3.83 2.7-6.61Z"
|
||
/>
|
||
<Path
|
||
fill="#34A853"
|
||
d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.9-2.26c-.8.54-1.83.86-3.06.86a5.31 5.31 0 0 1-5.02-3.69H.96v2.32A9 9 0 0 0 9 18Z"
|
||
/>
|
||
<Path
|
||
fill="#FBBC05"
|
||
d="M3.98 10.73c-.18-.54-.28-1.12-.28-1.73s.1-1.19.28-1.73V4.95H.96A9 9 0 0 0 0 9c0 1.45.35 2.82.96 4.05l3.02-2.32Z"
|
||
/>
|
||
<Path
|
||
fill="#EA4335"
|
||
d="M9 3.54c1.32 0 2.5.45 3.43 1.33l2.57-2.57C13.47.9 11.43 0 9 0A9 9 0 0 0 .96 4.95l3.02 2.32A5.31 5.31 0 0 1 9 3.54Z"
|
||
/>
|
||
</Svg>
|
||
);
|
||
|
||
export default Register;
|
||
|
||
const styles = StyleSheet.create({
|
||
pageContent: {
|
||
flex: 1,
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
},
|
||
webItemContainer: {
|
||
width: "100%",
|
||
maxWidth: 680,
|
||
},
|
||
mobileItemContainer: {
|
||
width: "100%",
|
||
minHeight: 720,
|
||
},
|
||
mobileAvoider: {
|
||
flex: 1,
|
||
},
|
||
mobileScrollContent: {
|
||
flexGrow: 1,
|
||
justifyContent: "center",
|
||
paddingVertical: 24,
|
||
},
|
||
formContent: {
|
||
gap: 32,
|
||
paddingTop: 5,
|
||
paddingHorizontal: 5,
|
||
},
|
||
title: {
|
||
fontSize: 22,
|
||
color: Palette.white,
|
||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||
},
|
||
languageInfo: {
|
||
fontSize: 14,
|
||
color: Palette.gray,
|
||
fontFamily: FONT_FAMILY.InterRegular,
|
||
},
|
||
languageInfoValue: {
|
||
color: Palette.white,
|
||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||
},
|
||
footer: {
|
||
alignItems: "center",
|
||
gap: 4,
|
||
},
|
||
terms: {
|
||
fontSize: 12,
|
||
color: Palette.gray,
|
||
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||
textAlign: "center",
|
||
},
|
||
loginText: {
|
||
fontSize: 14,
|
||
color: Palette.white,
|
||
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||
},
|
||
loginLink: {
|
||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||
},
|
||
bottomLoginPrompt: {
|
||
marginTop: 16,
|
||
paddingHorizontal: 24,
|
||
marginBottom: 30,
|
||
},
|
||
bottomFooterText: {
|
||
fontSize: 15,
|
||
color: Palette.white,
|
||
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||
textAlign: "center",
|
||
},
|
||
bottomFooterLink: {
|
||
fontFamily: FONT_FAMILY.InterBold,
|
||
color: Palette.white,
|
||
fontSize: 16,
|
||
},
|
||
socialWrapper: {
|
||
width: "100%",
|
||
gap: 16,
|
||
alignItems: "center",
|
||
},
|
||
socialButton: {
|
||
alignSelf: "center",
|
||
borderRadius: 12,
|
||
width: "90%",
|
||
|
||
backgroundColor: Palette.white,
|
||
borderWidth: 1,
|
||
borderColor: "#E3E7EF",
|
||
paddingVertical: 12,
|
||
paddingHorizontal: 20,
|
||
shadowColor: "rgba(12, 6, 34, 0.08)",
|
||
shadowOffset: { width: 0, height: 8 },
|
||
shadowOpacity: 0.3,
|
||
shadowRadius: 16,
|
||
elevation: 2,
|
||
},
|
||
socialButtonPressed: {
|
||
backgroundColor: "#F4F7FF",
|
||
},
|
||
socialButtonDisabled: {
|
||
opacity: 0.7,
|
||
},
|
||
socialButtonContent: {
|
||
flexDirection: "row",
|
||
alignItems: "center",
|
||
justifyContent: "space-between",
|
||
gap: 12,
|
||
},
|
||
socialIconContainer: {
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
width: 28,
|
||
height: 28,
|
||
},
|
||
socialButtonText: {
|
||
flex: 1,
|
||
textAlign: "center",
|
||
fontSize: 15,
|
||
color: "#202124",
|
||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||
},
|
||
socialRightSpacer: {
|
||
width: 24,
|
||
height: 24,
|
||
},
|
||
nativeButtonWrapper: {
|
||
alignSelf: "center",
|
||
width: "90%",
|
||
height: 50,
|
||
justifyContent: "center",
|
||
},
|
||
nativeButton: {
|
||
width: "100%",
|
||
height: 50,
|
||
},
|
||
nativeLoadingOverlay: {
|
||
...StyleSheet.absoluteFillObject,
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
},
|
||
});
|