Login actions

This commit is contained in:
2024-09-28 16:54:56 +02:00
parent 90ddfd1da5
commit ce5019ca38
5 changed files with 200 additions and 35 deletions
+64 -2
View File
@@ -1,5 +1,67 @@
export const useActions = ({ emailRef, passwordRef }) => { import { useRouter } from 'next/navigation';
const handleSubmit = () => {};
export const useActions = ({ setError, setIsLoading }) => {
const router = useRouter();
const handleSubmit = async (ev) => {
ev.preventDefault();
const formData = new FormData(ev.currentTarget);
const username = formData.get('username');
const password = formData.get('password');
if (!username || !password) {
return;
}
setIsLoading(true);
try {
const request = await fetch(
'https://lovemap-backend.vercel.app/auth/login',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username,
password,
}),
}
);
const response = await request.json();
if (request.status == 404) {
setError('Utilisateur inconnu');
setIsLoading(false);
return;
}
if (request.status == 403) {
setError('Mauvais mot de passe');
setIsLoading(false);
return;
}
if (request.status == 500) {
console.log('request.status: ', request.status);
setError('Erreur interne. Veuillez réessayer');
setIsLoading(false);
return;
}
const { token } = response;
localStorage.setItem('token', token);
router.push('/');
} catch (error) {
console.error(error);
setError('Erreur interne. Veuillez réessayer');
}
setIsLoading(false);
};
return { return {
handleSubmit, handleSubmit,
-11
View File
@@ -1,11 +0,0 @@
import { useRef } from 'react';
export const useData = () => {
const emailRef = useRef(null);
const passwordRef = useRef(null);
return {
emailRef,
passwordRef,
};
};
+25 -16
View File
@@ -4,23 +4,27 @@
//! Imports //! Imports
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------- React & Next -----------------------------------------------------
import { useState } from 'react';
// ---------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------- Components ------------------------------------------------------ // --------------------------------------------------- Components ------------------------------------------------------
import Image from 'next/image'; import Image from 'next/image';
import Link from 'next/link';
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------- Hooks & Utils ---------------------------------------------------- // -------------------------------------------------- Hooks & Utils ----------------------------------------------------
import { useData } from './hooks/useData';
import { useActions } from './hooks/useActions'; import { useActions } from './hooks/useActions';
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
// ------------------------------------------------- Assets & Styles --------------------------------------------------- // ------------------------------------------------- Assets & Styles ---------------------------------------------------
import Loader from '@/assets/Loader';
import '../styles.scss'; import '../styles.scss';
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
const Login = () => { const Login = () => {
const { emailRef, passwordRef } = useData(); const [error, setError] = useState(null);
const { handleSubmit } = useActions({ emailRef, passwordRef }); const [isLoading, setIsLoading] = useState(false);
const { handleSubmit } = useActions({ setError, setIsLoading });
return ( return (
<div className='authContainer'> <div className='authContainer'>
@@ -30,27 +34,30 @@ const Login = () => {
alt='appLogo' alt='appLogo'
width={1024} width={1024}
height={1024} height={1024}
priority
/> />
<div className='formContainer'>
<form
className='formContainer'
onSubmit={handleSubmit}
>
<h1 className='formTitle'>Connexion</h1> <h1 className='formTitle'>Connexion</h1>
<div <div className='form'>
role='form' {error && <p className='error'>{error}</p>}
className='form'
>
<div className='inputContainer'> <div className='inputContainer'>
<input <input
ref={emailRef} type='text'
type='email' name='username'
name='email'
className='input' className='input'
required required
/> />
<label className='inputLabel'>Adresse e-mail</label> <label className='inputLabel'>
Nom d&apos;utilisateur
</label>
</div> </div>
<div className='inputContainer'> <div className='inputContainer'>
<input <input
ref={passwordRef}
type='password' type='password'
name='password' name='password'
className='input' className='input'
@@ -61,13 +68,15 @@ const Login = () => {
</div> </div>
<div className='buttonsContainer'> <div className='buttonsContainer'>
<button <button
type='submit'
className='submitButton' className='submitButton'
onClick={handleSubmit} disabled={isLoading}
> >
Se connecter Se connecter
{isLoading && <Loader />}
</button> </button>
</div> </div>
</div> </form>
</div> </div>
); );
}; };
+16 -6
View File
@@ -41,6 +41,11 @@
align-items: stretch; align-items: stretch;
gap: 15px; gap: 15px;
& > .error {
text-align: center;
color: #fefefa;
}
& > .inputContainer { & > .inputContainer {
position: relative; position: relative;
display: grid; display: grid;
@@ -68,7 +73,8 @@
font-size: 1em; font-size: 1em;
color: #fefefa; color: #fefefa;
&:focus + .inputLabel { &:focus + .inputLabel,
&:not(:placeholder-shown) + .inputLabel {
top: 0; top: 0;
left: 10px; left: 10px;
transform: translateY(-50%); transform: translateY(-50%);
@@ -110,11 +116,12 @@
margin-top: 15px; margin-top: 15px;
& > .submitButton { & > .submitButton {
position: relative;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 5px; gap: 10px;
padding: 7px 35px; padding: 7px 42px;
border: 1px solid #fefefa; border: 1px solid #fefefa;
border-radius: 5px; border-radius: 5px;
background-color: #fefefa; background-color: #fefefa;
@@ -122,9 +129,12 @@
color: #d94253; color: #d94253;
cursor: pointer; cursor: pointer;
&.secondary { & > svg {
background-color: #d94253; position: absolute;
color: #fefefa; top: 50%;
right: 10px;
transform: translateY(-50%);
width: 20px;
} }
} }
} }
+95
View File
@@ -0,0 +1,95 @@
const Loader = (props) => {
return (
<svg
viewBox='0 0 57 57'
xmlns='http://www.w3.org/2000/svg'
stroke='currentColor'
{...props}
>
<g
fill='none'
fill-rule='evenodd'
>
<g
transform='translate(1 1)'
stroke-width='2'
>
<circle
cx='5'
cy='50'
r='5'
>
<animate
attributeName='cy'
begin='0s'
dur='2.2s'
values='50;5;50;50'
calcMode='linear'
repeatCount='indefinite'
/>
<animate
attributeName='cx'
begin='0s'
dur='2.2s'
values='5;27;49;5'
calcMode='linear'
repeatCount='indefinite'
/>
</circle>
<circle
cx='27'
cy='5'
r='5'
>
<animate
attributeName='cy'
begin='0s'
dur='2.2s'
from='5'
to='5'
values='5;50;50;5'
calcMode='linear'
repeatCount='indefinite'
/>
<animate
attributeName='cx'
begin='0s'
dur='2.2s'
from='27'
to='27'
values='27;49;5;27'
calcMode='linear'
repeatCount='indefinite'
/>
</circle>
<circle
cx='49'
cy='50'
r='5'
>
<animate
attributeName='cy'
begin='0s'
dur='2.2s'
values='50;50;5;50'
calcMode='linear'
repeatCount='indefinite'
/>
<animate
attributeName='cx'
from='49'
to='49'
begin='0s'
dur='2.2s'
values='49;5;27;49'
calcMode='linear'
repeatCount='indefinite'
/>
</circle>
</g>
</g>
</svg>
);
};
export default Loader;