Skip to content

Commit

Permalink
fix: front part
Browse files Browse the repository at this point in the history
  • Loading branch information
YoanRos committed Sep 3, 2024
1 parent 408bf10 commit 90ea53f
Show file tree
Hide file tree
Showing 19 changed files with 931 additions and 168 deletions.
10 changes: 7 additions & 3 deletions api/src/controllers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,40 @@ router.post(
"/signup",
catchErrors(async (req, res) => {
const { email, password, matomoId } = req.body || {};
console.log("signup", email, password, matomoId);
if (!matomoId) return res.status(400).json({ ok: false, error: "no matomo id" });

if (!email || !password) {
return res.status(400).json({ ok: false, error: "missing email or password" });
}

console.log("validator.isEmail(email)", validator.isEmail(email));
if (!validator.isEmail(email)) {
return res.status(400).json({ ok: false, error: "invalid email" });
}
console.log("validatePassword(password)", validatePassword(password));
if (!validatePassword(password)) {
return res.status(400).json({ ok: false, error: "password is not strong enough" });
}
const user = await prisma.user.findUnique({
where: { email },
});
console.log("user", user);

if (user) {
return res.status(400).json({ ok: false, error: "email already exists" });
}

const hashedPassword = await bcrypt.hash(password, 10);
const updateObj = {};
updateObj.email = email;
updateObj.password = hashedPassword;

await prisma.user.upsert({
where: { matomo_id: matomoId },
update: updateObj,
create: {
email,
password: hashedPassword,
matomo_id: matomoId,
created_from,
...updateObj,
},
});
Expand Down
16 changes: 16 additions & 0 deletions expo/src/Router.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ import SuccessStrategyModal from "./scenes/Craving/SuccessStrategyModal";
import ExportedDataDone from "./scenes/Craving/ExportedDataDone";
import SigninScreen from "./scenes/Auth/Signin";
import SignupScreen from "./scenes/Auth/Signup";
import EmailConfirmationScreen from "./scenes/WelcomeScreen/EmailConfirmationScreen";
import ForgotPassword from "./scenes/Auth/ForgotPassword";
import ReinitialisePassword from "./scenes/Auth/ReinitialisePassword";
import ChangeAccountModal from "./scenes/Infos/ChangeAccountModal";

const Label = ({ children, focused, color }) => (
<LabelStyled focused={focused} color={color}>
Expand Down Expand Up @@ -180,6 +184,9 @@ const App = () => {
<AppStack.Navigator screenOptions={{ headerShown: false }} initialRouteName={initialRouteName}>
<AppStack.Screen name="SIGNIN_SCREEN" component={SigninScreen} />
<AppStack.Screen name="SIGNUP_SCREEN" component={SignupScreen} />
<AppStack.Screen name="EMAIL_CONFIRMATION" component={EmailConfirmationScreen} />
<AppStack.Screen name="FORGOT_PASSWORD" component={ForgotPassword} />
<AppStack.Screen name="REINITIALISE_PASSWORD" component={ReinitialisePassword} />
<AppStack.Screen name="WELCOME" component={WelcomeScreen} />
<AppStack.Screen name="USER_SURVEY_START" component={UserSurveyStart} />
<AppStack.Screen name="USER_SURVEY_FROM_ONBOARDING" component={UserSurvey} />
Expand Down Expand Up @@ -365,6 +372,15 @@ const Router = () => {
animation: "fade",
}}
/>
<ModalsStack.Screen
name="CHANGE_ACCOUNT"
component={ChangeAccountModal}
options={{
headerShown: false,
contentStyle: { backgroundColor: "rgba(0,0,0,0.3)" },
animation: "fade",
}}
/>
<ModalsStack.Screen
name="NPS_SCREEN"
component={NPSScreen}
Expand Down
Binary file modified expo/src/assets/illustrations/screen_craving.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions expo/src/components/illustrations/icons/AccountGearIcon.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions expo/src/scenes/Auth/ForgotPassword.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useEffect, useState } from "react";
import { View, TextInput, TouchableOpacity, Text, SafeAreaView, KeyboardAvoidingView, Platform } from "react-native";
import API from "../../services/api";
import { storage } from "../../services/storage";
import AntDesign from "@expo/vector-icons/AntDesign";
import Entypo from "@expo/vector-icons/Entypo";
import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";

const ForgotPassword = ({ navigation }) => {
const [email, setEmail] = useState("");
const [validEmail, setValidEmail] = useState(false);
const [isButtonDisabled, setIsButtonDisabled] = useState(true);

const handleEmailChange = (text) => {
setEmail(text);
const emailRegex = new RegExp("^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$");
setValidEmail(emailRegex.test(text));
};

useEffect(() => {
setIsButtonDisabled(!validEmail);
}, [validEmail]);

return (
<SafeAreaView className="bg-[#3E309F] w-full h-full px-5">
<KeyboardAvoidingView enabled behavior={Platform.select({ ios: "padding", android: null })}>
<View className="flex px-10 space-y-10 mt-10 ">
<Text className="text-start text-white text-2xl font-bold">Réinitialiser mon mot de passe</Text>

<Text className="text-white text-sm">
Renseignez ci-dessous l’adresse e-mail utilisée pour vous connecter à votre compte Oz.
</Text>

<View className="flex space-y-3">
<Text className=" text-white text-lg font-bold">E-mail</Text>
<TextInput
placeholder="Renseignez votre adresse e-mail"
autoCapitalize="none"
value={email}
onChangeText={handleEmailChange}
className="bg-white rounded-md p-3"
autoCorrect={false}
/>
</View>
</View>
<View className="flex mt-10 items-center">
<TouchableOpacity
// onPress={signup}
onPress={() => navigation.navigate("EMAIL_CONFIRMATION")}
className={`rounded-full px-6 py-3 ${isButtonDisabled ? "bg-[#EA6C96]" : "bg-[#de285e]"}`}
disabled={isButtonDisabled}
>
<Text className="text-center text-white text-xl font-bold">Valider</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
};

export default ForgotPassword;
140 changes: 140 additions & 0 deletions expo/src/scenes/Auth/ReinitialisePassword.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React, { useEffect, useState } from "react";
import { View, TextInput, TouchableOpacity, Text, SafeAreaView, KeyboardAvoidingView, Platform } from "react-native";
import AntDesign from "@expo/vector-icons/AntDesign";
import Entypo from "@expo/vector-icons/Entypo";
import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";

const ReinitialisePassword = ({ navigation }) => {
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [isStrongPassword, setIsStrongPassword] = useState(false);
const [isMatching, setIsMatching] = useState(false);
const [isButtonDisabled, setIsButtonDisabled] = useState(true);
const [hidePassword, setHidePassword] = useState(true);
const [passwordChecks, setPasswordChecks] = useState({
minLength: false,
hasUpperCase: false,
hasLowerCase: false,
hasNumber: false,
hasSpecialChar: false,
});

const checkPassword = (password) => {
const checks = {
minLength: password.length >= 12,
hasUpperCase: /[A-Z]/.test(password),
hasLowerCase: /[a-z]/.test(password),
hasNumber: /[0-9]/.test(password),
hasSpecialChar: /[!@#\$%\^&\*]/.test(password),
};
setPasswordChecks(checks);
setIsStrongPassword(Object.values(checks).every((check) => check));
setIsMatching(password === confirmPassword);
};

const handleConfirmPasswordChange = (text) => {
setConfirmPassword(text);
setIsMatching(password === text);
};

useEffect(() => {
if (isStrongPassword && isMatching) {
setIsButtonDisabled(false);
} else {
setIsButtonDisabled(true);
}
console.log("isStrongPassword", isStrongPassword);
console.log("isMatching", isMatching);
}, [isStrongPassword, isMatching]);

const numberOfChecksPassed = Object.values(passwordChecks).filter(Boolean).length;

return (
<SafeAreaView className="bg-[#3E309F] w-full h-full px-5">
<KeyboardAvoidingView enabled behavior={Platform.select({ ios: "padding", android: null })}>
<View className="flex px-10 space-y-10 mt-10 ">
<Text className="text-start text-white text-2xl font-bold">Réinitialiser mon mot de passe</Text>
<Text className="text-white text-sm">Entrez ci-dessous votre nouveau mot de passe.</Text>
<View className="flex space-y-3">
<Text className=" text-white text-lg font-bold">Mot de passe</Text>
<Text className="text-white text-sm">
doit contenir au minimum 12 caractères, 1 Majuscule, 1 chiffre, 1 caractère spécial
</Text>
<View className="bg-white rounded-md p-3 flex flex-row items-center">
<TextInput
placeholder="Renseignez le même mot de passe"
value={password}
onChangeText={(text) => {
setPassword(text);
checkPassword(text);
}}
secureTextEntry={hidePassword}
className="text-black flex-1"
/>
<TouchableOpacity className="" onPress={() => setHidePassword(!hidePassword)}>
{hidePassword ? (
<MaterialCommunityIcons name="eye-outline" size={24} color="#3E309F" />
) : (
<MaterialCommunityIcons name="eye-off-outline" size={24} color="#3E309F" />
)}
</TouchableOpacity>
</View>
<View className="flex flex-row justify-between mt-2">
{[...Array(5)].map((_, index) => (
<View
key={index}
className={`h-1 flex-1 mx-0.5 rounded-xl ${
index < numberOfChecksPassed ? "bg-green-500" : "bg-gray-300"
}`}
/>
))}
</View>
</View>
<View className="flex space-y-3">
<Text className=" text-white text-xl font-bold mb-1">Confirmation du mot de passe</Text>
<View className="bg-white rounded-md p-3 flex flex-row items-center">
<TextInput
placeholder="Renseignez le même mot de passe"
value={confirmPassword}
onChangeText={handleConfirmPasswordChange}
secureTextEntry={hidePassword}
className="text-black flex-1"
/>
<TouchableOpacity className="" onPress={() => setHidePassword(!hidePassword)}>
{hidePassword ? (
<MaterialCommunityIcons name="eye-outline" size={24} color="#3E309F" />
) : (
<MaterialCommunityIcons name="eye-off-outline" size={24} color="#3E309F" />
)}
</TouchableOpacity>
</View>
{confirmPassword && (
<View className="flex items-center flex-row justify-end space-x-1">
{isMatching ? (
<AntDesign name="checkcircleo" size={15} color="#39CEC1" />
) : (
<Entypo name="circle-with-cross" size={15} color="#FF0000" />
)}
<Text className="text-white text-sm">
{isMatching ? "Mots de passe similaires" : "Mots de passe différents"}
</Text>
</View>
)}
</View>
</View>
<View className="flex mt-10 items-center">
<TouchableOpacity
// onPress={signup}
onPress={() => navigation.push("TABS")}
className={`rounded-full px-6 py-3 ${isButtonDisabled ? "bg-[#EA6C96]" : "bg-[#de285e]"}`}
// disabled={isButtonDisabled}
>
<Text className="text-center text-white text-xl font-bold">Valider</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
};

export default ReinitialisePassword;
Loading

0 comments on commit 90ea53f

Please sign in to comment.