From b624f33e9988e7ffc34c7cf0e2a8ddcb87578ab6 Mon Sep 17 00:00:00 2001 From: Elhoucine Azayou Date: Tue, 18 Jun 2024 13:45:37 +0200 Subject: [PATCH] feat(#478): responsive login MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Page accueil - Page connexion famille - Page connexion prof - Page inscription - Page réinitialisation mot de passe - Utilisateur validé - Améliorations --- src/components/accueil/NewHome.tsx | 177 ++++++++++++++------ src/pages/connexion.tsx | 257 ++++++++++++++++++----------- src/pages/inscription.tsx | 235 ++++++++++++++------------ src/pages/login.tsx | 205 ++++++++++++++--------- src/pages/reset-password.tsx | 173 +++++++++++-------- src/pages/user-verified.tsx | 151 ++++++++++------- src/styles/globals.scss | 6 + 7 files changed, 736 insertions(+), 468 deletions(-) diff --git a/src/components/accueil/NewHome.tsx b/src/components/accueil/NewHome.tsx index a68f3fd46..75c678a82 100644 --- a/src/components/accueil/NewHome.tsx +++ b/src/components/accueil/NewHome.tsx @@ -1,9 +1,8 @@ import { useRouter } from 'next/router'; import React from 'react'; -import { Button } from '@mui/material'; +import { Box, Button, Grid, Typography } from '@mui/material'; -import { KeepRatio } from '../KeepRatio'; import Home from 'src/svg/home.svg'; import Logo from 'src/svg/logo_1village.svg'; import School from 'src/svg/school.svg'; @@ -19,62 +18,130 @@ export function isRedirectValid(redirect: string) { return false; } } +interface LoginBoxProps { + title: string; + subTitle: string; + route: string; + Icon: React.ComponentType>; +} -export const NewHome = () => { +const LoginBox: React.FC = ({ title, subTitle, route, Icon }) => { const router = useRouter(); return ( -
- <> -
- -

Vous êtes...

-
- -
- {/* Block Teacher */} -
-

Professeur des écoles

- { - router.push('/login'); - }} - /> - -
- {/* Block Parent */} -
-

Parent d'élève

- { - router.push('/connexion'); - }} - /> - -
-
-
- -
+ + + {title} + + + { + router.push(`/${route}`); + }} + /> + + + + ); +}; + +export const NewHome = () => { + return ( + + + + + + + + + + + Vous êtes: + + + + + + + + + + + + + ); }; diff --git a/src/pages/connexion.tsx b/src/pages/connexion.tsx index ff3df9ce2..89f9f8bc0 100644 --- a/src/pages/connexion.tsx +++ b/src/pages/connexion.tsx @@ -3,9 +3,22 @@ import React from 'react'; import Visibility from '@mui/icons-material/Visibility'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; -import { Button, Checkbox, FormControl, FormControlLabel, IconButton, Input, InputAdornment, InputLabel, Link, TextField } from '@mui/material'; +import { + Box, + Button, + Checkbox, + FormControl, + FormControlLabel, + Grid, + IconButton, + Input, + InputAdornment, + InputLabel, + Link, + TextField, + Typography, +} from '@mui/material'; -import { KeepRatio } from '../components/KeepRatio'; import { isRedirectValid } from '../components/accueil/NewHome'; import { UserContext } from 'src/contexts/userContext'; import { useUserRequests } from 'src/services/useUsers'; @@ -25,6 +38,7 @@ const SignInParent = () => { const [isError, setIsError] = React.useState(false); const [isEmailError, setIsEmailError] = React.useState(false); const [isEmailSent, setIsEmailSent] = React.useState(false); + const [isProgress, setIsProgress] = React.useState(false); const { resendVerificationEmail } = useUserRequests(); @@ -42,6 +56,7 @@ const SignInParent = () => { e.preventDefault(); if (emailRef.current === null || passwordRef.current === null || rememberRef.current === undefined) return; //This is for Typescript compiler but useless alone if (emailRef.current.value === '' || passwordRef.current.value === '') return; //This is to unabled submit if no data + setIsProgress(true); login(emailRef.current.value, passwordRef.current.value, rememberRef.current.checked) .then((response) => { if (response.success) { @@ -51,61 +66,103 @@ const SignInParent = () => { setErrorCode(response.errorCode || 1); setIsError(true); } + setIsProgress(false); }) .catch((error) => { console.error(error); + setIsProgress(false); }); }; return ( - <> -
-
+ + - { router.push('/'); }} sx={{ - placeSelf: 'flex-start', - marginRight: '1rem', - fontSize: '0.875rem', + cursor: 'pointer', + width: 'fit-content', + height: 'auto', + margin: { + xs: '10px 0', + sm: '0 10px', + }, + alignSelf: 'center', }} > - - -

Parent d'élèves

- { - router.push('/'); - }} - sx={{ - placeSelf: 'center end', - marginRight: '1rem', - fontSize: '0.875rem', - }} - > - Village en classe - -
- -
-

