Merge pull request 'Système de vote sur les versions de contenu' (#2) from feat-votes into master
Reviewed-on: https://codeberg.org/OKI/konstitisyon.la/pulls/2
This commit is contained in:
@@ -80,7 +80,7 @@ function rowContent({
|
||||
})
|
||||
|
||||
if (version) {
|
||||
setVersionData(version)
|
||||
setVersionData({...version, versionId})
|
||||
setIsOpenComparison(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,63 @@ import PropTypes from 'prop-types'
|
||||
import IconButton from '@mui/material/IconButton'
|
||||
import ThumbUpIcon from '@mui/icons-material/ThumbUp'
|
||||
import ThumbDownIcon from '@mui/icons-material/ThumbDown'
|
||||
import {useState, useEffect} from 'react'
|
||||
import {useSession} from 'next-auth/react'
|
||||
import Snackbar from '@mui/material/Snackbar'
|
||||
import Alert from '@mui/material/Alert'
|
||||
import {handleVote, getUserVote} from '../../lib/directus.js'
|
||||
|
||||
export default function VersionComparison({versionData}) {
|
||||
const {current, main, outdated} = versionData
|
||||
const {data: session} = useSession()
|
||||
const [snackbar, setSnackbar] = useState({open: false, message: '', severity: 'success'})
|
||||
const [currentVote, setCurrentVote] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
const fetchVote = async () => {
|
||||
if (session?.user && versionData.versionId) {
|
||||
try {
|
||||
const vote = await getUserVote({
|
||||
accessToken: session.user.accessToken,
|
||||
userId: session.user.userId,
|
||||
versionId: versionData.versionId
|
||||
})
|
||||
setCurrentVote(vote)
|
||||
} catch (error) {
|
||||
console.error('Error fetching vote:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fetchVote()
|
||||
}, [session, versionData.versionId])
|
||||
|
||||
const handleVoteClick = async voteValue => {
|
||||
try {
|
||||
const newVoteValue = await handleVote({
|
||||
accessToken: session.user.accessToken,
|
||||
userId: session.user.userId,
|
||||
versionId: versionData.versionId,
|
||||
voteValue
|
||||
})
|
||||
setCurrentVote(newVoteValue)
|
||||
setSnackbar({
|
||||
open: true,
|
||||
message: newVoteValue === null ? 'Vote annulé' : 'Vote enregistré avec succès',
|
||||
severity: 'success'
|
||||
})
|
||||
} catch {
|
||||
setSnackbar({
|
||||
open: true,
|
||||
message: 'Erreur lors du vote',
|
||||
severity: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleCloseSnackbar = () => {
|
||||
setSnackbar(prev => ({...prev, open: false}))
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{padding: 3}}>
|
||||
@@ -25,12 +79,22 @@ export default function VersionComparison({versionData}) {
|
||||
<Typography variant='body1' sx={{color: outdated ? '#D32F2F' : '#1976D2', fontWeight: 'bold'}}>
|
||||
{current.contenu}
|
||||
</Typography>
|
||||
{!outdated && (
|
||||
{!outdated && session?.user && (
|
||||
<Box sx={{display: 'flex', justifyContent: 'flex-end', mt: 1}}>
|
||||
<IconButton size='small' color='success' aria-label='vote positif'>
|
||||
<IconButton
|
||||
size='small'
|
||||
color={currentVote === 1 ? 'success' : 'primary'}
|
||||
aria-label='vote positif'
|
||||
onClick={() => handleVoteClick(1)}
|
||||
>
|
||||
<ThumbUpIcon />
|
||||
</IconButton>
|
||||
<IconButton size='small' color='error' aria-label='vote négatif'>
|
||||
<IconButton
|
||||
size='small'
|
||||
color={currentVote === -1 ? 'error' : 'primary'}
|
||||
aria-label='vote négatif'
|
||||
onClick={() => handleVoteClick(-1)}
|
||||
>
|
||||
<ThumbDownIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
@@ -91,6 +155,16 @@ export default function VersionComparison({versionData}) {
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Snackbar
|
||||
open={snackbar.open}
|
||||
autoHideDuration={6000}
|
||||
anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}
|
||||
onClose={handleCloseSnackbar}
|
||||
>
|
||||
<Alert variant='filled' severity={snackbar.severity} sx={{width: '100%'}} onClose={handleCloseSnackbar}>
|
||||
{snackbar.message}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -101,5 +175,6 @@ VersionComparison.propTypes = {
|
||||
mainHash: PropTypes.string.isRequired,
|
||||
current: PropTypes.object.isRequired,
|
||||
main: PropTypes.object.isRequired,
|
||||
versionId: PropTypes.string
|
||||
}).isRequired,
|
||||
}
|
||||
|
||||
+98
-1
@@ -2,7 +2,7 @@
|
||||
import {
|
||||
createDirectus, rest, authentication, withToken, createItem,
|
||||
readUser, createContentVersion, readContentVersions, saveToContentVersion,
|
||||
readContentVersion,
|
||||
readContentVersion, readItems, updateItem, deleteItem,
|
||||
compareContentVersion
|
||||
} from '@directus/sdk'
|
||||
import {signOut} from 'next-auth/react'
|
||||
@@ -241,3 +241,100 @@ export async function createVersion({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function handleVote({
|
||||
accessToken,
|
||||
userId,
|
||||
versionId,
|
||||
voteValue
|
||||
}) {
|
||||
try {
|
||||
await handleUserStatus(accessToken, userId)
|
||||
|
||||
const existingVotes = await directusClient.request(
|
||||
withToken(
|
||||
accessToken,
|
||||
readItems('votes', {
|
||||
filter: {
|
||||
_and: [
|
||||
{content_version_id: {_eq: versionId}},
|
||||
{user_created: {_eq: userId}}
|
||||
]
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
if (existingVotes && existingVotes.length > 0) {
|
||||
const existingVote = existingVotes[0]
|
||||
|
||||
if (existingVote.vote === voteValue) {
|
||||
await directusClient.request(
|
||||
withToken(
|
||||
accessToken,
|
||||
deleteItem('votes', existingVote.id)
|
||||
)
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
const vote = {
|
||||
content_version_id: versionId,
|
||||
vote: voteValue
|
||||
}
|
||||
|
||||
await directusClient.request(
|
||||
withToken(
|
||||
accessToken,
|
||||
updateItem('votes', existingVote.id, vote)
|
||||
)
|
||||
)
|
||||
return voteValue
|
||||
}
|
||||
|
||||
const vote = {
|
||||
content_version_id: versionId,
|
||||
vote: voteValue
|
||||
}
|
||||
|
||||
await directusClient.request(
|
||||
withToken(
|
||||
accessToken,
|
||||
createItem('votes', vote)
|
||||
)
|
||||
)
|
||||
return voteValue
|
||||
} catch (error) {
|
||||
console.error('Error voting:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUserVote({
|
||||
accessToken,
|
||||
userId,
|
||||
versionId
|
||||
}) {
|
||||
try {
|
||||
await handleUserStatus(accessToken, userId)
|
||||
|
||||
const existingVotes = await directusClient.request(
|
||||
withToken(
|
||||
accessToken,
|
||||
readItems('votes', {
|
||||
filter: {
|
||||
_and: [
|
||||
{content_version_id: {_eq: versionId}},
|
||||
{user_created: {_eq: userId}}
|
||||
]
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
return existingVotes && existingVotes.length > 0 ? existingVotes[0].vote : null
|
||||
} catch (error) {
|
||||
console.error('Error fetching vote:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user