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 } from '../../constants'
import ErrorDiv from '../molecules/ErrorDiv'
const COLORS = [
'#8884d8',
'#82ca9d',
'#ffc658',
'#ff7300',
'#00C49F',
'#0088FE',
'#FF8042',
'#A4DE6C',
'#D0ED57',
'#FFBB28',
'#FF4444',
'#44AAFF',
'#AA44FF',
'#E91E63',
'#4CAF50',
'#9C27B0',
'#00BCD4',
'#FF5722',
'#607D8B',
'#795548',
]
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>
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
{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]}