Files
pawol.nu/components/sesyon/koneksyon.js
T
Cédric FAMIBELLE-PRONZOLA 4de3bb1f97 Add Button to LoginProvider
2022-10-31 23:01:33 +04:00

466 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {useEffect, useState, forwardRef} from 'react'
import {signIn} from 'next-auth/react'
import {useRouter} from 'next/router'
import PropTypes from 'prop-types'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Container from '@mui/material/Container'
import FormControl from '@mui/material/FormControl'
import IconButton from '@mui/material/IconButton'
import Input from '@mui/material/Input'
import InputAdornment from '@mui/material/InputAdornment'
import InputLabel from '@mui/material/InputLabel'
import LinearProgress from '@mui/material/LinearProgress'
import Snackbar from '@mui/material/Snackbar'
import Tab from '@mui/material/Tab'
import Tabs from '@mui/material/Tabs'
import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid'
import Visibility from '@mui/icons-material/Visibility'
import VisibilityOff from '@mui/icons-material/VisibilityOff'
import MuiAlert from '@mui/material/Alert'
import LoginIcon from '@mui/icons-material/Login'
import AppRegistrationRoundedIcon from '@mui/icons-material/AppRegistrationRounded'
import axios from 'axios'
import {validateEmail} from '../../lib/utils/emails'
import ResetPassword from '../password/reset-password'
import ResetDialog from '../password/reset-dialog'
import LoginProvider from './login-provider'
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001'
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:1337'
const PROVIDERS = [
{
id: 'google',
title: 'Google',
width: 16,
height: 16
},
{
id: 'twitter',
title: 'Twitter',
width: 16,
height: 13
},
{
id: 'github',
title: 'GitHub',
width: 16,
height: 15
}
]
function TabPanel(props) {
const {children, value, index, ...other} = props
return (
<div
role='tabpanel'
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && (
<Box sx={{p: 3}}>
{children}
</Box>
)}
</div>
)
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired,
}
function a11yProps(index) {
return {
id: `simple-tab-${index}`,
'aria-controls': `simple-tabpanel-${index}`,
}
}
const Alert = forwardRef(function Alert(props, ref) {
return <MuiAlert ref={ref} elevation={6} variant='filled' {...props} />
})
function Koneksyon({chimen}) {
const [error, setError] = useState('')
const [loginCredentials, setLoginCredentials] = useState({username: '', password: ''})
const [registerCredentials, setRegisterCredentials] = useState({username: '', email: '', password: ''})
const [passwordVerification, setPasswordVerification] = useState('')
const [showPassword, setShowPassword] = useState(false)
const [showRegisterPassword, setShowRegisterPassword] = useState(false)
const [showVerificationPassword, setShowVerificationPassword] = useState(false)
const [loading, setLoading] = useState(false)
const [open, setOpen] = useState(true)
const [success, setSuccess] = useState(false)
const [openDialog, setOpenDialog] = useState(false)
const [value, setValue] = useState(0)
const router = useRouter()
const handleUpdate = update => {
setLoginCredentials({...loginCredentials, ...update})
}
const handleRegisterUpdate = update => {
setRegisterCredentials({...registerCredentials, ...update})
}
const handleChange = (event, newValue) => {
setValue(newValue)
}
const register = async () => {
try {
const response = await axios.post(`${apiUrl}/auth/local/register`, {
...registerCredentials
}, {
headers: {
'content-type': 'application/json'
}
})
localStorage.setItem('username', `${response?.data?.user?.username}`)
setSuccess(true)
resetRegisterForm()
} catch (error_) {
if (error_.message.endsWith(400)) {
setError('E-mail ou utilisateur déjà enregistré')
} else {
setError('Une erreur sest produite')
}
}
}
const resetRegisterForm = () => {
setRegisterCredentials({username: '', email: '', password: ''})
setPasswordVerification('')
}
const handleClickLogin = async () => {
if (!validateEmail(loginCredentials.username) || loginCredentials.password === '') {
return
}
setLoading(true)
const response = await signIn('credentials', {
callbackUrl: `${siteUrl}${chimen}`,
redirect: false,
...loginCredentials
})
if (response.error) {
setError(response.error)
setLoading(false)
} else if (response.ok) {
setLoading(false)
router.push(chimen)
}
}
const handleClickRegister = async () => {
setLoading(true)
if (!validateEmail(registerCredentials.email) || registerCredentials.password === '') {
return
}
if (registerCredentials.password !== passwordVerification) {
setError('Les 2 mots de passe de correspondent pas')
setLoading(false)
return
}
if (registerCredentials.username.length < 3) {
setError('Le nom dutilisateur est trop court, 3 caratères minimum')
setLoading(false)
return
}
if (registerCredentials.password.length < 6) {
setError('Le mot de passe est trop court, 6 caratères minimum')
setLoading(false)
return
}
await register()
setLoading(false)
}
const handleClose = (event, reason) => {
if (reason === 'clickaway') {
return
}
setOpen(false)
setSuccess(false)
setError('')
}
useEffect(() => {
if (error) {
setOpen(true)
}
return () => {
setLoading(false)
}
}, [error])
const handleClickShowPassword = () => {
setShowPassword(!showPassword)
}
const handleClickShowRegisterPassword = () => {
setShowRegisterPassword(!showRegisterPassword)
}
const handleClickShowVerificationPassword = () => {
setShowVerificationPassword(!showVerificationPassword)
}
const handleMouseDownPassword = event => {
event.preventDefault()
}
const handleMouseDownRegisterPassword = event => {
event.preventDefault()
}
const handleMouseDownVerificationPassword = event => {
event.preventDefault()
}
const handleKeyUpLogin = event => {
if (event.keyCode === 13) {
handleClickLogin()
}
}
const handleKeyUpRegister = event => {
if (event.keyCode === 13) {
handleClickRegister()
}
}
return (
<Container sx={{marginTop: 2}} maxWidth='sm'>
<Box sx={{width: '100%'}}>
<Tabs centered value={value} aria-label='basic tabs example' onChange={handleChange}>
<Tab icon={<LoginIcon />} label='Se connecter' {...a11yProps(0)} />
<Tab icon={<AppRegistrationRoundedIcon />} label='Sinscrire' {...a11yProps(1)} />
</Tabs>
<TabPanel value={value} index={0}>
<Box sx={{textAlign: 'center', marginBottom: 3}}>
<Typography gutterBottom textAlign='center'>Connectez-vous avec</Typography>
<Grid container alignItems='center' justifyContent='center' columnSpacing={{xs: 1, sm: 2, md: 3}}>
{PROVIDERS.map(({id, title, width, height}) => (
<Grid key={id} item marginTop={1}>
<LoginProvider id={id} title={title} width={width} height={height} callbackUrl={`${siteUrl}${chimen}`} />
</Grid>
))}
</Grid>
</Box>
<Box sx={{textAlign: 'center', marginBottom: 3}}>
<Typography>ou utilisez votre e-mail pour vous identifier</Typography>
</Box>
<FormControl fullWidth autoComplete='off'>
<InputLabel htmlFor='username'>E-mail</InputLabel>
<Input
autoComplete='new-password'
value={loginCredentials.username}
name='username'
type='email'
id='email'
onChange={event => handleUpdate({username: event.target.value})}
onKeyUp={handleKeyUpLogin}
/>
</FormControl>
<FormControl fullWidth style={{marginTop: '1em'}}>
<InputLabel htmlFor='password'>Mot de passe</InputLabel>
<Input
autoComplete='new-password'
value={loginCredentials.password}
name='password'
type={showPassword ? 'text' : 'password'}
id='password'
endAdornment={
<InputAdornment position='end'>
<IconButton
aria-label='password visibility'
size='large'
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
onChange={event => handleUpdate({password: event.target.value})}
onKeyUp={handleKeyUpLogin}
/>
</FormControl>
<Button
fullWidth
disabled={loading || !validateEmail(loginCredentials.username) || loginCredentials.password === ''}
style={{marginTop: 20}}
variant='contained'
color='primary'
onClick={handleClickLogin}
>
<Typography style={{fontWeight: 'bold'}}>
Connexion
</Typography>
</Button>
<ResetPassword />
</TabPanel>
<TabPanel value={value} index={1}>
<FormControl fullWidth>
<InputLabel htmlFor='register-email'>E-mail</InputLabel>
<Input
autoComplete='email'
value={registerCredentials.email}
name='register-email'
type='email'
id='register-email'
onChange={event => handleRegisterUpdate({email: event.target.value})}
onKeyUp={handleKeyUpRegister}
/>
</FormControl>
<FormControl fullWidth style={{marginTop: '1em'}}>
<InputLabel htmlFor='register-username'>Nom dutilisateur</InputLabel>
<Input
autoComplete='username'
value={registerCredentials.username}
name='register-username'
type='text'
id='register-username'
onChange={event => handleRegisterUpdate({username: event.target.value})}
onKeyUp={handleKeyUpRegister}
/>
</FormControl>
<FormControl fullWidth style={{marginTop: '1em'}}>
<InputLabel htmlFor='password'>Mot de passe</InputLabel>
<Input
autoComplete='new-password' // Disable auto complete
value={registerCredentials.password}
name='register-password'
type={showRegisterPassword ? 'text' : 'password'}
id='register-password'
endAdornment={
<InputAdornment position='end'>
<IconButton
aria-label='password visibility'
size='large'
onClick={handleClickShowRegisterPassword}
onMouseDown={handleMouseDownRegisterPassword}
>
{showRegisterPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
onChange={event => handleRegisterUpdate({password: event.target.value})}
onKeyUp={handleKeyUpRegister}
/>
</FormControl>
<FormControl fullWidth style={{marginTop: '1em'}}>
<InputLabel htmlFor='password'>Vérification du mot de passe</InputLabel>
<Input
value={passwordVerification}
name='verification-password'
type={showVerificationPassword ? 'text' : 'password'}
id='verification-password'
error={registerCredentials.password !== passwordVerification}
endAdornment={
<InputAdornment position='end'>
<IconButton
aria-label='password visibility'
size='large'
onClick={handleClickShowVerificationPassword}
onMouseDown={handleMouseDownVerificationPassword}
>
{showVerificationPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
onChange={event => setPasswordVerification(event.target.value)}
onKeyUp={handleKeyUpRegister}
/>
</FormControl>
<Button
fullWidth
disabled={loading || !validateEmail(registerCredentials.email) || registerCredentials.username === '' || registerCredentials.password === ''}
style={{marginTop: 20}}
variant='contained'
color='primary'
onClick={handleClickRegister}
>
<Typography style={{fontWeight: 'bold'}}>
Inscription
</Typography>
</Button>
<Button
fullWidth
style={{marginTop: 20}}
variant='outlined'
color='warning'
onClick={() => setOpenDialog(true)}
>
<Typography style={{fontWeight: 'bold'}}>
Renvoyer le-mail de confirmation
</Typography>
</Button>
</TabPanel>
</Box>
<ResetDialog
activation
lyen='send-email-confirmation'
title='Envoi de le-mail de confirmation'
content='Si vous navez pas reçu le-mail de confirmation, renseignez le champ et validez le formulaire.'
open={openDialog}
setOpen={setOpenDialog}
setLoading={setLoading}
setError={setError}
setSuccess={setSuccess}
/>
{loading && <LinearProgress size={24} style={{width: '100%'}} />}
{error && (
<Snackbar
open={open}
autoHideDuration={6000}
onClose={handleClose}
>
<Alert severity='error' onClose={handleClose}><strong>{error}</strong></Alert>
</Snackbar>
)}
{success && (
<Snackbar
open={success}
autoHideDuration={15_000}
onClose={handleClose}
>
<Alert severity='success' onClose={handleClose}><strong>Veuillez confirmer votre adresse e-mail via le lien qui vous a été envoyé.</strong></Alert>
</Snackbar>
)}
</Container>
)
}
Koneksyon.propTypes = {
chimen: PropTypes.string.isRequired
}
export default Koneksyon