Skip to content

Commit

Permalink
county level data viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
lukedigiovanna committed Sep 14, 2024
1 parent 46c3021 commit 014b6e1
Show file tree
Hide file tree
Showing 10 changed files with 1,785 additions and 1,789 deletions.
3,506 changes: 1,737 additions & 1,769 deletions frontend/pnpm-lock.yaml

Large diffs are not rendered by default.

39 changes: 31 additions & 8 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,34 @@ function App() {
const [colorMode, setColorMode] = React.useState<ColorMode>("gradient");
const [year, setYear] = React.useState<number>(2020);

const keyPress = (event: KeyboardEvent) => {
if (event.key === "ArrowLeft") {
setYear(Math.max(2000, year - 4));
}
else if (event.key === "ArrowRight") {
setYear(Math.min(2020, year + 4));
}
}

React.useEffect(() => {
window.addEventListener('keydown', keyPress);

return () => {
window.removeEventListener('keydown', keyPress);
};
}, [year]); // Empty dependency array ensures this effect runs only once

const colorFunction = React.useMemo(() => {
console.log("recompute color function");
return (d: any) => {
const stateFP = stateNameToFP(d.properties.name as string);
const electionData = (electionResults as any)[year]["results"][stateFP];
const fp = countryView === "state" ? stateNameToFP(d.properties.name as string) : d.properties.STATEFP + d.properties.COUNTYFP;
const results = (electionResults as any)[year]["results"];

if (!Object.hasOwn(results, fp)) {
return colors.parties.other;
}

const electionData = results[fp];
const parties = Object.keys(electionData);
parties.sort((party1, party2) => {
return electionData[party2] - electionData[party1]
Expand All @@ -57,18 +80,18 @@ function App() {
return colormap(r);
}
}
}, [year, colorMode]);
}, [year, colorMode, countryView]);

const tooltipFunction = React.useMemo(() => {
return (d: any) => {
const div = document.createElement("div");
div.className = "state-results";
const title = document.createElement("h1");
title.innerText = d.properties.name;
title.innerText = countryView === "state" ? d.properties.name : d.properties.NAME;
div.appendChild(title);
const stateFP = stateNameToFP(d.properties.name as string);
const fp = countryView === "state" ? stateNameToFP(d.properties.name as string) : d.properties.STATEFP + d.properties.COUNTYFP;
const electionData = (electionResults as any)[year]
const stateData = electionData["results"][stateFP];
const stateData = electionData["results"][fp];
const candidates = electionData["candidates"];
const parties = Object.keys(stateData);
parties.sort((party1, party2) => {
Expand Down Expand Up @@ -106,7 +129,7 @@ function App() {
}
return div.outerHTML;
}
}, [year]);
}, [year, countryView]);

return (
<div className="flex flex-col items-center p-4 max-w-5xl mx-auto">
Expand Down Expand Up @@ -171,7 +194,7 @@ function App() {
</div>
{
countryView === "county" ?
<CountyGeoJsonMap countiesGeoJson={usCountiesGeoJson} statesGeoJson={usStatesGeoJson} />
<CountyGeoJsonMap countiesGeoJson={usCountiesGeoJson} statesGeoJson={usStatesGeoJson} colorFunction={colorFunction} tooltipFunction={tooltipFunction} />
:
<StateGeoJsonMap statesGeoJson={usStatesGeoJson} colorFunction={colorFunction} tooltipFunction={tooltipFunction}/>
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/assets/2000_state_election_results.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/src/assets/2004_state_election_results.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/src/assets/2008_state_election_results.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/src/assets/2012_state_election_results.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/src/assets/2016_state_election_results.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/src/assets/2020_state_election_results.json

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions frontend/src/components/CountyGeoJsonMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { FeatureCollection } from "geojson";
interface CountyGeoJsonMapProps {
countiesGeoJson: FeatureCollection; // GeoJSON for counties
statesGeoJson: FeatureCollection; // GeoJSON for state boundaries
colorFunction: (d: any) => string;
tooltipFunction: (d: any) => string; // HTML string
}

const CountyGeoJsonMap: React.FC<CountyGeoJsonMapProps> = ({ countiesGeoJson, statesGeoJson }) => {
const CountyGeoJsonMap: React.FC<CountyGeoJsonMapProps> = ({ countiesGeoJson, statesGeoJson, colorFunction, tooltipFunction }) => {
const svgRef = useRef<SVGSVGElement | null>(null);
const tooltipRef = useRef<HTMLDivElement | null>(null); // Tooltip reference

Expand Down Expand Up @@ -48,15 +50,15 @@ const CountyGeoJsonMap: React.FC<CountyGeoJsonMapProps> = ({ countiesGeoJson, st
.append("path")
.attr("class", "county")
.attr("d", pathGenerator as any) // Path generator's d attribute
.attr("fill", "#877eda")
.attr("fill", colorFunction)
.attr("stroke", "#000")
.attr("stroke-width", 1) // Thin stroke for county borders
.on("mouseover", function (event, d) {
.on("mouseover", function (event: any, d: any) {
// Show the tooltip on hover
tooltip.style("visibility", "visible")
.text(d.properties?.NAME); // Assuming the county name is in the "NAME" property
.html(tooltipFunction(d)); // Assuming the county name is in the "NAME" property
})
.on("mousemove", function (event) {
.on("mousemove", function (event: any) {
// Position the tooltip near the mouse cursor
tooltip.style("top", (event.pageY - 10) + "px")
.style("left", (event.pageX + 10) + "px");
Expand All @@ -77,7 +79,7 @@ const CountyGeoJsonMap: React.FC<CountyGeoJsonMapProps> = ({ countiesGeoJson, st
.attr("stroke", "#000") // Black stroke for state borders
.attr("stroke-width", 3); // Thicker stroke for state borders
}
}, [countiesGeoJson, statesGeoJson]);
}, [countiesGeoJson, statesGeoJson, colorFunction, tooltipFunction]);

return (
<div className="">
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/constants/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ const fpTable = {
}

function stateNameToFP(name: string) {
if (!name) {
return name;
}
const up = name.toUpperCase();
if (Object.hasOwn(fpTable, up)) {
return (fpTable as any)[up];
Expand Down

0 comments on commit 014b6e1

Please sign in to comment.