Add registration tab in Koneksyon component
This commit is contained in:
+257
-68
@@ -2,45 +2,122 @@ import {useEffect, useState, forwardRef} from 'react'
|
||||
import {signIn} from 'next-auth/react'
|
||||
import {useRouter} from 'next/router'
|
||||
import PropTypes from 'prop-types'
|
||||
import Link from 'next/link'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Container,
|
||||
FormControl,
|
||||
IconButton,
|
||||
Input,
|
||||
InputAdornment,
|
||||
InputLabel,
|
||||
LinearProgress,
|
||||
Snackbar,
|
||||
Typography
|
||||
} from '@mui/material'
|
||||
import {Visibility, VisibilityOff} from '@mui/icons-material'
|
||||
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 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'
|
||||
|
||||
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:1337'
|
||||
|
||||
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({detay, tit, soutit, titGwose, chimen}) {
|
||||
function Koneksyon({chimen}) {
|
||||
const [loginError, setError] = useState('')
|
||||
const [credentials, setCredentials] = useState({username: '', password: ''})
|
||||
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 [registrationSuccess, setRegistrationSuccess] = useState(false)
|
||||
const [value, setValue] = useState(0)
|
||||
const router = useRouter()
|
||||
|
||||
const handleUpdate = update => {
|
||||
setCredentials({...credentials, ...update})
|
||||
setLoginCredentials({...loginCredentials, ...update})
|
||||
}
|
||||
|
||||
const handleClick = async () => {
|
||||
if (!validateEmail(credentials.username) || credentials.password === '') {
|
||||
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('user-id', response?.data?.user?._id)
|
||||
setRegistrationSuccess(true)
|
||||
resetRegisterForm()
|
||||
} catch (error) {
|
||||
if (error.message.endsWith(400)) {
|
||||
setError('Email ou utilisateur déjà enregistré')
|
||||
} else {
|
||||
setError('Une erreur s’est produite')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const resetRegisterForm = () => {
|
||||
setRegisterCredentials({username: '', email: '', password: ''})
|
||||
setPasswordVerification('')
|
||||
}
|
||||
|
||||
const handleClickLogin = async () => {
|
||||
if (!validateEmail(loginCredentials.username) || loginCredentials.password === '') {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -48,7 +125,7 @@ function Koneksyon({detay, tit, soutit, titGwose, chimen}) {
|
||||
const response = await signIn('credentials', {
|
||||
callbackUrl: `${siteUrl}${chimen}`,
|
||||
redirect: false,
|
||||
...credentials
|
||||
...loginCredentials
|
||||
})
|
||||
if (response.error) {
|
||||
setError(response.error)
|
||||
@@ -59,12 +136,35 @@ function Koneksyon({detay, tit, soutit, titGwose, 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 d’utilisateur est trop court, 3 caratères minimum')
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
await register()
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
const handleClose = (event, reason) => {
|
||||
if (reason === 'clickaway') {
|
||||
return
|
||||
}
|
||||
|
||||
setOpen(false)
|
||||
setRegistrationSuccess(false)
|
||||
setError('')
|
||||
}
|
||||
|
||||
@@ -82,47 +182,64 @@ function Koneksyon({detay, tit, soutit, titGwose, chimen}) {
|
||||
setShowPassword(!showPassword)
|
||||
}
|
||||
|
||||
const handleClickShowRegisterPassword = () => {
|
||||
setShowRegisterPassword(!showRegisterPassword)
|
||||
}
|
||||
|
||||
const handleClickShowVerificationPassword = () => {
|
||||
setShowVerificationPassword(!showVerificationPassword)
|
||||
}
|
||||
|
||||
const handleMouseDownPassword = event => {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const handleKeyUp = event => {
|
||||
const handleMouseDownRegisterPassword = event => {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const handleMouseDownVerificationPassword = event => {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const handleKeyUpLogin = event => {
|
||||
if (event.keyCode === 13) {
|
||||
handleClick()
|
||||
handleClickLogin()
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyUpRegister = event => {
|
||||
if (event.keyCode === 13) {
|
||||
handleClickRegister()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxWidth='sm'>
|
||||
{tit && (
|
||||
<Box sx={{textAlign: 'center', marginTop: 5}}>
|
||||
<Typography display='inline' variant={`h${titGwose}`} component='h1'>
|
||||
{tit}
|
||||
</Typography>
|
||||
{soutit && (
|
||||
<Typography>
|
||||
<small>{soutit}</small>
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
<Container sx={{marginTop: 2}} maxWidth='sm'>
|
||||
|
||||
<FormControl fullWidth style={{marginTop: '1em'}} autoComplete='off'>
|
||||
<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='S’inscrire' {...a11yProps(1)} />
|
||||
</Tabs>
|
||||
<TabPanel value={value} index={0}>
|
||||
<FormControl fullWidth autoComplete='off'>
|
||||
<InputLabel htmlFor='username'>Email</InputLabel>
|
||||
<Input
|
||||
value={credentials.username}
|
||||
autoComplete='email'
|
||||
value={loginCredentials.username}
|
||||
name='username'
|
||||
type='email'
|
||||
id='email'
|
||||
onChange={event => handleUpdate({username: event.target.value})}
|
||||
onKeyUp={handleKeyUp}
|
||||
onKeyUp={handleKeyUpLogin}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormControl fullWidth style={{marginTop: '1em'}}>
|
||||
<InputLabel htmlFor='password'>Mot de passe</InputLabel>
|
||||
<Input
|
||||
value={credentials.password}
|
||||
value={loginCredentials.password}
|
||||
name='password'
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
id='password'
|
||||
@@ -139,39 +256,112 @@ function Koneksyon({detay, tit, soutit, titGwose, chimen}) {
|
||||
</InputAdornment>
|
||||
}
|
||||
onChange={event => handleUpdate({password: event.target.value})}
|
||||
onKeyUp={handleKeyUp}
|
||||
onKeyUp={handleKeyUpLogin}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<Button
|
||||
fullWidth
|
||||
disabled={loading || !validateEmail(credentials.username) || credentials.password === ''}
|
||||
disabled={loading || !validateEmail(loginCredentials.username) || loginCredentials.password === ''}
|
||||
style={{marginTop: 20}}
|
||||
variant='contained'
|
||||
color='primary'
|
||||
onClick={handleClick}
|
||||
onClick={handleClickLogin}
|
||||
>
|
||||
<Typography style={{fontWeight: 'bold'}}>
|
||||
Connexion
|
||||
</Typography>
|
||||
</Button>
|
||||
</TabPanel>
|
||||
<TabPanel value={value} index={1}>
|
||||
<FormControl fullWidth autoComplete='off'>
|
||||
<InputLabel htmlFor='register-username'>Nom d’utilisateur</InputLabel>
|
||||
<Input
|
||||
value={registerCredentials.username}
|
||||
autoComplete='username'
|
||||
name='register-username'
|
||||
type='text'
|
||||
id='register-username'
|
||||
onChange={event => handleRegisterUpdate({username: event.target.value})}
|
||||
onKeyUp={handleKeyUpRegister}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl fullWidth style={{marginTop: '1em'}} autoComplete='off'>
|
||||
<InputLabel htmlFor='register-email'>Email</InputLabel>
|
||||
<Input
|
||||
value={registerCredentials.email}
|
||||
autoComplete='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='password'>Mot de passe</InputLabel>
|
||||
<Input
|
||||
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>
|
||||
</TabPanel>
|
||||
</Box>
|
||||
|
||||
{loading && <LinearProgress size={24} style={{width: '100%', marginTop: '1em'}} />}
|
||||
|
||||
{detay && (
|
||||
<Box sx={{textAlign: 'center', marginTop: 3}}>
|
||||
<Typography display='block' variant='h6' component='h2'>
|
||||
Pour obtenir un accès, faites-en la demande
|
||||
</Typography>
|
||||
<Typography style={{fontSize: 20}} display='block'>
|
||||
📩
|
||||
</Typography>
|
||||
<Link passHref href='mailto:kontak@oki.re?subject=Accès à #OKi'>
|
||||
<a style={{color: 'green', fontSize: 20, textDecoration: 'none', fontWeight: 'bold'}}>kontak@oki.re</a>
|
||||
</Link>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{loginError && (
|
||||
<Snackbar
|
||||
open={open}
|
||||
@@ -181,22 +371,21 @@ function Koneksyon({detay, tit, soutit, titGwose, chimen}) {
|
||||
<Alert severity='error' onClose={handleClose}><strong>{loginError}</strong></Alert>
|
||||
</Snackbar>
|
||||
)}
|
||||
|
||||
{registrationSuccess && (
|
||||
<Snackbar
|
||||
open={registrationSuccess}
|
||||
autoHideDuration={15_000}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<Alert severity='success' onClose={handleClose}><strong>Inscription réussie. Veuillez confirmer votre adresse email, via le lien qui vous a été envoyé.</strong></Alert>
|
||||
</Snackbar>
|
||||
)}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
Koneksyon.defaultProps = {
|
||||
detay: false,
|
||||
tit: null,
|
||||
soutit: null,
|
||||
titGwose: 5
|
||||
}
|
||||
|
||||
Koneksyon.propTypes = {
|
||||
detay: PropTypes.bool,
|
||||
tit: PropTypes.string,
|
||||
soutit: PropTypes.string,
|
||||
titGwose: PropTypes.number,
|
||||
chimen: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user