Add components to write comments
This commit is contained in:
@@ -0,0 +1,117 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import {useRef} from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import Button from '@mui/material/Button'
|
||||||
|
import TextField from '@mui/material/TextField'
|
||||||
|
import Dialog from '@mui/material/Dialog'
|
||||||
|
import DialogActions from '@mui/material/DialogActions'
|
||||||
|
import DialogContent from '@mui/material/DialogContent'
|
||||||
|
import DialogContentText from '@mui/material/DialogContentText'
|
||||||
|
import DialogTitle from '@mui/material/DialogTitle'
|
||||||
|
import {createItem, withToken} from '@directus/sdk'
|
||||||
|
import LogoutCountdown from '../session/logout-countdown.js'
|
||||||
|
import {directusClient} from '@/lib/directus.js'
|
||||||
|
|
||||||
|
function hasRestrictedChar(text) {
|
||||||
|
const regex = /[<>&'"]/g
|
||||||
|
|
||||||
|
return Boolean(regex.test(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function HandleComments({session, selectedTitre, isOpen, setIsOpen, setError, setSuccess, setIsErrorAlertOpen, setIsSuccessAlertOpen}) {
|
||||||
|
const countdownRef = useRef()
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setIsOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFormSubmit = async e => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
const formData = new FormData(e.currentTarget)
|
||||||
|
const formJson = Object.fromEntries(formData.entries())
|
||||||
|
const {comment} = formJson
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (hasRestrictedChar(comment)) {
|
||||||
|
setError('Le texte ne doit pas contenir certains caractères spéciaux : <, >, \', ".')
|
||||||
|
setIsErrorAlertOpen(true)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await directusClient.request(withToken(
|
||||||
|
session.user.accessToken,
|
||||||
|
createItem('commentaires', {
|
||||||
|
text: comment,
|
||||||
|
titre: selectedTitre,
|
||||||
|
status: 'draft'
|
||||||
|
})
|
||||||
|
))
|
||||||
|
|
||||||
|
setSuccess('Envoyé avec succès. Commentaire en attente de validation.')
|
||||||
|
setIsSuccessAlertOpen(true)
|
||||||
|
} catch (error) {
|
||||||
|
if (error?.errors[0]?.message === 'Token expired.') {
|
||||||
|
countdownRef.current.startCountdown()
|
||||||
|
} else {
|
||||||
|
console.log(error?.errors[0]?.message)
|
||||||
|
setError(error?.errors[0]?.message)
|
||||||
|
setIsErrorAlertOpen(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog
|
||||||
|
open={isOpen}
|
||||||
|
PaperProps={{
|
||||||
|
component: 'form',
|
||||||
|
onSubmit(event) {
|
||||||
|
handleFormSubmit(event)
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClose={handleClose}
|
||||||
|
>
|
||||||
|
<DialogTitle>{selectedTitre.titre}</DialogTitle>
|
||||||
|
<DialogContent sx={{color: 'white'}}>
|
||||||
|
<DialogContentText sx={{color: 'white'}}>
|
||||||
|
Écrivez votre commentaire
|
||||||
|
</DialogContentText>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
required
|
||||||
|
multiline
|
||||||
|
fullWidth
|
||||||
|
mt={2}
|
||||||
|
rows={4}
|
||||||
|
id='comment'
|
||||||
|
name='comment'
|
||||||
|
label='Commentaire'
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button variant='contained' color='success' onClick={handleClose}>Annuler</Button>
|
||||||
|
<Button variant='contained' color='error' type='submit'>Valider</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
<LogoutCountdown ref={countdownRef} setError={setError} setIsErrorAlertOpen={setIsErrorAlertOpen} />
|
||||||
|
</>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleComments.propTypes = {
|
||||||
|
session: PropTypes.object,
|
||||||
|
selectedTitre: PropTypes.object.isRequired,
|
||||||
|
isOpen: PropTypes.bool.isRequired,
|
||||||
|
setIsOpen: PropTypes.func.isRequired,
|
||||||
|
setError: PropTypes.func.isRequired,
|
||||||
|
setSuccess: PropTypes.func.isRequired,
|
||||||
|
setIsErrorAlertOpen: PropTypes.func.isRequired,
|
||||||
|
setIsSuccessAlertOpen: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import {useState} from 'react'
|
||||||
import Box from '@mui/material/Box'
|
import Box from '@mui/material/Box'
|
||||||
import Paper from '@mui/material/Paper'
|
import Paper from '@mui/material/Paper'
|
||||||
import {styled} from '@mui/material/styles'
|
import {styled} from '@mui/material/styles'
|
||||||
import IconButton from '@mui/material/IconButton'
|
import IconButton from '@mui/material/IconButton'
|
||||||
import AddCommentIcon from '@mui/icons-material/AddComment'
|
import AddCommentIcon from '@mui/icons-material/AddComment'
|
||||||
import Tooltip, {tooltipClasses} from '@mui/material/Tooltip'
|
import Tooltip, {tooltipClasses} from '@mui/material/Tooltip'
|
||||||
|
import AuthAlert from '../auth-form/auth-alert.js'
|
||||||
import Titre from './titre.js'
|
import Titre from './titre.js'
|
||||||
import Article from './article.js'
|
import Article from './article.js'
|
||||||
|
import HandleComments from './handle-comments.js'
|
||||||
import {formatKonstitisyon} from '@/lib/format.js'
|
import {formatKonstitisyon} from '@/lib/format.js'
|
||||||
|
|
||||||
const LightTooltip = styled(({className, ...props}) => (
|
const LightTooltip = styled(({className, ...props}) => (
|
||||||
@@ -24,27 +26,66 @@ const LightTooltip = styled(({className, ...props}) => (
|
|||||||
|
|
||||||
export default function Konstitisyon({session, titres, articles}) {
|
export default function Konstitisyon({session, titres, articles}) {
|
||||||
const konstitisyon = formatKonstitisyon(titres, articles)
|
const konstitisyon = formatKonstitisyon(titres, articles)
|
||||||
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
|
const [isErrorAlertOpen, setIsErrorAlertOpen] = useState(false)
|
||||||
|
const [isSuccessAlertOpen, setIsSuccessAlertOpen] = useState(false)
|
||||||
|
const [selectedTitre, setSelectedTitre] = useState(null)
|
||||||
|
const [error, setError] = useState('')
|
||||||
|
const [success, setSuccess] = useState('')
|
||||||
|
|
||||||
|
const handleCommentsDialog = (titreId, titre) => {
|
||||||
|
setSelectedTitre({id: titreId, titre})
|
||||||
|
setIsOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<>
|
||||||
{konstitisyon.map(({titreId, titre, articles}) => (
|
{error && <AuthAlert
|
||||||
<Paper key={titreId} variant='outlined' sx={{p: 1, marginBlock: 2}} p={2} >
|
isOpen={isErrorAlertOpen}
|
||||||
<Titre session={session} titreId={titreId} titre={titre} />
|
setIsOpen={setIsErrorAlertOpen}
|
||||||
{articles.map(({id, numero, contenu}) => (
|
message={error}
|
||||||
<Article key={id} session={session} articleId={id} numero={numero} contenu={contenu} />
|
severity='error'
|
||||||
))}
|
/>}
|
||||||
{session && (
|
|
||||||
<Box sx={{textAlign: 'right'}}>
|
{success && <AuthAlert
|
||||||
<IconButton size='large' aria-label='commenter'>
|
isOpen={isSuccessAlertOpen}
|
||||||
<LightTooltip title='Commenter'>
|
setIsOpen={setIsSuccessAlertOpen}
|
||||||
<AddCommentIcon color='warning' fontSize='inherit' />
|
message={success}
|
||||||
</LightTooltip>
|
severity='success'
|
||||||
</IconButton>
|
/>}
|
||||||
</Box>
|
|
||||||
)}
|
<Box>
|
||||||
</Paper>
|
{konstitisyon.map(({titreId, titre, articles}) => (
|
||||||
))}
|
<Paper key={titreId} variant='outlined' sx={{p: 1, marginBlock: 2}} p={2} >
|
||||||
</Box>
|
<Titre session={session} titreId={titreId} titre={titre} />
|
||||||
|
{articles.map(({id, numero, contenu}) => (
|
||||||
|
<Article key={id} session={session} articleId={id} numero={numero} contenu={contenu} />
|
||||||
|
))}
|
||||||
|
{session && (
|
||||||
|
<Box sx={{textAlign: 'right'}}>
|
||||||
|
<IconButton size='large' aria-label='commenter' onClick={() => handleCommentsDialog(titreId, titre)}>
|
||||||
|
<LightTooltip title='Commenter'>
|
||||||
|
<AddCommentIcon color='warning' fontSize='inherit' />
|
||||||
|
</LightTooltip>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
|
{selectedTitre && (
|
||||||
|
<HandleComments
|
||||||
|
session={session}
|
||||||
|
selectedTitre={selectedTitre}
|
||||||
|
isOpen={isOpen}
|
||||||
|
setIsOpen={setIsOpen}
|
||||||
|
setError={setError}
|
||||||
|
setSuccess={setSuccess}
|
||||||
|
setIsErrorAlertOpen={setIsErrorAlertOpen}
|
||||||
|
setIsSuccessAlertOpen={setIsSuccessAlertOpen}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import {
|
||||||
|
useState, useEffect, forwardRef, useImperativeHandle
|
||||||
|
} from 'react'
|
||||||
|
import {signOut} from 'next-auth/react'
|
||||||
|
|
||||||
|
const LogoutCountdown = forwardRef(({setError, setIsErrorAlertOpen}, ref) => {
|
||||||
|
const [counter, setCounter] = useState(5)
|
||||||
|
const [isCountdownActive, setIsCountdownActive] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let timer
|
||||||
|
|
||||||
|
if (isCountdownActive) {
|
||||||
|
if (counter > 0) {
|
||||||
|
timer = setInterval(() => {
|
||||||
|
setCounter(prevCounter => prevCounter - 1)
|
||||||
|
}, 1000)
|
||||||
|
} else if (counter === 0) {
|
||||||
|
signOut()
|
||||||
|
}
|
||||||
|
|
||||||
|
setError(`Session expirée, reconnectez-vous ! Déconnexion dans... ${counter} sec`)
|
||||||
|
setIsErrorAlertOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => clearInterval(timer)
|
||||||
|
}, [isCountdownActive, counter, setError, setIsErrorAlertOpen])
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
startCountdown() {
|
||||||
|
setCounter(5)
|
||||||
|
setIsCountdownActive(true)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
|
||||||
|
LogoutCountdown.propTypes = {
|
||||||
|
setError: PropTypes.func.isRequired,
|
||||||
|
setIsErrorAlertOpen: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LogoutCountdown
|
||||||
Reference in New Issue
Block a user