feat: ajoute composant VersionFilters
This commit is contained in:
@@ -0,0 +1,205 @@
|
|||||||
|
import {useState, useMemo} from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import Box from '@mui/material/Box'
|
||||||
|
import FormControl from '@mui/material/FormControl'
|
||||||
|
import InputLabel from '@mui/material/InputLabel'
|
||||||
|
import Select from '@mui/material/Select'
|
||||||
|
import MenuItem from '@mui/material/MenuItem'
|
||||||
|
import TextField from '@mui/material/TextField'
|
||||||
|
import Chip from '@mui/material/Chip'
|
||||||
|
import Button from '@mui/material/Button'
|
||||||
|
import ClearIcon from '@mui/icons-material/Clear'
|
||||||
|
import FilterListIcon from '@mui/icons-material/FilterList'
|
||||||
|
import {formatDate} from '@/lib/format.js'
|
||||||
|
|
||||||
|
export default function VersionFilters({data, onFiltersChange}) {
|
||||||
|
const [filters, setFilters] = useState({
|
||||||
|
author: '',
|
||||||
|
dateFrom: '',
|
||||||
|
dateTo: '',
|
||||||
|
status: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// Extract unique authors from data
|
||||||
|
const authors = useMemo(() => {
|
||||||
|
const authorSet = new Set()
|
||||||
|
for (const version of data) {
|
||||||
|
if (version.user_created) {
|
||||||
|
const authorName = version.user_created.split('-')[0]
|
||||||
|
authorSet.add(authorName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...authorSet].sort()
|
||||||
|
}, [data])
|
||||||
|
|
||||||
|
// Extract date range from data
|
||||||
|
const dateRange = useMemo(() => {
|
||||||
|
if (data.length === 0) {
|
||||||
|
return {min: '', max: ''}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dates = data.map(v => new Date(v.date_created))
|
||||||
|
const minDate = new Date(Math.min(...dates))
|
||||||
|
const maxDate = new Date(Math.max(...dates))
|
||||||
|
|
||||||
|
return {
|
||||||
|
min: minDate.toISOString().split('T')[0],
|
||||||
|
max: maxDate.toISOString().split('T')[0]
|
||||||
|
}
|
||||||
|
}, [data])
|
||||||
|
|
||||||
|
const handleFilterChange = (filterKey, value) => {
|
||||||
|
const newFilters = {...filters, [filterKey]: value}
|
||||||
|
setFilters(newFilters)
|
||||||
|
onFiltersChange(newFilters)
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearAllFilters = () => {
|
||||||
|
const emptyFilters = {
|
||||||
|
author: '',
|
||||||
|
dateFrom: '',
|
||||||
|
dateTo: '',
|
||||||
|
status: ''
|
||||||
|
}
|
||||||
|
setFilters(emptyFilters)
|
||||||
|
onFiltersChange(emptyFilters)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasActiveFilters = Object.values(filters).some(value => value !== '')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{mb: 2}}>
|
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 2,
|
||||||
|
mb: 2,
|
||||||
|
flexWrap: 'wrap'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FilterListIcon color='action' />
|
||||||
|
|
||||||
|
<FormControl size='small' sx={{minWidth: 120}}>
|
||||||
|
<InputLabel>Auteur</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={filters.author}
|
||||||
|
label='Auteur'
|
||||||
|
onChange={event => handleFilterChange('author', event.target.value)}
|
||||||
|
>
|
||||||
|
<MenuItem value=''>Tous les auteurs</MenuItem>
|
||||||
|
{authors.map(author => (
|
||||||
|
<MenuItem key={author} value={author}>
|
||||||
|
@{author}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
size='small'
|
||||||
|
label='Du'
|
||||||
|
type='date'
|
||||||
|
value={filters.dateFrom}
|
||||||
|
InputLabelProps={{shrink: true}}
|
||||||
|
inputProps={{
|
||||||
|
min: dateRange.min,
|
||||||
|
max: dateRange.max
|
||||||
|
}}
|
||||||
|
sx={{width: 160}}
|
||||||
|
onChange={event => handleFilterChange('dateFrom', event.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
size='small'
|
||||||
|
label='Au'
|
||||||
|
type='date'
|
||||||
|
value={filters.dateTo}
|
||||||
|
InputLabelProps={{shrink: true}}
|
||||||
|
inputProps={{
|
||||||
|
min: filters.dateFrom || dateRange.min,
|
||||||
|
max: dateRange.max
|
||||||
|
}}
|
||||||
|
sx={{width: 160}}
|
||||||
|
onChange={event => handleFilterChange('dateTo', event.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormControl size='small' sx={{minWidth: 120}}>
|
||||||
|
<InputLabel>Statut</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={filters.status}
|
||||||
|
label='Statut'
|
||||||
|
onChange={event => handleFilterChange('status', event.target.value)}
|
||||||
|
>
|
||||||
|
<MenuItem value=''>Tous les statuts</MenuItem>
|
||||||
|
<MenuItem value='current'>En cours</MenuItem>
|
||||||
|
<MenuItem value='archived'>Archivé</MenuItem>
|
||||||
|
<MenuItem value='outdated'>Obsolète</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
{hasActiveFilters && (
|
||||||
|
<Button
|
||||||
|
size='small'
|
||||||
|
variant='outlined'
|
||||||
|
startIcon={<ClearIcon />}
|
||||||
|
onClick={clearAllFilters}
|
||||||
|
>
|
||||||
|
Effacer filtres
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Active filters display */}
|
||||||
|
{hasActiveFilters && (
|
||||||
|
<Box sx={{display: 'flex', gap: 1, flexWrap: 'wrap'}}>
|
||||||
|
{filters.author && (
|
||||||
|
<Chip
|
||||||
|
label={`Auteur: @${filters.author}`}
|
||||||
|
size='small'
|
||||||
|
color='primary'
|
||||||
|
variant='outlined'
|
||||||
|
onDelete={() => handleFilterChange('author', '')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{filters.dateFrom && (
|
||||||
|
<Chip
|
||||||
|
label={`Du: ${formatDate(filters.dateFrom, 'dd/MM/yyyy')}`}
|
||||||
|
size='small'
|
||||||
|
color='primary'
|
||||||
|
variant='outlined'
|
||||||
|
onDelete={() => handleFilterChange('dateFrom', '')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{filters.dateTo && (
|
||||||
|
<Chip
|
||||||
|
label={`Au: ${formatDate(filters.dateTo, 'dd/MM/yyyy')}`}
|
||||||
|
size='small'
|
||||||
|
color='primary'
|
||||||
|
variant='outlined'
|
||||||
|
onDelete={() => handleFilterChange('dateTo', '')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{filters.status && (
|
||||||
|
<Chip
|
||||||
|
label={`Statut: ${(
|
||||||
|
filters.status === 'current' ? 'En cours'
|
||||||
|
: (filters.status === 'archived' ? 'Archivé'
|
||||||
|
: 'Obsolète')
|
||||||
|
)}`}
|
||||||
|
size='small'
|
||||||
|
color='primary'
|
||||||
|
variant='outlined'
|
||||||
|
onDelete={() => handleFilterChange('status', '')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
VersionFilters.propTypes = {
|
||||||
|
data: PropTypes.array.isRequired,
|
||||||
|
onFiltersChange: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user