diff --git a/components/versions/list-versions.js b/components/versions/list-versions.js index c5d0bf4..d4485e5 100644 --- a/components/versions/list-versions.js +++ b/components/versions/list-versions.js @@ -80,7 +80,7 @@ function rowContent({ }) if (version) { - setVersionData(version) + setVersionData({...version, versionId}) setIsOpenComparison(true) } } diff --git a/components/versions/version-comparison.js b/components/versions/version-comparison.js index 631440e..7fd4615 100644 --- a/components/versions/version-comparison.js +++ b/components/versions/version-comparison.js @@ -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 ( @@ -25,12 +79,22 @@ export default function VersionComparison({versionData}) { {current.contenu} - {!outdated && ( + {!outdated && session?.user && ( - + handleVoteClick(1)} + > - + handleVoteClick(-1)} + > @@ -91,6 +155,16 @@ export default function VersionComparison({versionData}) { + + + {snackbar.message} + + ) } @@ -101,5 +175,6 @@ VersionComparison.propTypes = { mainHash: PropTypes.string.isRequired, current: PropTypes.object.isRequired, main: PropTypes.object.isRequired, + versionId: PropTypes.string }).isRequired, } diff --git a/lib/directus.js b/lib/directus.js index 5cf247c..6c411d4 100644 --- a/lib/directus.js +++ b/lib/directus.js @@ -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 + } +}