refactor: use HandleComments to read & write comments

This commit is contained in:
2024-06-19 14:44:49 +04:00
parent f4eb07c9a3
commit 1e587b5d6b
4 changed files with 79 additions and 40 deletions
@@ -0,0 +1,57 @@
'use client'
import PropTypes from 'prop-types'
import WriteComment from './write-comment.js'
import ReadComments from './read-comments.js'
export default function HandleComments({
session,
selectedTitre,
isOpen,
setIsOpen,
setError,
setSuccess,
setIsErrorAlertOpen,
setIsSuccessAlertOpen,
operation
}) {
if (operation === 'write') {
return (
<WriteComment
session={session}
selectedTitre={selectedTitre}
isOpen={isOpen}
setIsOpen={setIsOpen}
setError={setError}
setSuccess={setSuccess}
setIsErrorAlertOpen={setIsErrorAlertOpen}
setIsSuccessAlertOpen={setIsSuccessAlertOpen}
/>
)
}
if (operation === 'read') {
return (
<ReadComments
session={session}
selectedTitre={selectedTitre}
isOpen={isOpen}
setIsOpen={setIsOpen}
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,
operation: PropTypes.oneOf(['write', 'read']).isRequired
}
@@ -0,0 +1,121 @@
/* eslint-disable camelcase */
import React, {useEffect, useState, useRef} from 'react'
import PropTypes from 'prop-types'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import ListItemText from '@mui/material/ListItemText'
import DialogTitle from '@mui/material/DialogTitle'
import Dialog from '@mui/material/Dialog'
import Typography from '@mui/material/Typography'
import Pagination from '@mui/material/Pagination'
import Divider from '@mui/material/Divider'
import Box from '@mui/material/Box'
import {readItems, withToken} from '@directus/sdk'
import LogoutCountdown from '../../session/logout-countdown.js'
import {directusClient} from '@/lib/directus.js'
import {formatDate} from '@/lib/format.js'
const commentsPerPage = process.env.NEXT_PUBLIC_COMMENTS_PER_PAGE || 2
export default function ReadComments({session, selectedTitre, isOpen, setIsOpen, setError, setIsErrorAlertOpen}) {
const countdownRef = useRef()
const [comments, setComments] = useState([])
const [page, setPage] = useState(1)
const pageCount = Math.ceil(comments.length / commentsPerPage)
const startIndex = (page - 1) * commentsPerPage
const selectedComments = comments.slice(startIndex, startIndex + commentsPerPage)
useEffect(() => {
async function fetchComments() {
try {
const result = await directusClient.request(withToken(
session.user.accessToken,
readItems('commentaires', {
filter: {
titre: selectedTitre.id
},
sort: '-date_created'
}))
)
setComments(result)
} 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)
}
}
}
if (isOpen) {
fetchComments()
}
}, [isOpen, selectedTitre, setError, setIsErrorAlertOpen, session])
const handleClose = () => {
setIsOpen(false)
}
const handleChange = (event, value) => {
setPage(value)
}
return (
<>
<Dialog open={isOpen} onClose={handleClose}>
<DialogTitle>Commentaires</DialogTitle>
<List sx={{width: '100%', maxWidth: 360, bgcolor: 'background.paper'}}>
{selectedComments && selectedComments.length > 0 ? selectedComments.map(({id, date_created, text, user_created}) => (
<React.Fragment key={id}>
<ListItem alignItems='flex-start'>
<ListItemText
primary={
<Typography sx={{textDecoration: 'underline'}} component='span' variant='body2'>
{user_created.split('-')[0]}
</Typography>
}
secondary={
<>
<Typography
sx={{display: 'inline'}}
component='span'
variant='body2'
color='text.primary'
>
{text}
</Typography>
<br />
{formatDate(date_created, 'PPPPpp')}
</>
}
/>
</ListItem>
<Divider component='li' />
</React.Fragment>
)) : (
<Typography textAlign='center'>Aucun commentaire</Typography>
)}
</List>
<Box sx={{display: 'flex', justifyContent: 'center'}}>
<Pagination size='small' sx={{marginBlock: 3}} color='success' count={pageCount} page={page} onChange={handleChange} />
</Box>
</Dialog>
<LogoutCountdown ref={countdownRef} setError={setError} setIsErrorAlertOpen={setIsErrorAlertOpen} />
</>
)
}
ReadComments.propTypes = {
session: PropTypes.object,
selectedTitre: PropTypes.object.isRequired,
isOpen: PropTypes.bool.isRequired,
setIsOpen: PropTypes.func.isRequired,
setError: PropTypes.func.isRequired,
setIsErrorAlertOpen: PropTypes.func.isRequired
}
@@ -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 WriteComment({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
const formattedComment = comment.replaceAll('\'', '')
try {
if (hasRestrictedChar(formattedComment)) {
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: formattedComment,
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} />
</>
)
}
WriteComment.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
}