Fixes and tickets
This commit is contained in:
+345
-104
@@ -1,23 +1,32 @@
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import * as AppleAuthentication from "expo-apple-authentication";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
FlatList,
|
||||
KeyboardAvoidingView,
|
||||
Modal,
|
||||
Platform,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
} from "react-native";
|
||||
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
|
||||
import { BlurView } from "expo-blur";
|
||||
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 COUNTRIES from "../constants/countries";
|
||||
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 } from "../navigation/NavigationService";
|
||||
import { navigate, reset } from "../navigation/NavigationService";
|
||||
import { Palette } from "../styles";
|
||||
import { FONT_FAMILY } from "../styles/Fonts";
|
||||
|
||||
@@ -33,6 +42,23 @@ const Register = () => {
|
||||
const [isCountryModalVisible, setIsCountryModalVisible] = useState(false);
|
||||
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) => {
|
||||
@@ -51,7 +77,7 @@ const Register = () => {
|
||||
return COUNTRIES;
|
||||
}
|
||||
return COUNTRIES.filter((country) =>
|
||||
country.name.toLowerCase().includes(query)
|
||||
country.name.toLowerCase().includes(query),
|
||||
);
|
||||
}, [countrySearch]);
|
||||
|
||||
@@ -73,6 +99,118 @@ const Register = () => {
|
||||
setCountrySearch("");
|
||||
};
|
||||
|
||||
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 }}>
|
||||
<View style={{ gap: 12 }}>
|
||||
<Input
|
||||
placeholder="Prénom"
|
||||
label="Prénom"
|
||||
isBlur
|
||||
value={firstName}
|
||||
setValue={setFirstName}
|
||||
/>
|
||||
<Input
|
||||
placeholder="Nom"
|
||||
label="Nom"
|
||||
isBlur
|
||||
value={lastName}
|
||||
setValue={setLastName}
|
||||
/>
|
||||
<View style={styles.countryField}>
|
||||
<Text style={styles.inputLabel}>Pays</Text>
|
||||
<BlurView
|
||||
tint="dark"
|
||||
style={[
|
||||
styles.countryBlurWrapper,
|
||||
selectedCountry ? styles.countryButtonFilled : null,
|
||||
]}
|
||||
>
|
||||
<Pressable
|
||||
style={({ pressed }) => [
|
||||
styles.countryButton,
|
||||
pressed ? styles.countryButtonPressed : null,
|
||||
]}
|
||||
onPress={() => setIsCountryModalVisible(true)}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
styles.countryButtonText,
|
||||
!selectedCountry && styles.countryButtonPlaceholder,
|
||||
]}
|
||||
>
|
||||
{selectedCountry ? selectedCountry.name : "Choisis ton pays"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</BlurView>
|
||||
</View>
|
||||
<Input
|
||||
placeholder="Ville"
|
||||
label="Ville"
|
||||
isBlur
|
||||
value={city}
|
||||
setValue={setCity}
|
||||
/>
|
||||
</View>
|
||||
<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(),
|
||||
lastName: lastName.trim(),
|
||||
city: city.trim(),
|
||||
country: selectedCountry,
|
||||
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>
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<Page
|
||||
width={isWeb ? 600 : null}
|
||||
@@ -81,103 +219,39 @@ const Register = () => {
|
||||
title="Inscription"
|
||||
>
|
||||
<View style={styles.pageContent}>
|
||||
<ItemContainer height={680} disableKeyboardHeight>
|
||||
<View style={styles.formContent}>
|
||||
<Text style={styles.title}>Renseigne tes informations</Text>
|
||||
{preferredLanguage && (
|
||||
<Text style={styles.languageInfo}>
|
||||
Langue choisie :{" "}
|
||||
<Text style={styles.languageInfoValue}>
|
||||
{preferredLanguage === "fr" ? "Français" : "English"}
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
<View style={{ gap: 16 }}>
|
||||
<View style={{ gap: 12 }}>
|
||||
<Input
|
||||
placeholder="Prénom"
|
||||
label="Prénom"
|
||||
isBlur
|
||||
value={firstName}
|
||||
setValue={setFirstName}
|
||||
/>
|
||||
<Input
|
||||
placeholder="Nom"
|
||||
label="Nom"
|
||||
isBlur
|
||||
value={lastName}
|
||||
setValue={setLastName}
|
||||
/>
|
||||
<View style={styles.countryField}>
|
||||
<Text style={styles.inputLabel}>Pays</Text>
|
||||
<Pressable
|
||||
style={[
|
||||
styles.countryButton,
|
||||
selectedCountry ? styles.countryButtonFilled : null,
|
||||
]}
|
||||
onPress={() => setIsCountryModalVisible(true)}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
styles.countryButtonText,
|
||||
!selectedCountry && styles.countryButtonPlaceholder,
|
||||
]}
|
||||
>
|
||||
{selectedCountry
|
||||
? selectedCountry.name
|
||||
: "Choisis ton pays"}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
<Input
|
||||
placeholder="Ville"
|
||||
label="Ville"
|
||||
isBlur
|
||||
value={city}
|
||||
setValue={setCity}
|
||||
/>
|
||||
</View>
|
||||
<Input
|
||||
placeholder="Adresse mail"
|
||||
label="Adresse mail"
|
||||
isBlur
|
||||
type="email"
|
||||
value={email}
|
||||
setValue={setEmail}
|
||||
/>
|
||||
</View>
|
||||
<BorderGradientButton
|
||||
title="Créer mon compte"
|
||||
containerStyle={{
|
||||
width: "80%",
|
||||
alignSelf: "center",
|
||||
}}
|
||||
onPress={() =>
|
||||
navigate(Routes.CreatePassword, {
|
||||
email: email.trim(),
|
||||
firstName: firstName.trim(),
|
||||
lastName: lastName.trim(),
|
||||
city: city.trim(),
|
||||
country: selectedCountry,
|
||||
preferredLanguage,
|
||||
})
|
||||
}
|
||||
disabled={!isFormValid}
|
||||
/>
|
||||
<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>
|
||||
<Pressable onPress={() => navigate(Routes.Login)}>
|
||||
<Text style={styles.loginText}>
|
||||
Tu as déjà un compte?{" "}
|
||||
<Text style={styles.loginLink}>Se connecter</Text>
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
<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 style={styles.bottomLoginPrompt}>
|
||||
<Text style={styles.bottomFooterText}>
|
||||
Tu as déjà un compte ?{" "}
|
||||
<Text
|
||||
style={styles.bottomFooterLink}
|
||||
onPress={() => navigate(Routes.Login)}
|
||||
>
|
||||
Se connecter
|
||||
</Text>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Modal
|
||||
transparent
|
||||
@@ -224,6 +298,76 @@ const Register = () => {
|
||||
);
|
||||
};
|
||||
|
||||
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({
|
||||
@@ -232,6 +376,22 @@ const styles = StyleSheet.create({
|
||||
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,
|
||||
@@ -251,17 +411,19 @@ const styles = StyleSheet.create({
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
},
|
||||
countryButton: {
|
||||
countryBlurWrapper: {
|
||||
borderRadius: 12,
|
||||
borderWidth: 1,
|
||||
borderColor: Palette.ultraLightWhite,
|
||||
backgroundColor: Palette.glass,
|
||||
overflow: "hidden",
|
||||
},
|
||||
countryButton: {
|
||||
minHeight: 50,
|
||||
justifyContent: "center",
|
||||
paddingHorizontal: 16,
|
||||
width: "100%",
|
||||
},
|
||||
countryButtonFilled: {
|
||||
borderColor: Palette.primary,
|
||||
countryButtonPressed: {
|
||||
opacity: 0.85,
|
||||
},
|
||||
countryButtonText: {
|
||||
fontSize: 14,
|
||||
@@ -297,6 +459,85 @@ const styles = StyleSheet.create({
|
||||
loginLink: {
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
},
|
||||
bottomLoginPrompt: {
|
||||
marginTop: 16,
|
||||
paddingHorizontal: 24,
|
||||
},
|
||||
bottomFooterText: {
|
||||
fontSize: 14,
|
||||
color: Palette.white,
|
||||
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
|
||||
textAlign: "center",
|
||||
},
|
||||
bottomFooterLink: {
|
||||
fontFamily: FONT_FAMILY.InterSemiBold,
|
||||
color: Palette.white,
|
||||
},
|
||||
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",
|
||||
},
|
||||
modalOverlay: {
|
||||
flex: 1,
|
||||
backgroundColor: Palette.transparentBlack,
|
||||
|
||||
Reference in New Issue
Block a user