From 28177439e1b0129b10b06a55700fb6ef7092b937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20FAMIBELLE-PRONZOLA?= Date: Tue, 18 Jun 2024 11:11:15 +0400 Subject: [PATCH] Add components to write comments --- components/konstitisyon/handle-comments.js | 117 +++++++++++++++++++++ components/konstitisyon/index.js | 81 ++++++++++---- components/session/logout-countdown.js | 45 ++++++++ 3 files changed, 223 insertions(+), 20 deletions(-) create mode 100644 components/konstitisyon/handle-comments.js create mode 100644 components/session/logout-countdown.js diff --git a/components/konstitisyon/handle-comments.js b/components/konstitisyon/handle-comments.js new file mode 100644 index 0000000..b4d0c52 --- /dev/null +++ b/components/konstitisyon/handle-comments.js @@ -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 ( + <> + + {selectedTitre.titre} + + + Écrivez votre commentaire + + + + + + + + + + + + ) +} + +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 +} diff --git a/components/konstitisyon/index.js b/components/konstitisyon/index.js index 9764f65..c0cb096 100644 --- a/components/konstitisyon/index.js +++ b/components/konstitisyon/index.js @@ -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 ( - - {konstitisyon.map(({titreId, titre, articles}) => ( - - - {articles.map(({id, numero, contenu}) => ( -
- ))} - {session && ( - - - - - - - - )} - - ))} - + <> + {error && } + + {success && } + + + {konstitisyon.map(({titreId, titre, articles}) => ( + + + {articles.map(({id, numero, contenu}) => ( +
+ ))} + {session && ( + + handleCommentsDialog(titreId, titre)}> + + + + + + )} + + ))} + {selectedTitre && ( + + )} + + ) } diff --git a/components/session/logout-countdown.js b/components/session/logout-countdown.js new file mode 100644 index 0000000..d82f913 --- /dev/null +++ b/components/session/logout-countdown.js @@ -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