import { useEffect, useState, useRef } from "react"; import PropTypes from "prop-types"; import axios from "axios"; import * as d3 from "d3"; const FranceMap = ({ typeIndic = "indicateurs" }) => { if (typeof typeIndic !== "string") { console.error("typeIndic doit être une chaîne de caractères, reçu :", typeIndic); typeIndic = "indicateurs"; // Valeur par défaut } console.log("typeIndic reçu :", typeIndic); const [geoData, setGeoData] = useState(null); const [deptColors, setDeptColors] = useState({}); const [deptAverages, setDeptAverages] = useState({}); const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); const [selectedDept, setSelectedDept] = useState(null); const svgRef = useRef(); const containerRef = useRef(); // Charger les données GeoJSON useEffect(() => { console.log("url : ", "http://localhost:5000/api/" + typeIndic); axios .get("/France_dep.geojson") .then((res) => { setGeoData(res.data.features); }) .catch((err) => console.error("Erreur lors du chargement du GeoJSON :", err)); // Charger les couleurs depuis l'API backend axios.get("http://localhost:5000/api/" + typeIndic) .then((res) => { console.log("Couleurs reçues du backend :", res.data.colors); setDeptColors(res.data.colors); console.log("Moyennes reçues du backend :", res.data.averages); setDeptAverages(res.data.averages); }) .catch((err) => console.error("Erreur lors du chargement des couleurs :", err)); }, [typeIndic]); // Calculer la taille du conteneur parent et mettre à jour les dimensions useEffect(() => { const updateDimensions = () => { const { clientWidth, clientHeight } = containerRef.current; setDimensions({ width: clientWidth * 0.75, height: clientHeight * 0.75, }); }; updateDimensions(); window.addEventListener("resize", updateDimensions); return () => window.removeEventListener("resize", updateDimensions); }, []); // Mettre à jour la carte avec les nouvelles dimensions et couleurs useEffect(() => { if (!geoData || dimensions.width === 0 || dimensions.height === 0) return; const svg = d3.select(svgRef.current) .attr("width", dimensions.width) .attr("height", dimensions.height); const projection = d3.geoMercator() .fitSize([dimensions.width, dimensions.height], { type: "FeatureCollection", features: geoData }); const pathGenerator = d3.geoPath().projection(projection); const tooltip = d3.select("#tooltip"); svg.selectAll("path") .data(geoData) .join("path") .attr("d", pathGenerator) .attr("stroke", "black") .attr("fill", d => deptColors[d.properties.code] || "lightgray") .attr("opacity", 0.8) .on("click", function (event, d) { if (d && d.properties) { console.log(`Département sélectionné : ${d.properties.nom} (${d.properties.code})`); setSelectedDept(d); } else { console.error("Données du département manquantes ou mal formatées", d); } }) .on("mouseover", function (event, d) { // Diminuer l'opacité des autres départements (50%) svg.selectAll("path") .attr("opacity", (dept) => dept.properties.code === d.properties.code || dept === selectedDept ? 1 : 0.25); tooltip.style("display", "block") .html(`<strong>${d.properties.nom} (${d.properties.code})</strong><br>Score moyen : ${deptAverages[d.properties.code] || "N/A"}`) .style("left", event.pageX + 3 + "px") .style("top", event.pageY + 3 + "px"); }) .on("mousemove", function (event) { tooltip.style("left", event.pageX -185 + "px") .style("top", event.pageY -50 + "px"); }) .on("mouseout", function () { // Rétablir l'opacité à 100% pour tous les départements svg.selectAll("path") .attr("opacity", 1); tooltip.style("display", "none"); }) .attr("fill", (d) => { if (selectedDept && selectedDept.properties.code === d.properties.code) { return "red"; // Couleur pour le département sélectionné } return deptColors[d.properties.code] || "lightgray"; }); }, [geoData, deptColors, dimensions, selectedDept, deptAverages]); return ( <div ref={containerRef} style={{ position: "relative", width: "100%", height: "100%", display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center" }}> <h1 style={{ textAlign: "center", fontSize: "2em" }}>Carte de France</h1> <svg ref={svgRef}></svg> <div id="tooltip" style={{ position: "absolute", background: "white", padding: "5px", borderRadius: "5px", border: "1px solid black", display: "none" }}></div> </div> ); }; FranceMap.propTypes = { typeIndic: PropTypes.string, }; export default FranceMap;