import {forwardRef, useRef, useState, useEffect} from 'react'
import PropTypes from 'prop-types'
import Table from '@mui/material/Table'
import TableBody from '@mui/material/TableBody'
import TableCell from '@mui/material/TableCell'
import TableContainer from '@mui/material/TableContainer'
import TableHead from '@mui/material/TableHead'
import TableRow from '@mui/material/TableRow'
import Paper from '@mui/material/Paper'
import Button from '@mui/material/Button'
import ToggleButton from '@mui/material/ToggleButton'
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
import ViewListIcon from '@mui/icons-material/ViewList'
import TimelineIcon from '@mui/icons-material/Timeline'
import {TableVirtuoso} from 'react-virtuoso'
import {Box, Typography} from '@mui/material'
import SessionExpired from '../session/session-expired.js'
import VersionDialog from './version-dialog.js'
import VersionTimeline from './version-timeline.js'
import VersionSearch from './version-search.js'
import VersionFilters from './version-filters.js'
import CopyButton from './copy-button.js'
import ShareButton from './share-button.js'
import ExportPdfButton from './export-pdf-button.js'
import PrintButton from './print-button.js'
import {formatDate} from '@/lib/format.js'
import {compareVersion, getVoteCounts} from '@/lib/directus.js'
import {filterVersions, getFilterStats} from '@/lib/version-utils.js'
const columns = [
{
width: 180,
label: 'Version',
dataKey: 'name',
},
{
width: 140,
label: 'Créée le',
dataKey: 'date_created',
numeric: true,
},
{
width: 200,
label: 'Actions',
dataKey: 'actions',
}
]
const VirtuosoTableComponents = {
Scroller: forwardRef((props, ref) => (
)),
Table: props => (
),
TableHead: forwardRef((props, ref) => ),
TableRow,
TableBody: forwardRef((props, ref) => ),
}
function fixedHeaderContent() {
return (
{columns.map(column => (
{column.label}
))}
)
}
function rowContent({
row,
accessToken,
userId,
countdownRef,
setError,
setIsErrorAlertOpen,
setIsOpenComparison,
setVersionCompare,
outdatedStatusMap,
voteCountsMap
}) {
const handleButtonClick = async versionId => {
const version = await compareVersion({
accessToken,
userId,
versionId,
countdownRef,
setError,
setIsErrorAlertOpen
})
if (version) {
setVersionCompare({...version, versionId})
setIsOpenComparison(true)
}
}
const isOutdated = outdatedStatusMap[row.id] || false
const voteCounts = voteCountsMap[row.id] || null
return (
<>
{columns.map(column => (
{column.dataKey === 'date_created'
? formatDate(row[column.dataKey], 'Pp')
: (column.dataKey === 'actions'
? (
)
: )}
))}
>
)
}
export default function ListVersions({
collection,
data,
accessToken,
userId,
setError,
setIsErrorAlertOpen
}) {
const countdownRef = useRef()
const [viewMode, setViewMode] = useState('table')
const [isOpenComparison, setIsOpenComparison] = useState(false)
const [versionCompare, setVersionCompare] = useState(null)
const [searchTerm, setSearchTerm] = useState('')
const [filters, setFilters] = useState({
author: '',
dateFrom: '',
dateTo: '',
status: ''
})
const [outdatedStatusMap, setOutdatedStatusMap] = useState({})
const [voteCountsMap, setVoteCountsMap] = useState({})
// Fetch outdated status and vote counts for all versions
useEffect(() => {
async function fetchVersionsData() {
const statusMap = {}
const countsMap = {}
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
}
// Fetch vote counts
const counts = await getVoteCounts({
accessToken,
versionId: version.id
})
countsMap[version.id] = counts
} catch (error) {
console.warn(`Failed to fetch data for version ${version.id}:`, error)
statusMap[version.id] = false
countsMap[version.id] = {positive: 0, negative: 0, total: 0}
}
})
)
setOutdatedStatusMap(statusMap)
setVoteCountsMap(countsMap)
}
if (data.length > 0) {
fetchVersionsData()
}
}, [data, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen])
// Filter data based on search and filters
const filteredData = filterVersions(data, searchTerm, filters)
const stats = getFilterStats(data, filteredData)
const versionData = data.find(({id}) => id === versionCompare?.versionId)
// Function to refresh vote counts for a specific version after voting
const refreshVoteCounts = async versionId => {
try {
const counts = await getVoteCounts({
accessToken,
versionId
})
setVoteCountsMap(prev => ({...prev, [versionId]: counts}))
} catch (error) {
console.warn(`Failed to refresh vote counts for version ${versionId}:`, error)
}
}
const handleSearchChange = newSearchTerm => {
setSearchTerm(newSearchTerm)
}
const handleFiltersChange = newFilters => {
setFilters(newFilters)
}
const handleViewModeChange = (event, newViewMode) => {
if (newViewMode !== null) {
setViewMode(newViewMode)
}
}
return (
<>
{collection}
{stats.hidden > 0 && (
({stats.filtered}/{stats.total} versions)
)}
Table
Timeline
{filteredData.length === 0 ? (
{searchTerm || Object.values(filters).some(Boolean)
? 'Aucune version ne correspond aux critères de recherche'
: 'Aucune version disponible'}
) : (
viewMode === 'table' ? (
rowContent({
index, row, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen, setIsOpenComparison, setVersionCompare, outdatedStatusMap, voteCountsMap
})}
/>
) : (
)
)}
{isOpenComparison && (
)}
>
)
}
ListVersions.propTypes = {
collection: PropTypes.oneOf(['titres', 'articles']).isRequired,
data: PropTypes.array.isRequired,
accessToken: PropTypes.string.isRequired,
userId: PropTypes.string.isRequired,
setError: PropTypes.func.isRequired,
setIsErrorAlertOpen: PropTypes.func.isRequired
}