Affichage élections législatives 2022
This commit is contained in:
parent
1b0b894acc
commit
5f279fa949
@ -1,22 +1,39 @@
|
|||||||
import {createBrowserRouter, RouterProvider} from "react-router-dom"
|
import {createBrowserRouter, RouterProvider} from "react-router-dom"
|
||||||
|
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import Elections2024 from './Elections2024'
|
import ElectionsLegislatives2022 from "./ElectionsLegislatives2022"
|
||||||
|
import ElectionsEuropeennes2024 from './ElectionsEuropeennes2024'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
element: <Elections2024 typeResultats="france" />,
|
element: <ElectionsEuropeennes2024 typeResultats="france" />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/elections/legislatives/2022/:typeResultats/",
|
||||||
|
element: <ElectionsLegislatives2022 />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/elections/legislatives/2022/:typeResultats/:zoneId/",
|
||||||
|
element: <ElectionsLegislatives2022 />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/elections/europeennes/2024/:typeResultats/",
|
path: "/elections/europeennes/2024/:typeResultats/",
|
||||||
element: <Elections2024 />,
|
element: <ElectionsEuropeennes2024 />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/elections/europeennes/2024/:typeResultats/:zoneId/",
|
path: "/elections/europeennes/2024/:typeResultats/:zoneId/",
|
||||||
element: <Elections2024 />
|
element: <ElectionsEuropeennes2024 />
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// path: "/elections/legislatives/2024/:typeResultats/",
|
||||||
|
// element: <ElectionsLegislatives2024 />,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: "/elections/legislatives/2024/:typeResultats/:zoneId/",
|
||||||
|
// element: <ElectionsLegislatives2024 />
|
||||||
|
// },
|
||||||
])
|
])
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
|
@ -63,6 +63,27 @@ export default function ElectionsEuropeennes2024() {
|
|||||||
const siegesParListe = calculerSieges(listes, donnees, retirerSeuil ? 0 : 0.05)
|
const siegesParListe = calculerSieges(listes, donnees, retirerSeuil ? 0 : 0.05)
|
||||||
const [siegesParBloc, siegesParNuance] = regrouperVoix(siegesParListe, listes, blocs, nuances)
|
const [siegesParBloc, siegesParNuance] = regrouperVoix(siegesParListe, listes, blocs, nuances)
|
||||||
|
|
||||||
|
const [categoriesHistogramme, valeursHistogramme, couleursHistogramme] = useMemo(() => {
|
||||||
|
if (grouperParBloc) {
|
||||||
|
const categories = {}
|
||||||
|
const couleurs = {}
|
||||||
|
for (let bloc of blocs) {
|
||||||
|
categories[bloc.nom] = bloc.nom
|
||||||
|
couleurs[bloc.nom] = bloc.couleur
|
||||||
|
}
|
||||||
|
return [categories, voixParBloc, couleurs]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const categories = {}
|
||||||
|
const couleurs = {}
|
||||||
|
for (let nuance of nuances) {
|
||||||
|
categories[nuance.code] = nuance.nom
|
||||||
|
couleurs[nuance.code] = nuance.couleur
|
||||||
|
}
|
||||||
|
return [categories, voixParNuance, couleurs]
|
||||||
|
}
|
||||||
|
}, [typeResultats, nuances, blocs, donnees, voixParNuance, voixParBloc, grouperParBloc])
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<AppBar position="sticky">
|
<AppBar position="sticky">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
@ -73,8 +94,8 @@ export default function ElectionsEuropeennes2024() {
|
|||||||
</AppBar>
|
</AppBar>
|
||||||
<Container>
|
<Container>
|
||||||
<HistogrammeVoix titre={`Résultats des élections européennes 2024 : ${nomZone}`}
|
<HistogrammeVoix titre={`Résultats des élections européennes 2024 : ${nomZone}`}
|
||||||
resultats={donnees} voixParNuance={voixParNuance} voixParBloc={voixParBloc}
|
nomCategories={categoriesHistogramme} valeurParCategorie={valeursHistogramme}
|
||||||
blocs={blocs} nuances={nuances} grouperParBloc={grouperParBloc} />
|
totalExprimes={donnees.exprimes} couleurParCategorie={couleursHistogramme} />
|
||||||
<CompositionHemicycle titre={`Eurodéputé⋅es français⋅es dans l'hémicycle européen 2024 : ${nomZone}`}
|
<CompositionHemicycle titre={`Eurodéputé⋅es français⋅es dans l'hémicycle européen 2024 : ${nomZone}`}
|
||||||
blocs={blocs} nuances={nuances} siegesParBloc={siegesParBloc} siegesParNuance={siegesParNuance}
|
blocs={blocs} nuances={nuances} siegesParBloc={siegesParBloc} siegesParNuance={siegesParNuance}
|
||||||
grouperParBloc={grouperParBloc} />
|
grouperParBloc={grouperParBloc} />
|
||||||
|
148
nupes-elections-front/src/ElectionsLegislatives2022.js
Normal file
148
nupes-elections-front/src/ElectionsLegislatives2022.js
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import {useParams} from "react-router-dom"
|
||||||
|
import {AppBar, Container, Toolbar} from "@mui/material"
|
||||||
|
import * as Highcharts from 'highcharts'
|
||||||
|
import highchartsItem from 'highcharts/modules/item-series'
|
||||||
|
import {useEffect, useMemo, useState} from "react"
|
||||||
|
import {
|
||||||
|
SelectionAffichage,
|
||||||
|
TableauParticipation,
|
||||||
|
CarteResultats,
|
||||||
|
HistogrammeVoix, GroupementParBloc, SelectionTour
|
||||||
|
} from "./includes/composants_elections"
|
||||||
|
import {getNomZone, regrouperVoix} from "./utils"
|
||||||
|
import 'leaflet/dist/leaflet.css'
|
||||||
|
import {
|
||||||
|
TableauResultatsCandidatsLegislatives,
|
||||||
|
TableauResultatsNuancesLegislatives
|
||||||
|
} from "./includes/composants_elections_legislatives"
|
||||||
|
|
||||||
|
|
||||||
|
highchartsItem(Highcharts)
|
||||||
|
|
||||||
|
export default function ElectionsLegislatives2022() {
|
||||||
|
const {typeResultats, zoneId} = useParams()
|
||||||
|
|
||||||
|
const [grouperParBloc, setGrouperParBloc] = useState(false)
|
||||||
|
const [tour, setTour] = useState(1)
|
||||||
|
const [blocs, setBlocs] = useState([])
|
||||||
|
const [candidats, setCandidats] = useState([])
|
||||||
|
const [nuances, setNuances] = useState([])
|
||||||
|
const [resultats, setResultats] = useState([])
|
||||||
|
const [typeSousZone, setTypeSousZone] = useState("region")
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("/data/resultats/legislatives/2022/blocs.json").then(response => response.json())
|
||||||
|
.then(data => setBlocs(data))
|
||||||
|
fetch("/data/resultats/legislatives/2022/nuances.json").then(response => response.json())
|
||||||
|
.then(data => setNuances(data))
|
||||||
|
|
||||||
|
if (typeResultats === "france") {
|
||||||
|
fetch("/data/resultats/legislatives/2022/france.json").then(response => response.json())
|
||||||
|
.then(data => setResultats(data))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fetch(`/data/resultats/legislatives/2022/${typeResultats}/${zoneId}.json`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => setResultats(data))
|
||||||
|
}
|
||||||
|
}, [typeResultats, zoneId])
|
||||||
|
|
||||||
|
const zoneInfo = useMemo(() => resultats?.zone ?? {}, [resultats])
|
||||||
|
const nomZone = useMemo(() => getNomZone(typeResultats, zoneInfo), [typeResultats, zoneInfo])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let circonscription = ""
|
||||||
|
|
||||||
|
if (typeResultats === "circonscription")
|
||||||
|
circonscription = zoneId
|
||||||
|
else if (typeResultats === "bureau_vote")
|
||||||
|
circonscription = zoneInfo?.circonscription ?? ""
|
||||||
|
else {
|
||||||
|
setCandidats(nuances)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!circonscription)
|
||||||
|
return
|
||||||
|
|
||||||
|
fetch(`/data/resultats/legislatives/2022/candidats/${circonscription}.json`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => setCandidats(data))
|
||||||
|
}, [typeResultats, zoneId, zoneInfo, nuances])
|
||||||
|
|
||||||
|
const donnees = useMemo(() => {
|
||||||
|
if (tour === 1)
|
||||||
|
return resultats?.tour1 ?? {}
|
||||||
|
else if (tour === 2)
|
||||||
|
return resultats?.tour2 ?? {}
|
||||||
|
else
|
||||||
|
return {}
|
||||||
|
}, [resultats, tour])
|
||||||
|
|
||||||
|
const dejaGroupeParNuance = typeResultats !== "circonscription" && typeResultats !== "bureau_vote"
|
||||||
|
const [voixParBloc, voixParNuance] = regrouperVoix(donnees.voix, candidats, blocs, nuances,
|
||||||
|
dejaGroupeParNuance)
|
||||||
|
|
||||||
|
const candidatKey = typeSousZone === "circonscription" || typeSousZone === "bureau_vote" ? "numero" : "code"
|
||||||
|
|
||||||
|
const [categoriesHistogramme, valeursHistogramme, couleursHistogramme] = useMemo(() => {
|
||||||
|
if (grouperParBloc) {
|
||||||
|
const categories = {}
|
||||||
|
const couleurs = {}
|
||||||
|
for (let bloc of blocs) {
|
||||||
|
categories[bloc.nom] = bloc.nom
|
||||||
|
couleurs[bloc.nom] = bloc.couleur
|
||||||
|
}
|
||||||
|
return [categories, voixParBloc, couleurs]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeResultats === "circonscription" || typeResultats === "bureau_vote") {
|
||||||
|
// On affiche les noms des candidat⋅es
|
||||||
|
const categories = {}
|
||||||
|
const couleurs = {}
|
||||||
|
for (let candidat of candidats) {
|
||||||
|
categories[candidat.numero] = `${candidat.prenom} ${candidat.nom} (${candidat.nuance})`
|
||||||
|
couleurs[candidat.numero] = nuances.filter(nuance => nuance.code === candidat.nuance)[0]?.couleur
|
||||||
|
}
|
||||||
|
return [categories, donnees.voix, couleurs]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// On affiche les nuances
|
||||||
|
const categories = {}
|
||||||
|
const couleurs = {}
|
||||||
|
for (let nuance of nuances) {
|
||||||
|
categories[nuance.code] = nuance.nom
|
||||||
|
couleurs[nuance.code] = nuance.couleur
|
||||||
|
}
|
||||||
|
return [categories, voixParNuance, couleurs]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [typeResultats, candidats, nuances, blocs, donnees, voixParNuance, voixParBloc, grouperParBloc])
|
||||||
|
|
||||||
|
const tableauResultats = useMemo(() => {
|
||||||
|
if (typeResultats === "circonscription" || typeResultats === "bureau_vote")
|
||||||
|
return <TableauResultatsCandidatsLegislatives candidats={candidats} blocs={blocs} nuances={nuances} donnees={donnees} />
|
||||||
|
else
|
||||||
|
return <TableauResultatsNuancesLegislatives blocs={blocs} nuances={nuances} donnees={donnees} />
|
||||||
|
}, [typeResultats, candidats, blocs, nuances, donnees])
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<AppBar position="sticky">
|
||||||
|
<Toolbar>
|
||||||
|
<GroupementParBloc grouperParBloc={grouperParBloc} setGrouperParBloc={setGrouperParBloc} />
|
||||||
|
<SelectionAffichage typeResultats={typeResultats} typeSousZone={typeSousZone} setTypeSousZone={setTypeSousZone} />
|
||||||
|
<SelectionTour tour={tour} setTour={setTour} />
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
<Container>
|
||||||
|
<HistogrammeVoix titre={`Résultats des élections législatives 2022 : ${nomZone}`}
|
||||||
|
nomCategories={categoriesHistogramme} valeurParCategorie={valeursHistogramme}
|
||||||
|
totalExprimes={donnees.exprimes} couleurParCategorie={couleursHistogramme} />
|
||||||
|
{tableauResultats}
|
||||||
|
<TableauParticipation resultats={donnees} />
|
||||||
|
<CarteResultats typeElection={"legislatives"} anneeElection={"2022"} typeResultats={typeResultats} zoneInfo={zoneInfo}
|
||||||
|
typeSousZone={typeSousZone} candidats={candidats} blocs={blocs} nuances={nuances} tour={tour}
|
||||||
|
grouperParBloc={grouperParBloc} candidatKey={candidatKey} />
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
}
|
@ -16,25 +16,19 @@ import Switch from "@mui/material/Switch";
|
|||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
|
|
||||||
|
|
||||||
export function HistogrammeVoix({titre, resultats, voixParNuance, voixParBloc, blocs, nuances, grouperParBloc}) {
|
export function HistogrammeVoix({titre, nomCategories, valeurParCategorie, totalExprimes, couleurParCategorie}) {
|
||||||
const [categoriesVoix, dataVoix] = useMemo(() => {
|
const [categoriesVoix, dataVoix] = useMemo(() => {
|
||||||
const categories = []
|
const categories = []
|
||||||
const data = []
|
const data = []
|
||||||
if (grouperParBloc) {
|
|
||||||
for (let bloc of blocs) {
|
for (let categorie of Object.keys(nomCategories)) {
|
||||||
categories.push(bloc.nom)
|
categories.push(nomCategories[categorie])
|
||||||
data.push([bloc.nom, voixParBloc[bloc.nom], bloc.couleur, bloc.nom])
|
data.push([nomCategories[categorie], valeurParCategorie[categorie], couleurParCategorie[categorie],
|
||||||
}
|
nomCategories[categorie]])
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (let nuance of nuances) {
|
|
||||||
categories.push(nuance.nom)
|
|
||||||
data.push([nuance.nom, voixParNuance[nuance.code], nuance.couleur, nuance.nom])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [categories, data]
|
return [categories, data]
|
||||||
}, [voixParBloc, voixParNuance, blocs, nuances, grouperParBloc])
|
}, [nomCategories, valeurParCategorie, couleurParCategorie])
|
||||||
|
|
||||||
const scoreOptions = {
|
const scoreOptions = {
|
||||||
chart: {
|
chart: {
|
||||||
@ -45,7 +39,7 @@ export function HistogrammeVoix({titre, resultats, voixParNuance, voixParBloc, b
|
|||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
formatter: function () {
|
formatter: function () {
|
||||||
return `<span>${this.x}</span> : <strong>${this.y}</strong> voix (${(100 * this.y / resultats.exprimes).toFixed(2)} %)<br>`
|
return `<span>${this.x}</span> : <strong>${this.y}</strong> voix (${(100 * this.y / totalExprimes).toFixed(2)} %)<br>`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
@ -244,9 +238,11 @@ export function SelectionAffichage({typeResultats, typeSousZone, setTypeSousZone
|
|||||||
|
|
||||||
|
|
||||||
function ZoneGeoJSON({typeElection, anneeElection, resultatsZone, typeSousZone,
|
function ZoneGeoJSON({typeElection, anneeElection, resultatsZone, typeSousZone,
|
||||||
candidats, blocs, nuances, tour, grouperParBloc = false}) {
|
candidats, blocs, nuances, tour, grouperParBloc = false, candidatKey = "numero"}) {
|
||||||
const sousZoneInfo = resultatsZone.zone
|
const sousZoneInfo = resultatsZone.zone
|
||||||
const donnees = resultatsZone ? (tour === 1 ? resultatsZone.tour1 : resultatsZone.tour2) : {}
|
const donnees = useMemo(() => {
|
||||||
|
return resultatsZone ? (tour === 1 ? resultatsZone.tour1 : resultatsZone.tour2) : {}
|
||||||
|
}, [resultatsZone, tour])
|
||||||
|
|
||||||
const [idZone, nomZone] = useMemo(() => {
|
const [idZone, nomZone] = useMemo(() => {
|
||||||
if (!sousZoneInfo)
|
if (!sousZoneInfo)
|
||||||
@ -262,10 +258,23 @@ function ZoneGeoJSON({typeElection, anneeElection, resultatsZone, typeSousZone,
|
|||||||
return ["", ""]
|
return ["", ""]
|
||||||
}, [typeSousZone, sousZoneInfo])
|
}, [typeSousZone, sousZoneInfo])
|
||||||
|
|
||||||
const voixCandidats = useMemo(() => donnees?.voix ?? {}, [resultatsZone])
|
const [candidatsZone, setCandidatsZone] = useState(candidats)
|
||||||
const candidatsTries = trierCandidats(candidats, voixCandidats)
|
useEffect(() => {
|
||||||
|
if (typeElection === "legislatives" && (typeSousZone === "circonscription" || typeSousZone === "bureau_vote") && sousZoneInfo.id) {
|
||||||
|
const circo_id = typeSousZone === "circonscription" ? sousZoneInfo.id : sousZoneInfo.circonscription
|
||||||
|
fetch(`/data/resultats/${typeElection}/${anneeElection}/candidats/${circo_id}.json`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => setCandidatsZone(data))
|
||||||
|
}
|
||||||
|
}, [typeElection, anneeElection, typeSousZone, sousZoneInfo])
|
||||||
|
|
||||||
const [voixParBloc, voixParNuance] = regrouperVoix(voixCandidats, candidats, blocs, nuances)
|
const voixCandidats = useMemo(() => donnees?.voix ?? {}, [donnees])
|
||||||
|
const candidatsTries = trierCandidats(candidatsZone, voixCandidats, candidatKey)
|
||||||
|
|
||||||
|
const dejaGroupesParNuance = typeElection === "legislatives"
|
||||||
|
&& (typeSousZone !== "circonscription" && typeSousZone !== "bureau_vote")
|
||||||
|
const [voixParBloc, voixParNuance] = regrouperVoix(voixCandidats, candidatsZone, blocs, nuances,
|
||||||
|
dejaGroupesParNuance)
|
||||||
|
|
||||||
let couleur = 'grey'
|
let couleur = 'grey'
|
||||||
if (grouperParBloc) {
|
if (grouperParBloc) {
|
||||||
@ -294,8 +303,8 @@ function ZoneGeoJSON({typeElection, anneeElection, resultatsZone, typeSousZone,
|
|||||||
<strong><a href={`/elections/${typeElection}/${anneeElection}/${typeSousZone}/${idZone}/`}>{nomZone}</a></strong>
|
<strong><a href={`/elections/${typeElection}/${anneeElection}/${typeSousZone}/${idZone}/`}>{nomZone}</a></strong>
|
||||||
<ul>
|
<ul>
|
||||||
{candidatsTries.slice(0, 5).map(candidat =>
|
{candidatsTries.slice(0, 5).map(candidat =>
|
||||||
<li key={candidat.numero}>
|
<li key={candidat[candidatKey]}>
|
||||||
{candidat.nom} : {voixCandidats[candidat.numero]} ({(100 * voixCandidats[candidat.numero] / donnees.exprimes).toFixed(2)} %)
|
{candidat.nom} : {voixCandidats[candidat[candidatKey]]} ({(100 * voixCandidats[candidat[candidatKey]] / donnees.exprimes).toFixed(2)} %)
|
||||||
</li>)}
|
</li>)}
|
||||||
</ul>
|
</ul>
|
||||||
</Popup>
|
</Popup>
|
||||||
@ -303,7 +312,7 @@ function ZoneGeoJSON({typeElection, anneeElection, resultatsZone, typeSousZone,
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ContenuCarte({typeElection, anneeElection, zoneInfo, typeSousZone, candidats, blocs, nuances, tour,
|
function ContenuCarte({typeElection, anneeElection, zoneInfo, typeSousZone, candidats, blocs, nuances, tour,
|
||||||
grouperParBloc = false}) {
|
grouperParBloc = false, candidatKey = "numero"}) {
|
||||||
const map = useMap()
|
const map = useMap()
|
||||||
const [resultatsZones, setResultatsZones] = useState([])
|
const [resultatsZones, setResultatsZones] = useState([])
|
||||||
|
|
||||||
@ -366,15 +375,15 @@ function ContenuCarte({typeElection, anneeElection, zoneInfo, typeSousZone, cand
|
|||||||
return <>
|
return <>
|
||||||
{resultatsZones.filter(resultatsZone => resultatsZone.zone.geometry['type'])
|
{resultatsZones.filter(resultatsZone => resultatsZone.zone.geometry['type'])
|
||||||
.map(resultatsZone =>
|
.map(resultatsZone =>
|
||||||
<ZoneGeoJSON key={getZoneIdentifier(resultatsZone.zone)}
|
<ZoneGeoJSON key={getZoneIdentifier(typeSousZone, resultatsZone.zone)}
|
||||||
typeElection={typeElection} anneeElection={anneeElection}
|
typeElection={typeElection} anneeElection={anneeElection}
|
||||||
resultatsZone={resultatsZone} typeSousZone={typeSousZone} candidats={candidats}
|
resultatsZone={resultatsZone} typeSousZone={typeSousZone} candidats={candidats}
|
||||||
blocs={blocs} nuances={nuances} tour={tour} grouperParBloc={grouperParBloc}/>)}
|
blocs={blocs} nuances={nuances} tour={tour} grouperParBloc={grouperParBloc} candidatKey={candidatKey} />)}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CarteResultats({typeElection, anneeElection, typeResultats, zoneInfo, typeSousZone, candidats,
|
export function CarteResultats({typeElection, anneeElection, typeResultats, zoneInfo, typeSousZone, candidats,
|
||||||
blocs, nuances, tour, grouperParBloc = false}) {
|
blocs, nuances, tour, grouperParBloc = false, candidatKey = "numero"}) {
|
||||||
const center = typeResultats === "france" ? [46.603354, 1.888334] : [0, 0]
|
const center = typeResultats === "france" ? [46.603354, 1.888334] : [0, 0]
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
@ -385,7 +394,7 @@ export function CarteResultats({typeElection, anneeElection, typeResultats, zone
|
|||||||
/>
|
/>
|
||||||
<ContenuCarte typeElection={typeElection} anneeElection={anneeElection}
|
<ContenuCarte typeElection={typeElection} anneeElection={anneeElection}
|
||||||
zoneInfo={zoneInfo} typeSousZone={typeSousZone} candidats={candidats}
|
zoneInfo={zoneInfo} typeSousZone={typeSousZone} candidats={candidats}
|
||||||
blocs={blocs} nuances={nuances} tour={tour} grouperParBloc={grouperParBloc} />
|
blocs={blocs} nuances={nuances} tour={tour} grouperParBloc={grouperParBloc} candidatKey={candidatKey} />
|
||||||
</MapContainer>
|
</MapContainer>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,103 @@
|
|||||||
|
import {trierCandidats} from "../utils"
|
||||||
|
import TableContainer from "@mui/material/TableContainer"
|
||||||
|
import Paper from "@mui/material/Paper"
|
||||||
|
import Table from "@mui/material/Table"
|
||||||
|
import TableHead from "@mui/material/TableHead"
|
||||||
|
import TableRow from "@mui/material/TableRow"
|
||||||
|
import TableCell from "@mui/material/TableCell"
|
||||||
|
import TableBody from "@mui/material/TableBody"
|
||||||
|
|
||||||
|
export function TableauResultatsCandidatsLegislatives({blocs, candidats, nuances, donnees}) {
|
||||||
|
const voixCandidats = donnees?.voix ?? {}
|
||||||
|
const candidatsTriees = trierCandidats(candidats, voixCandidats)
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Numéro</TableCell>
|
||||||
|
<TableCell>Candidat</TableCell>
|
||||||
|
<TableCell colSpan={2}>Nuance</TableCell>
|
||||||
|
<TableCell colSpan={2}>Bloc</TableCell>
|
||||||
|
<TableCell>Voix</TableCell>
|
||||||
|
<TableCell>% Inscrit⋅es</TableCell>
|
||||||
|
<TableCell>% Exprimé⋅es</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{candidatsTriees.map((candidat) => (
|
||||||
|
<LigneCandidat key={candidat.numero} candidat={candidat} voix={voixCandidats[candidat.numero] || 0}
|
||||||
|
donnees={donnees} nuances={nuances} blocs={blocs} />
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
function LigneCandidat({candidat, voix, donnees, nuances, blocs}) {
|
||||||
|
const nuance = nuances.filter(nuance => nuance.code === candidat.nuance)[0]
|
||||||
|
const bloc = blocs.filter(bloc => bloc.nom === candidat.bloc)[0]
|
||||||
|
|
||||||
|
return <TableRow key={candidat.numero}>
|
||||||
|
<TableCell>{candidat.numero}</TableCell>
|
||||||
|
<TableCell>{candidat.prenom} {candidat.nom}</TableCell>
|
||||||
|
<TableCell sx={{backgroundColor: nuance.couleur, padding: "0.2em"}}></TableCell>
|
||||||
|
<TableCell>{nuance.nom} ({nuance.code})</TableCell>
|
||||||
|
<TableCell sx={{backgroundColor: bloc.couleur, padding: "0.2em"}}></TableCell>
|
||||||
|
<TableCell>{bloc.nom}</TableCell>
|
||||||
|
<TableCell>{voix}</TableCell>
|
||||||
|
<TableCell>{(100 * voix / donnees.inscrits).toFixed(2)} %</TableCell>
|
||||||
|
<TableCell>{(100 * voix / donnees.exprimes).toFixed(2)} %</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composant pour le tableau des résultats des élections législatives
|
||||||
|
* @param blocs
|
||||||
|
* @param nuances
|
||||||
|
* @param donnees
|
||||||
|
* @return {JSX.Element}
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
export function TableauResultatsNuancesLegislatives({blocs, nuances, donnees}) {
|
||||||
|
const voixNuances = donnees?.voix ?? {}
|
||||||
|
const nuancesTriees = trierCandidats(nuances, voixNuances, "code")
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={2}>Nuance</TableCell>
|
||||||
|
<TableCell colSpan={2}>Bloc</TableCell>
|
||||||
|
<TableCell>Voix</TableCell>
|
||||||
|
<TableCell>% Inscrit⋅es</TableCell>
|
||||||
|
<TableCell>% Exprimé⋅es</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{nuancesTriees.map((nuance) => (
|
||||||
|
<LigneNuance key={nuance.code} nuance={nuance} voix={voixNuances[nuance.code] || 0}
|
||||||
|
donnees={donnees} blocs={blocs} />
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
function LigneNuance({nuance, voix, donnees, blocs}) {
|
||||||
|
const bloc = blocs.filter(bloc => bloc.nom === nuance.bloc)[0]
|
||||||
|
|
||||||
|
return <TableRow key={nuance.code}>
|
||||||
|
<TableCell sx={{backgroundColor: nuance.couleur, padding: "0.2em"}}></TableCell>
|
||||||
|
<TableCell>{nuance.nom} ({nuance.code})</TableCell>
|
||||||
|
<TableCell sx={{backgroundColor: bloc.couleur, padding: "0.2em"}}></TableCell>
|
||||||
|
<TableCell>{bloc.nom}</TableCell>
|
||||||
|
<TableCell>{voix}</TableCell>
|
||||||
|
<TableCell>{(100 * voix / donnees.inscrits).toFixed(2)} %</TableCell>
|
||||||
|
<TableCell>{(100 * voix / donnees.exprimes).toFixed(2)} %</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
export function getNomZone(typeResultats, zoneInfo) {
|
export function getNomZone(typeResultats, zoneInfo) {
|
||||||
if (!zoneInfo)
|
if (!zoneInfo.type)
|
||||||
return ""
|
return ""
|
||||||
else if (typeResultats === "france")
|
else if (typeResultats === "france")
|
||||||
return "France"
|
return "France"
|
||||||
@ -15,30 +15,36 @@ export function getNomZone(typeResultats, zoneInfo) {
|
|||||||
return zoneInfo.libelle
|
return zoneInfo.libelle
|
||||||
}
|
}
|
||||||
|
|
||||||
export function trierCandidats(candidats, voix_par_candidat) {
|
export function trierCandidats(candidats, voix_par_candidat, key = "numero") {
|
||||||
return candidats.toSorted((l1, l2) => {
|
return candidats.toSorted((l1, l2) => {
|
||||||
return (voix_par_candidat[l2.numero] || 0) - (voix_par_candidat[l1.numero] || 0)
|
return (voix_par_candidat[l2[key]] || 0) - (voix_par_candidat[l1[key]] || 0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function regrouperVoix(voixCandidats, candidats, blocs, nuances) {
|
export function regrouperVoix(voixCandidats, candidats, blocs, nuances, dejaGroupesParNuance = false) {
|
||||||
if (!candidats || !voixCandidats || !blocs || !nuances
|
if (!candidats || !voixCandidats || !blocs || !nuances
|
||||||
|| candidats.length === 0 || blocs.length === 0 || nuances.length === 0)
|
|| candidats.length === 0 || blocs.length === 0 || nuances.length === 0)
|
||||||
return [{}, {}]
|
return [{}, {}]
|
||||||
|
|
||||||
|
const key = dejaGroupesParNuance ? "code" : "numero"
|
||||||
|
|
||||||
const parBloc = {}
|
const parBloc = {}
|
||||||
const parNuance = {}
|
const parNuance = dejaGroupesParNuance ? voixCandidats : {}
|
||||||
|
|
||||||
for (let bloc of blocs) {
|
for (let bloc of blocs) {
|
||||||
parBloc[bloc.nom] = 0
|
parBloc[bloc.nom] = 0
|
||||||
}
|
}
|
||||||
for (let nuance of nuances) {
|
|
||||||
parNuance[nuance.code] = 0
|
if (!dejaGroupesParNuance) {
|
||||||
|
for (let nuance of nuances) {
|
||||||
|
parNuance[nuance.code] = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let candidat of candidats) {
|
for (let candidat of candidats) {
|
||||||
parBloc[candidat.bloc] += voixCandidats[candidat.numero] || 0
|
parBloc[candidat.bloc] += voixCandidats[candidat[key]] || 0
|
||||||
parNuance[candidat.nuance] += voixCandidats[candidat.numero] || 0
|
if (!dejaGroupesParNuance)
|
||||||
|
parNuance[candidat.nuance] += voixCandidats[candidat[key]] || 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return [parBloc, parNuance]
|
return [parBloc, parNuance]
|
||||||
|
@ -31,7 +31,12 @@ def exporter_nuances(engine: Engine, verbose: bool = False) -> None:
|
|||||||
nuances_json = []
|
nuances_json = []
|
||||||
|
|
||||||
for nuance in nuances:
|
for nuance in nuances:
|
||||||
nuance_json = {'code': nuance.code, 'nom': nuance.nom, 'couleur': nuance.couleur, "bloc": nuance.bloc_id}
|
nuance_json = {
|
||||||
|
'code': nuance.code,
|
||||||
|
'nom': nuance.nom,
|
||||||
|
'couleur': nuance.couleur,
|
||||||
|
"bloc": nuance.bloc.nom,
|
||||||
|
}
|
||||||
nuances_json.append(nuance_json)
|
nuances_json.append(nuance_json)
|
||||||
|
|
||||||
file = DATA_DIR / "resultats" / "legislatives" / "2022" / "nuances.json"
|
file = DATA_DIR / "resultats" / "legislatives" / "2022" / "nuances.json"
|
||||||
@ -54,6 +59,7 @@ def exporter_candidats(engine: Engine, verbose: bool = False) -> None:
|
|||||||
candidat_json = {
|
candidat_json = {
|
||||||
'numero': candidat.numero,
|
'numero': candidat.numero,
|
||||||
'nuance': candidat.nuance_id,
|
'nuance': candidat.nuance_id,
|
||||||
|
'bloc': candidat.nuance.bloc.nom,
|
||||||
'nom': candidat.nom,
|
'nom': candidat.nom,
|
||||||
'prenom': candidat.prenom,
|
'prenom': candidat.prenom,
|
||||||
'nom_suppleance': candidat.nom_suppleance,
|
'nom_suppleance': candidat.nom_suppleance,
|
||||||
@ -316,8 +322,8 @@ def exporter_resultats_circonscriptions(engine: Engine, verbose: bool = False) -
|
|||||||
resultats_dict['tour1']['voix'] = resultats_t1
|
resultats_dict['tour1']['voix'] = resultats_t1
|
||||||
resultats_dict['tour2']['voix'] = resultats_t2
|
resultats_dict['tour2']['voix'] = resultats_t2
|
||||||
for voix_candidat in resultats_circonscription.voix:
|
for voix_candidat in resultats_circonscription.voix:
|
||||||
resultats_t1[voix_candidat.candidat.id] = voix_candidat.voix_t1
|
resultats_t1[voix_candidat.candidat.numero] = voix_candidat.voix_t1
|
||||||
resultats_t2[voix_candidat.candidat.id] = voix_candidat.voix_t2
|
resultats_t2[voix_candidat.candidat.numero] = voix_candidat.voix_t2
|
||||||
|
|
||||||
file = DATA_DIR / "resultats" / "legislatives" / "2022" / "circonscription" / f"{circonscription.id}.json"
|
file = DATA_DIR / "resultats" / "legislatives" / "2022" / "circonscription" / f"{circonscription.id}.json"
|
||||||
if not file.parent.is_dir():
|
if not file.parent.is_dir():
|
||||||
@ -457,8 +463,8 @@ def exporter_resultats_bureaux_vote(engine: Engine, verbose: bool = False) -> No
|
|||||||
resultats_dict['tour1']['voix'] = resultats_t1
|
resultats_dict['tour1']['voix'] = resultats_t1
|
||||||
resultats_dict['tour2']['voix'] = resultats_t2
|
resultats_dict['tour2']['voix'] = resultats_t2
|
||||||
for voix_candidat in resultats_bureau_vote.voix:
|
for voix_candidat in resultats_bureau_vote.voix:
|
||||||
resultats_t1[voix_candidat.candidat.id] = voix_candidat.voix_t1
|
resultats_t1[voix_candidat.candidat.numero] = voix_candidat.voix_t1
|
||||||
resultats_t2[voix_candidat.candidat.id] = voix_candidat.voix_t2
|
resultats_t2[voix_candidat.candidat.numero] = voix_candidat.voix_t2
|
||||||
|
|
||||||
file = DATA_DIR / "resultats" / "legislatives" / "2022" / "bureau_vote" / f"{bureau_vote.id}.json"
|
file = DATA_DIR / "resultats" / "legislatives" / "2022" / "bureau_vote" / f"{bureau_vote.id}.json"
|
||||||
if not file.parent.is_dir():
|
if not file.parent.is_dir():
|
||||||
|
@ -33,7 +33,7 @@ def creer_blocs(engine: Engine, verbose: bool = False) -> None:
|
|||||||
def creer_nuances(engine: Engine, verbose: bool = False) -> None:
|
def creer_nuances(engine: Engine, verbose: bool = False) -> None:
|
||||||
nuances = [
|
nuances = [
|
||||||
{"code": "DXG", "nom": "Divers extrême gauche", "couleur": "#BB0000", "bloc_id": 1},
|
{"code": "DXG", "nom": "Divers extrême gauche", "couleur": "#BB0000", "bloc_id": 1},
|
||||||
{"code": "RDG", "nom": "Radical de gauche", "couleur": "#FFD1DC", "bloc_id": 1},
|
{"code": "RDG", "nom": "Parti radical de gauche", "couleur": "#FFD1DC", "bloc_id": 1},
|
||||||
{"code": "NUP", "nom": "Nouvelle union populaire écologique et sociale", "couleur": "#E4032E", "bloc_id": 1},
|
{"code": "NUP", "nom": "Nouvelle union populaire écologique et sociale", "couleur": "#E4032E", "bloc_id": 1},
|
||||||
{"code": "DVG", "nom": "Divers gauche", "couleur": "#FFC0C0", "bloc_id": 1},
|
{"code": "DVG", "nom": "Divers gauche", "couleur": "#FFC0C0", "bloc_id": 1},
|
||||||
{"code": "ECO", "nom": "Écologistes", "couleur": "#77FF77", "bloc_id": 5},
|
{"code": "ECO", "nom": "Écologistes", "couleur": "#77FF77", "bloc_id": 5},
|
||||||
|
Loading…
Reference in New Issue
Block a user