Newer
Older
import { useEffect, useState } from 'react'
import { LineChart, Line, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer, CartesianGrid } from 'recharts'
import { getRegions, getTimeSeries, type TimeSeriesData } from '../../services/temporal.services'
import { TAX_TYPES, YEARS, COLORS } from '../../constants'
import ErrorDiv from '../molecules/ErrorDiv'
export default function Temporal() {
const [taxType, setTaxType] = useState<string>('tfpb')
const [startYear, setStartYear] = useState<number>(2019)
const [endYear, setEndYear] = useState<number>(2022)
const [data, setData] = useState<TimeSeriesData | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [regions, setRegions] = useState<string[]>([])
const [selectedRegions, setSelectedRegions] = useState<string[]>([])
useEffect(() => {
getRegions().then(r => {
setRegions(r)
setSelectedRegions(r)
})
}, [])
const toggleRegion = (region: string) => {
setSelectedRegions(prev => (prev.includes(region) ? prev.filter(r => r !== region) : [...prev, region]))
}
const handleSubmit = async () => {
setLoading(true)
setError(null)
try {
const result = await getTimeSeries([], taxType, startYear, endYear)
setData(result)
} catch (e) {
setData(null)
setError(e instanceof Error ? e.message : 'Une erreur est survenue')
} finally {
setLoading(false)
}
const visibleRegions = data ? Object.keys(data).filter(r => selectedRegions.includes(r)) : []
? YEARS.filter(y => y >= startYear && y <= endYear).map(year => {
const point: Record<string, number | string> = { year }
for (const region of visibleRegions) {
const entry = data[region]?.find(e => e.year === year)
if (entry) point[region] = parseFloat(entry.avg_rate)
}
return point
})
: []
return (
<div className="p-6 text-white flex flex-col gap-6">
<h2 className="text-lg font-semibold">Taux d'imposition moyen par region</h2>
<div className="flex flex-wrap gap-4 items-end">
<div className="flex flex-col gap-1">
<label className="text-xs text-[#b0afaf] uppercase">Taxe</label>
onChange={e => setTaxType(e.target.value)}
className="bg-[#212529] border border-[#3a3f44] rounded px-3 py-1.5 text-white text-sm"
>
<option key={t} value={t}>
{t.toUpperCase()}
</option>
))}
</select>
</div>
<div className="flex flex-col gap-1">
<label className="text-xs text-[#b0afaf] uppercase">De</label>
onChange={e => setStartYear(Number(e.target.value))}
className="bg-[#212529] border border-[#3a3f44] rounded px-3 py-1.5 text-white text-sm"
>
<option key={y} value={y}>
{y}
</option>
))}
</select>
</div>
<div className="flex flex-col gap-1">
<label className="text-xs text-[#b0afaf] uppercase">A</label>
onChange={e => setEndYear(Number(e.target.value))}
className="bg-[#212529] border border-[#3a3f44] rounded px-3 py-1.5 text-white text-sm"
>
<option key={y} value={y}>
{y}
</option>
))}
</select>
</div>
<button
onClick={handleSubmit}
disabled={loading}
className="bg-[#8884d8] hover:bg-[#7773c7] disabled:opacity-50 text-white text-sm px-4 py-1.5 rounded transition-colors"
>
{loading ? 'Chargement...' : 'Afficher'}
</button>
</div>
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
{regions.length > 0 && (
<div className="flex flex-col gap-2">
<label className="text-xs text-[#b0afaf] uppercase">Régions {selectedRegions.length > 0 && `(${selectedRegions.length})`}</label>
<div className="flex flex-wrap gap-2">
<button
onClick={() => setSelectedRegions(regions)}
className="text-xs px-3 py-1 rounded-full border border-[#3a3f44] text-[#b0afaf] hover:text-white transition-colors"
>
Tous
</button>
<button
onClick={() => setSelectedRegions([])}
className="text-xs px-3 py-1 rounded-full border border-[#3a3f44] text-[#b0afaf] hover:text-white transition-colors"
>
Aucun
</button>
{regions.map(region => (
<button
key={region}
onClick={() => toggleRegion(region)}
className={`text-xs px-3 py-1 rounded-full border transition-colors ${
selectedRegions.includes(region)
? 'bg-[#8884d8] border-[#8884d8] text-white'
: 'border-[#3a3f44] text-[#b0afaf] hover:text-white'
}`}
>
{region}
</button>
))}
</div>
</div>
)}
{error && <ErrorDiv message={error} />}
{!error && chartData.length > 0 && (
<ResponsiveContainer width="100%" height={400}>
<LineChart data={chartData}>
<CartesianGrid strokeDasharray="3 3" stroke="#3a3f44" />
<XAxis dataKey="year" stroke="#b0afaf" />
<YAxis stroke="#b0afaf" tickFormatter={(v: number) => `${v}%`} />
<Tooltip
contentStyle={{
backgroundColor: '#212529',
border: '1px solid #3a3f44',
borderRadius: 8,
}}
formatter={(value, name) => [`${value}%`, name]}
/>
<Legend
wrapperStyle={{
paddingTop: '20px',
}}
<Line
key={region}
type="monotone"
dataKey={region}
stroke={COLORS[regions.indexOf(region) % COLORS.length]}