"use client"; import { useEffect, useMemo, useState } from "react"; import * as d3 from "d3"; import { taxes } from '@/src/data/taxes'; import { CommuneData } from "@/src/type/CommuneData"; import { Departement } from "@/src/type/Departement"; import { years } from "@/src/data/years"; import Nuage_svg from "@/src/components/svg/Nuage_svg"; import { fetchDepartements, fetchCommuneStats } from "@/src/services/communeService"; import { useQuery } from "@tanstack/react-query"; export default function Nuage() { const [year, setYear] = useState(2022); const [taxe, setTaxe] = useState("cves"); //const [departements, setDepartements] = useState([]); const [selectedDepartement, setSelectedDepartement] = useState(""); const [hovered, setHovered] = useState(null); //const [data, setData] = useState([]); //const [isLoading, setIsLoading] = useState(false); const [isExpanded, setIsExpanded] = useState(false); const [tooltip, setTooltip] = useState<{ x: number; y: number; data: CommuneData; } | null>(null); const width = 700; const height = 420; const margin = { top: 40, right: 30, bottom: 50, left: 60 }; /** * Récupérer tous les départements */ const { data: departements = [] } = useQuery({ queryKey: ['departements'], queryFn: fetchDepartements, staleTime: Infinity, // Les départements ne changent jamais en théorie }); // Sélectionne le premier département pour le select useMemo(() => { if (departements.length > 0 && !selectedDepartement) { setSelectedDepartement(departements[0].nom); } }, [departements, selectedDepartement]); /** * Récupérer les communes en fonction du départements */ const { data = [], isLoading } = useQuery({ queryKey: ['nuageData', taxe, selectedDepartement, year], queryFn: () => fetchCommuneStats(taxe, selectedDepartement, year), enabled: !!selectedDepartement, // attente d'un département placeholderData: (prev) => prev, staleTime: 1000 * 60 * 2, // Cache de 2 minutes }); const communes = useMemo(() => { return Array.from(new Set(data.map(d => d.commune))); }, [data]); /** * Couleurs */ const colorScale = useMemo(() => { return d3.scaleOrdinal() .domain(communes) .range(d3.schemeTableau10); }, [communes]); /** * Scales */ const xScale = useMemo(() => { const domain = data.length ? d3.extent(data, d => d.taxRate) as [number, number] : [0, 100]; return d3.scaleLinear() .domain(domain) .nice() .range([margin.left, width - margin.right]); }, [data]); const yScale = useMemo(() => { const domain = data.length ? d3.extent(data, d => d.volume) as [number, number] : [0, 1000000]; return d3.scaleLinear() .domain(domain) .nice() .range([height - margin.bottom, margin.top]); }, [data]); if (!xScale || !yScale) return

Chargement...

; const xTicks = xScale.ticks(5); const yTicks = yScale.ticks(5); return (

Relation taux d'imposition / Volume collecté

{/* Options */}
{isLoading &&

Chargement...

} {/* SVG */} {tooltip && (
{tooltip.data.commune}
Taux : {tooltip.data.taxRate.toFixed(2)} %
Volume : {d3.format(",")(tooltip.data.volume)} €
)} {/* Légende */}
{(isExpanded ? communes : communes.slice(0, 30)).map(commune => (
setHovered(commune)} onMouseLeave={() => setHovered(null)} className="flex items-center gap-2 cursor-pointer group" style={{ width: 'fit-content' }} // Empêche certains comportements de saut > {commune}
))}
{/* Bouton Voir plus / Voir moins */} {communes.length > 30 && (
)}
); }