mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
début du design system
This commit is contained in:
parent
ee7a7a0544
commit
09955be8d4
12 changed files with 203 additions and 232 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -131,4 +131,5 @@ launch.json
|
|||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
db-backup/
|
||||
db-backup/
|
||||
/.vs
|
||||
|
|
|
|||
44
client/package-lock.json
generated
44
client/package-lock.json
generated
|
|
@ -17,8 +17,11 @@
|
|||
"@mui/icons-material": "^6.4.6",
|
||||
"@mui/lab": "^5.0.0-alpha.153",
|
||||
"@mui/material": "^6.4.6",
|
||||
"@types/bootstrap": "^5.2.10",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"axios": "^1.8.1",
|
||||
"bootstrap": "^5.3.3",
|
||||
"bootstrap-icons": "^1.11.3",
|
||||
"dompurify": "^3.2.3",
|
||||
"esbuild": "^0.25.0",
|
||||
"gift-pegjs": "^2.0.0-beta.1",
|
||||
|
|
@ -4521,6 +4524,14 @@
|
|||
"@babel/types": "^7.20.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/bootstrap": {
|
||||
"version": "5.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.10.tgz",
|
||||
"integrity": "sha512-F2X+cd6551tep0MvVZ6nM8v7XgGN/twpdNDjqS1TUM7YFNEtQYWk+dKAnH+T1gr6QgCoGMPl487xw/9hXooa2g==",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/debug": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||
|
|
@ -5536,6 +5547,39 @@
|
|||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
|
||||
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.11.8"
|
||||
}
|
||||
},
|
||||
"node_modules/bootstrap-icons": {
|
||||
"version": "1.11.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz",
|
||||
"integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -21,8 +21,11 @@
|
|||
"@mui/icons-material": "^6.4.6",
|
||||
"@mui/lab": "^5.0.0-alpha.153",
|
||||
"@mui/material": "^6.4.6",
|
||||
"@types/bootstrap": "^5.2.10",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"axios": "^1.8.1",
|
||||
"bootstrap": "^5.3.3",
|
||||
"bootstrap-icons": "^1.11.3",
|
||||
"dompurify": "^3.2.3",
|
||||
"esbuild": "^0.25.0",
|
||||
"gift-pegjs": "^2.0.0-beta.1",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { BrowserRouter } from 'react-router-dom';
|
|||
|
||||
import { ThemeProvider, createTheme } from '@mui/material';
|
||||
import '@fortawesome/fontawesome-free/css/all.min.css';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
import './cssReset.css';
|
||||
import './index.css';
|
||||
|
|
|
|||
|
|
@ -1,61 +1,64 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import './authDrawer.css';
|
||||
import SimpleLogin from './providers/SimpleLogin/Login';
|
||||
import authService from '../../services/AuthService';
|
||||
import { ENV_VARIABLES } from '../../constants';
|
||||
import ButtonAuth from './providers/OAuth-Oidc/ButtonAuth';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
const AuthSelection: React.FC = () => {
|
||||
const [authData, setAuthData] = useState<any>(null); // Stocke les données d'auth
|
||||
const [authData, setAuthData] = useState<any>(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
ENV_VARIABLES.VITE_BACKEND_URL;
|
||||
// Récupérer les données d'authentification depuis l'API
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const data = await authService.fetchAuthData();
|
||||
setAuthData(data);
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="auth-selection-page">
|
||||
<h1>Connexion</h1>
|
||||
<div className="d-flex flex-column align-items-center p-4 w-100">
|
||||
<h1 className="mb-4">Connexion</h1>
|
||||
|
||||
{/* Formulaire de connexion Simple Login */}
|
||||
{/* Simple Login Form - Responsive width */}
|
||||
{authData && authData['simpleauth'] && (
|
||||
<div className="form-container">
|
||||
<div className="border rounded-3 p-4 my-2 shadow-sm w-100" style={{ maxWidth: '400px' }}>
|
||||
<SimpleLogin />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Conteneur OAuth/OIDC */}
|
||||
{authData && Object.keys(authData).some(key => authData[key].type === 'oidc' || authData[key].type === 'oauth') && (
|
||||
<div className="auth-button-container">
|
||||
{Object.keys(authData).map((providerKey) => {
|
||||
const providerType = authData[providerKey].type;
|
||||
if (providerType === 'oidc' || providerType === 'oauth') {
|
||||
return (
|
||||
<ButtonAuth
|
||||
key={providerKey}
|
||||
providerName={providerKey}
|
||||
providerType={providerType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{/* OAuth/OIDC Providers - Responsive width */}
|
||||
{authData && Object.keys(authData).some(key =>
|
||||
authData[key].type === 'oidc' || authData[key].type === 'oauth') && (
|
||||
<div className="d-flex flex-column my-3 w-100" style={{ maxWidth: '400px' }}>
|
||||
{Object.keys(authData).map((providerKey) => {
|
||||
const providerType = authData[providerKey].type;
|
||||
if (providerType === 'oidc' || providerType === 'oauth') {
|
||||
return (
|
||||
<ButtonAuth
|
||||
key={providerKey}
|
||||
providerName={providerKey}
|
||||
providerType={providerType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<button className="home-button-container" onClick={() => navigate('/')}>Retour à l'accueil</button>
|
||||
</div>
|
||||
<button
|
||||
className="btn btn-link text-dark p-0 mt-3"
|
||||
onClick={() => navigate('/')}
|
||||
>
|
||||
Retour à l'accueil
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthSelection;
|
||||
export default AuthSelection;
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
.auth-selection-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.form-container {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
width: 400px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
}
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
input {
|
||||
margin: 5px 0;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
button {
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background-color: #5271ff;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* This hover was affecting the entire App */
|
||||
/* button:hover {
|
||||
background-color: #5271ff;
|
||||
} */
|
||||
.home-button-container {
|
||||
background: none;
|
||||
color: black;
|
||||
}
|
||||
.home-button-container:hover {
|
||||
background: none;
|
||||
color: black;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { ENV_VARIABLES } from '../../../../constants';
|
||||
import '../css/buttonAuth.css';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
interface ButtonAuthContainerProps {
|
||||
providerName: string;
|
||||
|
|
@ -13,14 +13,16 @@ const handleAuthLogin = (provider: string) => {
|
|||
|
||||
const ButtonAuth: React.FC<ButtonAuthContainerProps> = ({ providerName, providerType }) => {
|
||||
return (
|
||||
<>
|
||||
<div className={`${providerName}-${providerType}-container button-container`}>
|
||||
<h2>Se connecter avec {providerType.toUpperCase()}</h2>
|
||||
<button key={providerName} className={`provider-btn ${providerType}-btn`} onClick={() => handleAuthLogin(providerName)}>
|
||||
Continuer avec {providerName}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
<div className={`border rounded-3 p-3 my-3 mx-auto shadow-sm ${providerName}-${providerType}-container`} style={{ maxWidth: '400px' }}>
|
||||
<h2 className="h5 mb-3">Se connecter avec {providerType.toUpperCase()}</h2>
|
||||
<button
|
||||
key={providerName}
|
||||
className={`btn btn-outline-secondary w-100 ${providerType}-btn`}
|
||||
onClick={() => handleAuthLogin(providerName)}
|
||||
>
|
||||
Continuer avec {providerName}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,90 +1,82 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
// JoinRoom.tsx
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import '../css/simpleLogin.css';
|
||||
import { TextField } from '@mui/material';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
|
||||
import LoginContainer from '../../../../components/LoginContainer/LoginContainer'
|
||||
import { TextField, Button, CircularProgress } from '@mui/material';
|
||||
import LoginContainer from '../../../../components/LoginContainer/LoginContainer';
|
||||
import ApiService from '../../../../services/ApiService';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
const SimpleLogin: React.FC = () => {
|
||||
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
|
||||
const [connectionError, setConnectionError] = useState<string>('');
|
||||
const [isConnecting] = useState<boolean>(false);
|
||||
const [isConnecting, setIsConnecting] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
|
||||
// Cleanup if needed
|
||||
};
|
||||
}, []);
|
||||
|
||||
const login = async () => {
|
||||
console.log(`SimpleLogin: login: email: ${email}, password: ${password}`);
|
||||
setIsConnecting(true);
|
||||
const result = await ApiService.login(email, password);
|
||||
setIsConnecting(false);
|
||||
|
||||
if (result !== true) {
|
||||
setConnectionError(result);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<LoginContainer
|
||||
title=''
|
||||
error={connectionError}>
|
||||
|
||||
<LoginContainer title='' error={connectionError}>
|
||||
{/* Email Input */}
|
||||
<TextField
|
||||
label="Email"
|
||||
variant="outlined"
|
||||
className="mb-3 w-100" // Bootstrap classes for spacing and width
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Nom d'utilisateur"
|
||||
sx={{ marginBottom: '1rem' }}
|
||||
fullWidth
|
||||
fullWidth // Material-UI fullWidth
|
||||
/>
|
||||
|
||||
{/* Password Input */}
|
||||
<TextField
|
||||
label="Mot de passe"
|
||||
variant="outlined"
|
||||
type="password"
|
||||
className="mb-3 w-100" // Bootstrap classes
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Nom de la salle"
|
||||
sx={{ marginBottom: '1rem' }}
|
||||
placeholder="Mot de passe"
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<LoadingButton
|
||||
loading={isConnecting}
|
||||
onClick={login}
|
||||
{/* Login Button */}
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ marginBottom: `${connectionError && '2rem'}` }}
|
||||
disabled={!email || !password}
|
||||
className={`w-100 mb-${connectionError ? '4' : '3'}`} // Dynamic margin-bottom
|
||||
onClick={login}
|
||||
disabled={!email || !password || isConnecting}
|
||||
startIcon={isConnecting ? <CircularProgress size={20} /> : null}
|
||||
size="large"
|
||||
>
|
||||
Login
|
||||
</LoadingButton>
|
||||
</Button>
|
||||
|
||||
<div className="login-links">
|
||||
|
||||
|
||||
{/* <Link to="/resetPassword"> */}
|
||||
<del>Réinitialiser le mot de passe</del>
|
||||
{/* </Link> */}
|
||||
|
||||
<Link to="/register">
|
||||
{/* Links Section */}
|
||||
<div className="d-flex flex-column align-items-center pt-3">
|
||||
<del className="py-1 text-muted">Réinitialiser le mot de passe</del>
|
||||
<Link
|
||||
to="/register"
|
||||
className="py-1 text-decoration-none text-primary"
|
||||
>
|
||||
Créer un compte
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
|
||||
</LoginContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default SimpleLogin;
|
||||
export default SimpleLogin;
|
||||
|
|
@ -1,32 +1,35 @@
|
|||
// JoinRoom.tsx
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { TextField, FormLabel, RadioGroup, FormControlLabel, Radio, Box } from '@mui/material';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
TextField,
|
||||
FormLabel,
|
||||
RadioGroup,
|
||||
FormControlLabel,
|
||||
Radio,
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress
|
||||
} from '@mui/material';
|
||||
import LoginContainer from '../../../../components/LoginContainer/LoginContainer';
|
||||
import ApiService from '../../../../services/ApiService';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
const Register: React.FC = () => {
|
||||
|
||||
const [name, setName] = useState(''); // State for name
|
||||
const [name, setName] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [roles, setRoles] = useState<string[]>(['teacher']); // Set 'student' as the default role
|
||||
|
||||
const [roles, setRoles] = useState<string[]>(['teacher']);
|
||||
const [connectionError, setConnectionError] = useState<string>('');
|
||||
const [isConnecting] = useState<boolean>(false);
|
||||
const [isConnecting, setIsConnecting] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
return () => { };
|
||||
}, []);
|
||||
|
||||
const handleRoleChange = (role: string) => {
|
||||
setRoles([role]); // Update the roles array to contain the selected role
|
||||
setRoles([role]);
|
||||
};
|
||||
|
||||
const isValidEmail = (email: string) => {
|
||||
// Basic email format validation
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
};
|
||||
|
|
@ -37,7 +40,9 @@ const Register: React.FC = () => {
|
|||
return;
|
||||
}
|
||||
|
||||
setIsConnecting(true);
|
||||
const result = await ApiService.register(name, email, password, roles);
|
||||
setIsConnecting(false);
|
||||
|
||||
if (result !== true) {
|
||||
setConnectionError(result);
|
||||
|
|
@ -46,46 +51,49 @@ const Register: React.FC = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<LoginContainer
|
||||
title="Créer un compte"
|
||||
error={connectionError}
|
||||
>
|
||||
<LoginContainer title="Créer un compte" error={connectionError}>
|
||||
{/* Name Field */}
|
||||
<TextField
|
||||
label="Nom"
|
||||
variant="outlined"
|
||||
className="mb-3 w-100"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="Votre nom"
|
||||
sx={{ marginBottom: '1rem' }}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
{/* Email Field */}
|
||||
<TextField
|
||||
label="Email"
|
||||
variant="outlined"
|
||||
className="mb-3 w-100"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Adresse courriel"
|
||||
sx={{ marginBottom: '1rem' }}
|
||||
fullWidth
|
||||
type="email"
|
||||
error={!!connectionError && !isValidEmail(email)}
|
||||
type="email"
|
||||
error={!!connectionError && !isValidEmail(email)}
|
||||
helperText={connectionError && !isValidEmail(email) ? "Adresse email invalide." : ""}
|
||||
/>
|
||||
|
||||
{/* Password Field */}
|
||||
<TextField
|
||||
label="Mot de passe"
|
||||
variant="outlined"
|
||||
className="mb-3 w-100"
|
||||
value={password}
|
||||
type="password"
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Mot de passe"
|
||||
sx={{ marginBottom: '1rem' }}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', marginBottom: '1rem' }}>
|
||||
<FormLabel component="legend" sx={{ marginRight: '1rem' }}>Choisir votre rôle</FormLabel>
|
||||
{/* Role Selection */}
|
||||
<Box className="d-flex align-items-center mb-3">
|
||||
<FormLabel component="legend" className="me-3">
|
||||
Choisir votre rôle
|
||||
</FormLabel>
|
||||
<RadioGroup
|
||||
row
|
||||
aria-label="role"
|
||||
|
|
@ -98,17 +106,19 @@ const Register: React.FC = () => {
|
|||
</RadioGroup>
|
||||
</Box>
|
||||
|
||||
<LoadingButton
|
||||
loading={isConnecting}
|
||||
onClick={register}
|
||||
{/* Register Button */}
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ marginBottom: `${connectionError && '2rem'}` }}
|
||||
disabled={!name || !email || !password}
|
||||
className={`w-100 mb-${connectionError ? '4' : '3'}`}
|
||||
onClick={register}
|
||||
disabled={!name || !email || !password || isConnecting}
|
||||
startIcon={isConnecting ? <CircularProgress size={20} /> : null}
|
||||
size="large"
|
||||
>
|
||||
S'inscrire
|
||||
</LoadingButton>
|
||||
</Button>
|
||||
</LoginContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Register;
|
||||
export default Register;
|
||||
|
|
@ -1,68 +1,72 @@
|
|||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// JoinRoom.tsx
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { TextField } from '@mui/material';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
|
||||
import LoginContainer from '../../../../components/LoginContainer/LoginContainer'
|
||||
import { TextField, Button, CircularProgress } from '@mui/material';
|
||||
import LoginContainer from '../../../../components/LoginContainer/LoginContainer';
|
||||
import ApiService from '../../../../services/ApiService';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
const ResetPassword: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [email, setEmail] = useState('');
|
||||
|
||||
const [connectionError, setConnectionError] = useState<string>('');
|
||||
const [isConnecting] = useState<boolean>(false);
|
||||
const [isConnecting, setIsConnecting] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
|
||||
// Cleanup if needed
|
||||
};
|
||||
}, []);
|
||||
|
||||
const reset = async () => {
|
||||
const result = await ApiService.resetPassword(email);
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
const result = await ApiService.resetPassword(email);
|
||||
|
||||
if (!result) {
|
||||
setConnectionError(result.toString());
|
||||
return;
|
||||
if (!result) {
|
||||
setConnectionError(result.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
navigate("/login");
|
||||
} finally {
|
||||
setIsConnecting(false);
|
||||
}
|
||||
|
||||
navigate("/login")
|
||||
};
|
||||
|
||||
const isValidEmail = (email: string) => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
};
|
||||
|
||||
return (
|
||||
<LoginContainer
|
||||
title='Récupération du compte'
|
||||
error={connectionError}>
|
||||
|
||||
<LoginContainer title='Récupération du compte' error={connectionError}>
|
||||
{/* Email Field */}
|
||||
<TextField
|
||||
label="Email"
|
||||
variant="outlined"
|
||||
className="mb-3 w-100"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Adresse courriel"
|
||||
sx={{ marginBottom: '1rem' }}
|
||||
fullWidth
|
||||
type="email"
|
||||
error={!!connectionError && !isValidEmail(email)}
|
||||
helperText={connectionError && !isValidEmail(email) ? "Adresse email invalide." : ""}
|
||||
/>
|
||||
|
||||
<LoadingButton
|
||||
loading={isConnecting}
|
||||
onClick={reset}
|
||||
{/* Reset Button */}
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ marginBottom: `${connectionError && '2rem'}` }}
|
||||
disabled={!email}
|
||||
className={`w-100 mb-${connectionError ? '4' : '3'}`}
|
||||
onClick={reset}
|
||||
disabled={!email || isConnecting}
|
||||
startIcon={isConnecting ? <CircularProgress size={20} /> : null}
|
||||
size="large"
|
||||
>
|
||||
Réinitialiser le mot de passe
|
||||
</LoadingButton>
|
||||
|
||||
</Button>
|
||||
</LoginContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResetPassword;
|
||||
export default ResetPassword;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
.provider-btn {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ccc;
|
||||
color: black;
|
||||
margin: 4px 0 4px 0;
|
||||
}
|
||||
|
||||
.provider-btn:hover {
|
||||
background-color: #dbdbdb;
|
||||
border: 1px solid #ccc;
|
||||
color: black;
|
||||
margin: 4px 0 4px 0;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
width: 400px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
.login-links {
|
||||
padding-top: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.login-links a {
|
||||
padding: 4px;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.login-links a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
Loading…
Reference in a new issue