import {useParams} from "react-router-dom" import FormGroup from '@mui/material/FormGroup' import FormControlLabel from '@mui/material/FormControlLabel' import Table from '@mui/material/Table' import TableBody from '@mui/material/TableBody' import TableCell from '@mui/material/TableCell' import TableContainer from '@mui/material/TableContainer' import TableHead from '@mui/material/TableHead' import TableRow from '@mui/material/TableRow' import Paper from '@mui/material/Paper' import Switch from '@mui/material/Switch' import * as Highcharts from 'highcharts' import highchartsItem from 'highcharts/modules/item-series' import HighchartsReact from 'highcharts-react-official' import {useEffect, useState} from "react" import {GeoJSON, MapContainer, Popup, TileLayer, useMap} from "react-leaflet" import 'leaflet/dist/leaflet.css' highchartsItem(Highcharts) function ResultatsTable({blocs, nuances, listes, resultats, siegesParListe}) { const voix_listes = resultats?.voix_listes ?? {} const listes_triees = listes.toSorted((l1, l2) => { return (voix_listes[l2.numero] || 0) - (voix_listes[l1.numero] || 0) }) return <> Numéro Liste Nuance Bloc Voix % Inscrit⋅es % Exprimé⋅es Sièges {listes_triees.map((liste) => ( ))}
} function ListeRow({liste, voix, resultats, siegesParListe, blocs, nuances}) { const bloc = blocs.filter(bloc => bloc.nom === liste.bloc)[0] const nuance = nuances.filter(nuance => nuance.code === liste.nuance)[0] return {liste.numero} {liste.nom} {liste.nuance} {liste.bloc} {voix} {(100 * voix / resultats.inscrits).toFixed(2)} % {(100 * voix / resultats.exprimes).toFixed(2)} % {siegesParListe[liste.numero]} } function ParticipationTable({resultats}) { return <> Nombre % Inscrit⋅es % Votant⋅es Inscrit⋅es {resultats.inscrits} Abstention {resultats.abstentions} {(100 * resultats.abstentions / resultats.inscrits).toFixed(2)} % Votant⋅es {resultats.votants} {(100 * resultats.votants / resultats.inscrits).toFixed(2)} % Blancs {resultats.blancs} {(100 * resultats.blancs / resultats.inscrits).toFixed(2)} % {(100 * resultats.blancs / resultats.votants).toFixed(2)} % Nuls {resultats.nuls} {(100 * resultats.nuls / resultats.inscrits).toFixed(2)} % {(100 * resultats.nuls / resultats.votants).toFixed(2)} % Exprimés {resultats.exprimes} {(100 * resultats.exprimes / resultats.inscrits).toFixed(2)} % {(100 * resultats.exprimes / resultats.votants).toFixed(2)} %
} function RegionGeoJSON({resultats_region, listes, blocs, nuances, grouperParBloc = false}) { const voix_listes = resultats_region?.voix_listes ?? {} const listes_triees = listes.toSorted((l1, l2) => { return (voix_listes[l2.numero] || 0) - (voix_listes[l1.numero] || 0) }) const voixParBloc = {} const voixParNuance = {} for (let bloc of blocs) { voixParBloc[bloc.nom] = 0 } for (let nuance of nuances) { voixParNuance[nuance.code] = 0 } for (let liste of listes) { voixParBloc[liste.bloc] += resultats_region.voix_listes[liste.numero] || 0 voixParNuance[liste.nuance] += resultats_region.voix_listes[liste.numero] || 0 } let couleur = 'grey' if (grouperParBloc) { let maxVoix = 0 for (let bloc of blocs) { if (voixParBloc[bloc.nom] > maxVoix) { maxVoix = voixParBloc[bloc.nom] couleur = bloc.couleur } } } else { let maxVoix = 0 for (let nuance of nuances) { if (voixParNuance[nuance.code] > maxVoix) { maxVoix = voixParNuance[nuance.code] couleur = nuance.couleur } } } return {resultats_region.region.nom} } function ContenuCarte({typeResultats, resultats, listes, blocs, nuances, grouperParBloc = false}) { const [regions, setRegions] = useState([]) useEffect(() => { if (!resultats || !resultats.france || !resultats.france.regions) return setRegions(regions => []) resultats.france.regions.forEach(region_code => { fetch(`/data/resultats/europeennes2024/regions/${region_code}.json`).then(response => response.json()) .then(region => setRegions(regions => [...regions, region])) }) }, [typeResultats, resultats]) const map = useMap() return <> {regions.map(region => )} } function Carte({typeResultats, resultats, listes, blocs, nuances, grouperParBloc = false}) { const center = [46.603354, 1.888334] return <> } export default function Election2024({typeResultats = "france"}) { const {zoneId} = useParams() const [zoneName, setZoneName] = useState("France") const [grouperParBloc, setGrouperParBloc] = useState(false) const [retirerSeuil, setRetirerSeuil] = useState(false) const [blocs, setBlocs] = useState([]) const [nuances, setNuances] = useState([]) const [listes, setListes] = useState([]) const [resultats, setResultats] = useState([]) const [siegesParListe, setSiegesParListe] = useState({}) const [voixParBloc, setVoixParBloc] = useState([]) const [voixParNuance, setVoixParNuance] = useState([]) const [siegesParBloc, setSiegesParBloc] = useState([]) const [siegesParNuance, setSiegesParNuance] = useState([]) const [categoriesVoix, setCategoriesVoix] = useState([]) const [dataVoix, setDataVoix] = useState([]) const [dataSieges, setDataSieges] = useState([]) useEffect(() => { fetch("/data/resultats/europeennes2024/blocs.json").then(response => response.json()) .then(data => setBlocs(data)) fetch("/data/resultats/europeennes2024/nuances.json").then(response => response.json()) .then(data => setNuances(data)) fetch("/data/resultats/europeennes2024/listes.json").then(response => response.json()) .then(data => setListes(data)) if (typeResultats === "france") { fetch("/data/resultats/europeennes2024/france.json").then(response => response.json()) .then(data => setResultats(data)) } else { fetch(`/data/resultats/europeennes2024/${typeResultats}/${zoneId}.json`).then(response => response.json()) .then(data => setResultats(data)) } }, [typeResultats, zoneId]) useEffect(() => { if (!resultats || resultats.length === 0) setZoneName("") else if (typeResultats === "france") setZoneName("France") else if (typeResultats === "regions") setZoneName(`Région ${resultats.region.nom}`) else if (typeResultats === "departements") setZoneName(`Département ${resultats.departement.nom}`) else if (typeResultats === "circonscriptions") setZoneName(`Circonscription ${resultats.circonscription.nom}`) else if (typeResultats === "communes") setZoneName(`Commune ${resultats.commune.nom}`) else if (typeResultats === "bureaux_vote") setZoneName(resultats.bureau_vote.libelle) }, [typeResultats, resultats]) useEffect(() => { const parBloc = {} const parNuance = {} for (let bloc of blocs) { parBloc[bloc.nom] = 0 } for (let nuance of nuances) { parNuance[nuance.code] = 0 } for (let liste of listes) { parBloc[liste.bloc] += resultats.voix_listes[liste.numero] || 0 parNuance[liste.nuance] += resultats.voix_listes[liste.numero] || 0 } setVoixParBloc(parBloc) setVoixParNuance(parNuance) }, [blocs, nuances, listes, resultats]) useEffect(() => { const categories = [] const data = [] if (grouperParBloc) { for (let bloc of blocs) { categories.push(bloc.nom) data.push([bloc.nom, voixParBloc[bloc.nom], bloc.couleur, bloc.nom]) } } else { for (let nuance of nuances) { categories.push(nuance.nom) data.push([nuance.nom, voixParNuance[nuance.code], nuance.couleur, nuance.nom]) } } setCategoriesVoix(categories) setDataVoix(data) }, [voixParBloc, voixParNuance, grouperParBloc]) useEffect(() => { const MAX_SIEGES = 81 const sieges = {} const listesElues = [] let siegesAffectes = 0 let totalVoix = resultats.exprimes for (let liste of listes) { const voix = resultats.voix_listes[liste.numero] || 0 if (voix / resultats.exprimes < 0.05 && !retirerSeuil) { // Barre des 5 % non franchie totalVoix -= voix sieges[liste.numero] = 0 } else { listesElues.push(liste) } } if (listesElues.length === 0) return for (let liste of listesElues) { const voix = resultats.voix_listes[liste.numero] || 0 sieges[liste.numero] = Math.floor(MAX_SIEGES * voix / totalVoix) siegesAffectes += sieges[liste.numero] } while (siegesAffectes < MAX_SIEGES) { // Méthode de la plus forte moyenne pour affecter les sièges restants let maxMoyenne = 0 let listeElue = null for (let liste of listesElues) { if (sieges[liste.numero] < MAX_SIEGES) { const voix = resultats.voix_listes[liste.numero] || 0 const moyenne = voix / (sieges[liste.numero] + 1) if (moyenne > maxMoyenne) { maxMoyenne = moyenne listeElue = liste } } } sieges[listeElue.numero]++ siegesAffectes++ } setSiegesParListe(sieges) }, [listes, resultats, retirerSeuil]) useEffect(() => { const parBloc = {} const parNuance = {} for (let bloc of blocs) { parBloc[bloc.nom] = 0 } for (let nuance of nuances) { parNuance[nuance.code] = 0 } for (let liste of listes) { parBloc[liste.bloc] += siegesParListe[liste.numero] || 0 parNuance[liste.nuance] += siegesParListe[liste.numero] || 0 } setSiegesParBloc(parBloc) setSiegesParNuance(parNuance) }, [blocs, nuances, listes, siegesParListe]) useEffect(() => { const data = [] if (grouperParBloc) { for (let bloc of blocs) { data.push([bloc.nom, siegesParBloc[bloc.nom], bloc.couleur, bloc.nom]) } } else { for (let nuance of nuances) { data.push([nuance.nom, siegesParNuance[nuance.code], nuance.couleur, nuance.nom]) } } setDataSieges(data) }, [blocs, nuances, siegesParBloc, siegesParNuance, grouperParBloc]) const compositonOptions = { chart: { type: 'item' }, title: { text: 'Projection eurodéputé⋅es français⋅es 2024' }, legend: { labelFormat: '{name} {y}' }, series: [{ name: 'Nombre de sièges', keys: ['name', 'y', 'color', 'label'], data: dataSieges, dataLabels: { enabled: false, format: '{point.label}' }, // Circular options center: ['50%', '88%'], size: '170%', startAngle: -100, endAngle: 100 }] } const scoreOptions = { chart: { type: 'column' }, title: { text: `Résultats des élections européennes 2024 : ${zoneName}`, }, tooltip: { formatter: function () { return `${this.x} : ${this.y} voix (${(100 * this.y / resultats.exprimes).toFixed(2)} %)
` } }, xAxis: { categories: categoriesVoix, }, series: [{ name: "Nombre de voix", keys: ['name', 'y', 'color', 'label'], data: dataVoix, }] } return <> setGrouperParBloc(event.target.checked)} inputProps={{ 'aria-label': 'controlled' }} />} label="Grouper par bloc plutôt que nuance politique" /> setRetirerSeuil(event.target.checked)} inputProps={{ 'aria-label': 'controlled' }} />} label="Retirer le seuil des 5 %" /> }