Se connecter

-
+ + + + + { + router.push('/'); + }} + sx={{ + placeSelf: 'center end', + marginRight: '1rem', + fontSize: '0.875rem', + }} + > + Village en classe + + + + + + + Parent d'élèves + + + + Se connecter + + { inputRef={emailRef} onChange={() => (errorCode !== -1 ? setErrorCode(-1) : null)} //reset error code sx={{ - width: '30ch', + width: '100%', mb: '1rem', }} /> - + Mot de passe @@ -140,7 +197,8 @@ const SignInParent = () => { } /> - {isError ? errorMessages[errorCode] : null} + + {isError ? errorMessages[errorCode] : null} {errorCode === 3 && ( { @@ -157,7 +215,7 @@ const SignInParent = () => { onClick={() => { router.push('/reset-password'); }} - style={{ color: 'tomato', fontWeight: 'bold' }} + style={{ color: 'tomato', fontWeight: 'bold', textAlign: 'left' }} > identifiants invalides @@ -181,60 +239,67 @@ const SignInParent = () => { {isEmailError && Email incorrect} - -
-
- } - /> - { - router.push('/reset-password'); - }} - sx={{ - display: 'inline-block', - lineHeight: '1.5', - justifySelf: 'end', - textDecoration: 'underline', - }} - > - Mot de passe oublié ? - -
- -
+
- { - router.push('/inscription'); - }} - sx={{ - fontSize: '0.875rem', - mt: 2, - }} - > - Créer un compte - -
-
-
- + + { + router.push('/reset-password'); + }} + sx={{ + display: 'inline-block', + lineHeight: '1.5', + justifySelf: 'end', + textDecoration: 'underline', + }} + > + Mot de passe oublié ? + + + { + router.push('/inscription'); + }} + sx={{ + fontSize: '0.875rem', + mt: 2, + }} + > + Créer un compte + + + + + + ); }; diff --git a/src/pages/inscription.tsx b/src/pages/inscription.tsx index b27796b57..20c51326d 100644 --- a/src/pages/inscription.tsx +++ b/src/pages/inscription.tsx @@ -3,9 +3,8 @@ import React, { useEffect, useRef, useState } from 'react'; import Visibility from '@mui/icons-material/Visibility'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; -import { Box, Button, Checkbox, IconButton, InputAdornment, Link, TextField } from '@mui/material'; +import { Box, Button, Checkbox, FormControlLabel, Grid, IconButton, InputAdornment, Link, TextField, Typography } from '@mui/material'; -import { KeepRatio } from '../components/KeepRatio'; import LanguageFilter from 'src/components/LanguageFilter'; import { useLanguages } from 'src/services/useLanguages'; import { useUserRequests } from 'src/services/useUsers'; @@ -44,6 +43,7 @@ const Inscription = () => { }); const [isSubmitSuccessfull, setIsSubmitSuccessfull] = useState(false); const [isRegisterDataValid, setIsRegisterDataValid] = useState(false); + const [isPending, setIsPending] = useState(false); const { languages } = useLanguages(); const { addUser, resendVerificationEmail } = useUserRequests(); @@ -166,10 +166,12 @@ const Inscription = () => { const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); if (isCGUread && isEmailValid && isFirstnameValid && isPasswordMatch && isPasswordValid && isLastnameValid) { + setIsPending(true); try { await addUser(newUser); } catch (err) { setIsEmailUsed(true); + setIsPending(false); return; } @@ -192,57 +194,93 @@ const Inscription = () => { const passwordMessage = passwordMessageRef.current; return ( - <> -
-
+ + - { router.push('/'); }} sx={{ - placeSelf: 'flex-start', - marginRight: '1rem', - fontSize: '0.875rem', + cursor: 'pointer', + width: 'fit-content', + height: 'auto', + alignSelf: 'center', + margin: { + xs: '10px 0', + sm: '0 10px', + }, }} > - - -

Créer un compte

- { - router.push('/connexion'); - }} + +
+ + + { + router.push('/connexion'); + }} + sx={{ + marginRight: '1rem', + fontSize: '0.875rem', + textAlign: 'end', + }} + > + Retour à la page de connexion + + + + + + + Créer un compte + + - Retour à la page de connexion - -
- -
{!isSubmitSuccessfull ? ( <> -

Créer un compte

-
+ { helperText={isEmailUsed && 'Email déjà utilisé'} InputLabelProps={{ shrink: true }} sx={{ - width: '30ch', + width: '100%', mb: '1rem', '& .MuiAutocomplete-root': { backgroundColor: 'white', @@ -271,7 +309,7 @@ const Inscription = () => { error={!isFirstnameValid} InputLabelProps={{ shrink: true }} sx={{ - width: '30ch', + width: '100%', mb: '1rem', '& .MuiAutocomplete-root': { backgroundColor: 'white', @@ -288,10 +326,7 @@ const Inscription = () => { name="lastname" error={!isLastnameValid} InputLabelProps={{ shrink: true }} - sx={{ - width: '30ch', - mb: '1rem', - }} + sx={{ width: '100%', mb: '1rem' }} onChange={(event) => { setLastname(event.target.value); }} @@ -302,6 +337,7 @@ const Inscription = () => { placeholder="Entrez votre nom de passe" name="password" autoComplete="off" + sx={{ width: '100%', mb: '1rem' }} InputProps={{ endAdornment: ( @@ -315,10 +351,6 @@ const Inscription = () => { error={isPasswordValid === false} helperText={isPasswordValid === true ? '8 lettres minimum, une majuscule et un chiffre' : passwordMessage} InputLabelProps={{ shrink: true }} - sx={{ - width: '30ch', - mb: '1rem', - }} onChange={(event) => { setPassword(event.target.value); }} @@ -329,6 +361,7 @@ const Inscription = () => { placeholder="Confirmez votre mot de passe" autoComplete="off" name="confirmPassword" + sx={{ width: '100%', mb: '1rem' }} type={isConfirmationPasswordVisible === false ? 'password' : 'text'} error={isPasswordMatch === false} helperText={isPasswordMatch === false ? 'Les mots de passes doivent être identiques' : null} @@ -342,76 +375,62 @@ const Inscription = () => { ), }} InputLabelProps={{ shrink: true }} - sx={{ - width: '30ch', - mb: '1rem', - }} onChange={(event) => { setConfirmPassword(event.target.value); }} /> - + + + { + setHasAcceptedNewsletter(!hasAcceptedNewsletter); + }} + /> + } + label={Accepter de recevoir des nouvelles du projet 1Village} + /> - - { - setHasAcceptedNewsletter(!hasAcceptedNewsletter); - }} - /> -
- Accepter de recevoir des nouvelles du projet 1Village -
-
- - { - setIsCGUread(!isCGUread); - }} - /> -
- Accepter les conditions générales d'utilisation ** -
-
-
- -
- + { + setIsCGUread(!isCGUread); + }} + /> + } + label={ + + Accepter les conditions générales d'utilisation ** + + } + /> + + +
) : ( - <> +

Bienvenu(e) dans un Village

Un email de confirmation viens de vous être envoyé à l'adresse email indiquée.

-
Vous allez être redirigée vers la page de connexion.
- +
Vous allez être redirigée vers la page de connexion...
+
)} -
-
-
- + + + + ); }; diff --git a/src/pages/login.tsx b/src/pages/login.tsx index 38165cbd8..e04dc03ae 100644 --- a/src/pages/login.tsx +++ b/src/pages/login.tsx @@ -2,9 +2,8 @@ import { useRouter } from 'next/router'; import qs from 'query-string'; import React from 'react'; -import { Backdrop, Button, CircularProgress, Link, Tooltip } from '@mui/material'; +import { Backdrop, Box, Button, CircularProgress, Grid, Link, Tooltip, Typography } from '@mui/material'; -import { KeepRatio } from '../components/KeepRatio'; import { isRedirectValid } from '../components/accueil/NewHome'; import { UserContext } from 'src/contexts/userContext'; import ArrowBack from 'src/svg/arrow_back.svg'; @@ -61,101 +60,143 @@ const SignInTeacher = () => { }, []); return ( - <> -
-
+ + - {' '} - { router.push('/'); }} sx={{ - placeSelf: 'flex-start', - marginRight: '1rem', - fontSize: '0.875rem', + cursor: 'pointer', + width: 'fit-content', + height: 'auto', + margin: { + xs: '10px 0', + sm: '0 10px', + }, + alignSelf: 'center', }} > - - -

Professeurs des écoles

- { - router.push('/'); - }} - sx={{ - placeSelf: 'center end', - marginRight: '1rem', - fontSize: '0.875rem', - }} - > - Village en famille - -
- -
- - {SSO_HOST.length && CLIENT_ID ? ( - - ) : ( - - - - - - )} + + + + { + router.push('/'); + }} sx={{ + placeSelf: 'center end', + marginRight: '1rem', fontSize: '0.875rem', - mt: 2, - fontWeight: 'bold', }} > - S'inscrire + Village en famille + + + + + + Professeurs des écoles + + +
+ + {SSO_HOST.length && CLIENT_ID ? ( + + ) : ( + + + + + + )} + + S'inscrire + + + {/* Bloc error text */} + + {errorCode !== -1 ? errorMessages[errorCode as 0] || errorMessages[0] : null} + +
- {/* Bloc error text */} - - {errorCode !== -1 ? errorMessages[errorCode as 0] || errorMessages[0] : null} - -
-
- - - -
- + + + + + + + ); }; diff --git a/src/pages/reset-password.tsx b/src/pages/reset-password.tsx index f42807df7..55dd56b41 100644 --- a/src/pages/reset-password.tsx +++ b/src/pages/reset-password.tsx @@ -1,9 +1,8 @@ import { useRouter } from 'next/router'; import React from 'react'; -import { Button, Link, TextField, Typography, Backdrop, CircularProgress } from '@mui/material'; +import { Button, Link, TextField, Typography, Backdrop, CircularProgress, Grid, Box } from '@mui/material'; -import { KeepRatio } from 'src/components/KeepRatio'; import ArrowBack from 'src/svg/arrow_back.svg'; import Logo from 'src/svg/logo_1village_famille.svg'; import PelicoSouriant from 'src/svg/pelico/pelico-souriant.svg'; @@ -57,86 +56,115 @@ const ResetPassword: React.FunctionComponent = () => { }; return ( - <> -
-
+ + - { router.push('/'); }} sx={{ - placeSelf: 'flex-start', - marginRight: '1rem', - fontSize: '0.875rem', + cursor: 'pointer', + width: 'fit-content', + height: 'auto', + alignSelf: 'center', + margin: { + xs: '10px 0', + sm: '0 10px', + }, }} > - - -

Mot de passe oublié

- { - router.push('/connexion'); - }} + +
+ + + { + router.push('/connexion'); + }} + sx={{ + marginRight: '1rem', + fontSize: '0.875rem', + textAlign: 'end', + }} + > + Retour à la page de connexion + + + + + + + Réinitialisation du mot de passe + + - Retour à la page de connexion - -
- -
{!isSuccess ? ( - <> -

Réinitialisation du mot de passe

- -
+ + Veuillez renseigner l'email lié à votre compte.
Nous vous enverrons un email avec un lien qui vous permettra de réinitialiser votre mot de passe. -
+ -
{errorCode === 0 && ( {errorMessages[0]} )} -
-
-
Email :
+ + { value={email} onChange={handleEmailInputChange} variant="outlined" - sx={{ flexGrow: 1, marginLeft: '1rem' }} error={errorCode === 1} helperText={errorCode === 1 ? errorMessages[1] : null} + sx={{ + flexGrow: '1', + margin: '1rem 0', + }} /> - -
+ +
Retourner à la connexion
-
+ + theme.zIndex.drawer + 1, color: '#fff' }} open={loading}> - + ) : ( - <> - + +
Un email vient de vous être envoyé à l'adresse donnée

-
Vous allez être redirigé(e) vers la page de connexion
- +
Vous allez être redirigé(e) vers la page de connexion...
+
)} -
-
-
- + + + + ); }; diff --git a/src/pages/user-verified.tsx b/src/pages/user-verified.tsx index 50fb56c43..dfab25a96 100644 --- a/src/pages/user-verified.tsx +++ b/src/pages/user-verified.tsx @@ -1,9 +1,8 @@ import { useRouter } from 'next/router'; import React, { useContext, useEffect, useRef } from 'react'; -import { Link } from '@mui/material'; +import { Box, Grid, Link, Typography } from '@mui/material'; -import { KeepRatio } from 'src/components/KeepRatio'; import { UserContext } from 'src/contexts/userContext'; import { useUserRequests } from 'src/services/useUsers'; import ArrowBack from 'src/svg/arrow_back.svg'; @@ -38,72 +37,110 @@ const UserVerified: React.FunctionComponent = () => { }, [isLoggedIn, router]); return ( - <> -
-
+ + - { router.push('/'); }} sx={{ - placeSelf: 'flex-start', - marginRight: '1rem', - fontSize: '0.875rem', + width: 'fit-content', + height: 'auto', + margin: { + xs: '10px 0', + sm: '0 10px', + }, + alignSelf: 'center', }} > - - -

