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