diff --git a/components/versions/export-pdf-button.js b/components/versions/export-pdf-button.js index d2fc2e7..5dc0aaa 100644 --- a/components/versions/export-pdf-button.js +++ b/components/versions/export-pdf-button.js @@ -46,7 +46,7 @@ const renderMarkdownToHtml = async content => { } } -export default function ExportPdfButton({versionData, size = 'medium', variant = 'outlined'}) { +export default function ExportPdfButton({versionData, isOutdated = false, size = 'medium', variant = 'outlined'}) { const [isExporting, setIsExporting] = useState(false) const handleExportPdf = async () => { @@ -86,55 +86,55 @@ export default function ExportPdfButton({versionData, size = 'medium', variant = .pdf-content p { margin: 10px 0; } .pdf-content strong, .pdf-content b { font-weight: bold; } .pdf-content em, .pdf-content i { font-style: italic; } - .pdf-content ul, .pdf-content ol { - margin: 10px 0; - padding-left: 25px; + .pdf-content ul, .pdf-content ol { + margin: 10px 0; + padding-left: 25px; } .pdf-content li { margin: 5px 0; } - .pdf-content blockquote { - margin: 15px 0; - padding: 10px 20px; - border-left: 4px solid #1976d2; - background-color: #f5f5f5; - font-style: italic; + .pdf-content blockquote { + margin: 15px 0; + padding: 10px 20px; + border-left: 4px solid #1976d2; + background-color: #f5f5f5; + font-style: italic; } - .pdf-content code { - background-color: #f5f5f5; - padding: 2px 4px; - border-radius: 3px; - font-family: 'Courier New', monospace; - font-size: 13px; + .pdf-content code { + background-color: #f5f5f5; + padding: 2px 4px; + border-radius: 3px; + font-family: 'Courier New', monospace; + font-size: 13px; } - .pdf-content pre { - background-color: #f5f5f5; - padding: 15px; - border-radius: 5px; - overflow-x: auto; - margin: 15px 0; + .pdf-content pre { + background-color: #f5f5f5; + padding: 15px; + border-radius: 5px; + overflow-x: auto; + margin: 15px 0; } - .pdf-content pre code { - background: none; - padding: 0; + .pdf-content pre code { + background: none; + padding: 0; } .pdf-content a { color: #1976d2; text-decoration: underline; } - .pdf-content hr { - border: none; - border-top: 1px solid #ccc; - margin: 20px 0; + .pdf-content hr { + border: none; + border-top: 1px solid #ccc; + margin: 20px 0; } - .pdf-content table { - border-collapse: collapse; - margin: 15px 0; - width: 100%; + .pdf-content table { + border-collapse: collapse; + margin: 15px 0; + width: 100%; } - .pdf-content th, .pdf-content td { - border: 1px solid #ccc; - padding: 8px; - text-align: left; + .pdf-content th, .pdf-content td { + border: 1px solid #ccc; + padding: 8px; + text-align: left; } - .pdf-content th { - background-color: #f5f5f5; - font-weight: bold; + .pdf-content th { + background-color: #f5f5f5; + font-weight: bold; } ` document.head.append(styleElement) @@ -142,7 +142,8 @@ export default function ExportPdfButton({versionData, size = 'medium', variant = const authorName = versionData.user_created?.split('-')[0] || 'Système' const createdAt = new Date(versionData.date_created) const threeDaysAgo = new Date(Date.now() - (3 * 24 * 60 * 60 * 1000)) - const voteStatus = createdAt < threeDaysAgo ? 'fermé' : 'ouvert' + const isExpired = createdAt < threeDaysAgo + const voteStatus = (isExpired || isOutdated) ? 'fermé' : 'ouvert' const voteColor = voteStatus === 'ouvert' ? '#2e7d32' : '#d32f2f' // Render markdown content to HTML @@ -251,6 +252,7 @@ export default function ExportPdfButton({versionData, size = 'medium', variant = ExportPdfButton.propTypes = { versionData: PropTypes.object.isRequired, + isOutdated: PropTypes.bool, size: PropTypes.oneOf(['small', 'medium', 'large']), variant: PropTypes.oneOf(['text', 'outlined', 'contained']) } diff --git a/components/versions/list-versions.js b/components/versions/list-versions.js index 5b6c3cd..004d827 100644 --- a/components/versions/list-versions.js +++ b/components/versions/list-versions.js @@ -1,4 +1,4 @@ -import {forwardRef, useRef, useState} from 'react' +import {forwardRef, useRef, useState, useEffect} from 'react' import PropTypes from 'prop-types' import Table from '@mui/material/Table' import TableBody from '@mui/material/TableBody' @@ -84,7 +84,8 @@ function rowContent({ setError, setIsErrorAlertOpen, setIsOpenComparison, - setVersionCompare + setVersionCompare, + outdatedStatusMap }) { const handleButtonClick = async versionId => { const version = await compareVersion({ @@ -102,6 +103,8 @@ function rowContent({ } } + const isOutdated = outdatedStatusMap[row.id] || false + return ( <> {columns.map(column => ( @@ -137,11 +140,13 @@ function rowContent({ /> @@ -182,6 +187,42 @@ export default function ListVersions({ dateTo: '', status: '' }) + const [outdatedStatusMap, setOutdatedStatusMap] = useState({}) + + // Fetch outdated status for all versions + useEffect(() => { + async function fetchOutdatedStatus() { + const statusMap = {} + + await Promise.all( + data.map(async version => { + try { + const comparisonData = await compareVersion({ + accessToken, + userId, + versionId: version.id, + countdownRef, + setError, + setIsErrorAlertOpen + }) + + if (comparisonData) { + statusMap[version.id] = comparisonData.outdated || false + } + } catch (error) { + console.warn(`Failed to fetch outdated status for version ${version.id}:`, error) + statusMap[version.id] = false + } + }) + ) + + setOutdatedStatusMap(statusMap) + } + + if (data.length > 0) { + fetchOutdatedStatus() + } + }, [data, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen]) // Filter data based on search and filters const filteredData = filterVersions(data, searchTerm, filters) @@ -261,7 +302,7 @@ export default function ListVersions({ components={VirtuosoTableComponents} fixedHeaderContent={fixedHeaderContent} itemContent={(index, row) => rowContent({ - index, row, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen, setIsOpenComparison, setVersionCompare + index, row, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen, setIsOpenComparison, setVersionCompare, outdatedStatusMap })} /> diff --git a/components/versions/print-button.js b/components/versions/print-button.js index 0be4d0c..f282b87 100644 --- a/components/versions/print-button.js +++ b/components/versions/print-button.js @@ -49,7 +49,7 @@ const renderMarkdownToHtml = async content => { } } -export default function PrintButton({versionData, size = 'medium', variant = 'outlined'}) { +export default function PrintButton({versionData, isOutdated = false, size = 'medium', variant = 'outlined'}) { const [isPrinting, setIsPrinting] = useState(false) const [snackbar, setSnackbar] = useState({open: false, message: '', severity: 'success'}) @@ -61,7 +61,8 @@ export default function PrintButton({versionData, size = 'medium', variant = 'ou const authorName = versionData.user_created?.split('-')[0] || 'Système' const createdAt = new Date(versionData.date_created) const threeDaysAgo = new Date(Date.now() - (3 * 24 * 60 * 60 * 1000)) - const voteStatus = createdAt < threeDaysAgo ? 'fermé' : 'ouvert' + const isExpired = createdAt < threeDaysAgo + const voteStatus = (isExpired || isOutdated) ? 'fermé' : 'ouvert' const voteColor = voteStatus === 'ouvert' ? '#2e7d32' : '#d32f2f' // Render markdown content to HTML @@ -390,6 +391,7 @@ export default function PrintButton({versionData, size = 'medium', variant = 'ou PrintButton.propTypes = { versionData: PropTypes.object.isRequired, + isOutdated: PropTypes.bool, size: PropTypes.oneOf(['small', 'medium', 'large']), variant: PropTypes.oneOf(['text', 'outlined', 'contained']) } diff --git a/components/versions/version-page.js b/components/versions/version-page.js index 9872951..3ae1e6d 100644 --- a/components/versions/version-page.js +++ b/components/versions/version-page.js @@ -54,20 +54,18 @@ export default function VersionPage({session, versionId, viewMode}) { setVersionData(version) - // If in comparison mode, also fetch comparison data - if (viewMode === 'comparison') { - const comparison = await compareVersion({ - accessToken, - userId, - versionId, - countdownRef, - setError, - setIsErrorAlertOpen - }) + // Fetch comparison data (needed for outdated status even if not in comparison mode) + const comparison = await compareVersion({ + accessToken, + userId, + versionId, + countdownRef, + setError, + setIsErrorAlertOpen + }) - if (comparison) { - setVersionCompare({...comparison, versionId}) - } + if (comparison) { + setVersionCompare({...comparison, versionId}) } } catch (error) { console.error('Failed to fetch version:', error) @@ -79,7 +77,7 @@ export default function VersionPage({session, versionId, viewMode}) { } fetchVersionData() - }, [accessToken, userId, versionId, viewMode]) + }, [accessToken, userId, versionId]) const handleBack = () => { router.push('/dashboard') diff --git a/components/versions/version-timeline.js b/components/versions/version-timeline.js index b168a29..61a3db6 100644 --- a/components/versions/version-timeline.js +++ b/components/versions/version-timeline.js @@ -309,11 +309,13 @@ function VersionCard({ />