Utilisateur vérifié

- { - router.push('/'); - }} + +
+ + + { + router.push('/'); + }} + sx={{ + placeSelf: 'center end', + marginRight: '1rem', + fontSize: '0.875rem', + }} + > + Retour à la page de connexion + + + + + + + Utilisateur vérifié + + - Retour à la page de connexion - -
- -
- -
Bienvenue à un 1Village
-
-
Vous pouvez dès à présent vous connecter à votre compte 1Village
-
-
Vous allez être redirigé(e) vers la page de connexion
-
-
-
- +
+ +
Bienvenue à un 1Village
+
+
Vous pouvez dès à présent vous connecter à votre compte 1Village
+
+
Vous allez être redirigé(e) vers la page de connexion
+
+ + + + ); }; diff --git a/src/styles/globals.scss b/src/styles/globals.scss index e2e4275f5..30075173e 100644 --- a/src/styles/globals.scss +++ b/src/styles/globals.scss @@ -250,6 +250,12 @@ a.text--success:hover { justify-content: center; align-items: center; } +.bg-gradiant-only { + background: rgb(224, 195, 252); + background: -o-linear-gradient(315deg, rgba(224, 195, 252, 1) 0%, rgba(142, 197, 252, 1) 100%); + background: linear-gradient(135deg, rgba(224, 195, 252, 1) 0%, rgba(142, 197, 252, 1) 100%); + background-attachment: fixed; +} .bg-grey { background-color: $bg-page; }