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'
|
||||
|
||||
import PropTypes from 'prop-types'
|
||||
import {useState} from 'react'
|
||||
import Box from '@mui/material/Box'
|
||||
import Paper from '@mui/material/Paper'
|
||||
import {styled} from '@mui/material/styles'
|
||||
import IconButton from '@mui/material/IconButton'
|
||||
import AddCommentIcon from '@mui/icons-material/AddComment'
|
||||
import Tooltip, {tooltipClasses} from '@mui/material/Tooltip'
|
||||
import AuthAlert from '../auth-form/auth-alert.js'
|
||||
import Titre from './titre.js'
|
||||
import Article from './article.js'
|
||||
import HandleComments from './handle-comments.js'
|
||||
import {formatKonstitisyon} from '@/lib/format.js'
|
||||
|
||||
const LightTooltip = styled(({className, ...props}) => (
|
||||
@@ -24,27 +26,66 @@ const LightTooltip = styled(({className, ...props}) => (
|
||||
|
||||
export default function Konstitisyon({session, 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 (
|
||||
<Box>
|
||||
{konstitisyon.map(({titreId, titre, articles}) => (
|
||||
<Paper key={titreId} variant='outlined' sx={{p: 1, marginBlock: 2}} p={2} >
|
||||
<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'>
|
||||
<LightTooltip title='Commenter'>
|
||||
<AddCommentIcon color='warning' fontSize='inherit' />
|
||||
</LightTooltip>
|
||||
</IconButton>
|
||||
</Box>
|
||||
)}
|
||||
</Paper>
|
||||
))}
|
||||
</Box>
|
||||
<>
|
||||
{error && <AuthAlert
|
||||
isOpen={isErrorAlertOpen}
|
||||
setIsOpen={setIsErrorAlertOpen}
|
||||
message={error}
|
||||
severity='error'
|
||||
/>}
|
||||
|
||||
{success && <AuthAlert
|
||||
isOpen={isSuccessAlertOpen}
|
||||
setIsOpen={setIsSuccessAlertOpen}
|
||||
message={success}
|
||||
severity='success'
|
||||
/>}
|
||||
|
||||
<Box>
|
||||
{konstitisyon.map(({titreId, titre, articles}) => (
|
||||
<Paper key={titreId} variant='outlined' sx={{p: 1, marginBlock: 2}} p={2} >
|
||||
<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