Migrate to React

This commit is contained in:
Adrian Rumpold
2025-07-09 06:51:16 +02:00
parent 50d2fa8bfe
commit 5dc583e387
23 changed files with 4791 additions and 341 deletions

View File

@@ -0,0 +1,95 @@
import * as d3 from "d3";
import { useEffect, useRef } from "react";
import { colorScheme, config } from "../config";
interface QuestionGroupChartProps {
question: string;
groupData: { response: string }[];
responses: string[];
xScale: d3.ScaleBand<string>;
}
export function QuestionGroupChart({
question,
groupData,
responses,
xScale,
}: QuestionGroupChartProps) {
const svgRef = useRef(null);
useEffect(() => {
// Clear SVG
d3.select(svgRef.current).selectAll("*").remove();
// Group responses by category (within this group only)
const responseGroups = d3.group(groupData, (d) => d.response);
const maxCount =
d3.max(Array.from(responseGroups.values(), (values) => values.length)) ||
0;
const maxRows = Math.ceil(maxCount / config.columnsPerGroup);
const chartHeight =
maxRows * (config.dotRadius * 2 + config.dotSpacing) +
config.margin.bottom;
const chartWidth =
xScale.range()[1] + config.margin.left + config.margin.right;
const svg = d3
.select(svgRef.current)
.attr("width", chartWidth)
.attr("height", chartHeight);
const g = svg
.append("g")
.attr(
"transform",
`translate(${config.margin.left},${config.margin.top})`
);
// Dots
responses.forEach((response) => {
const responseData = responseGroups.get(response) || [];
const x = xScale(response) || 0;
responseData.forEach((_, index) => {
const row = Math.floor(index / config.columnsPerGroup);
const col = index % config.columnsPerGroup;
const dotX =
x +
xScale.bandwidth() / 2 +
(col - (config.columnsPerGroup - 1) / 2) *
(config.dotRadius * 2 + config.dotSpacing);
const dotY =
chartHeight -
config.margin.top -
config.margin.bottom -
(row + 1) * (config.dotRadius * 2 + config.dotSpacing);
g.append("circle")
.attr("class", "dot")
.attr("cx", dotX)
.attr("cy", dotY)
.attr("r", config.dotRadius)
.attr("fill", colorScheme[response] || "#666");
});
});
}, [groupData, responses, xScale, question]);
/*
// Calculate height for container
const responseGroups = d3.group(groupData, (d) => d.response);
const maxCount =
d3.max(Array.from(responseGroups.values(), (values) => values.length)) || 0;
const maxRows = Math.ceil(maxCount / config.columnsPerGroup);
const chartHeight =
maxRows * (config.dotRadius * 2 + config.dotSpacing) +
config.margin.top +
config.margin.bottom;
*/
return (
<div className="question-group">
<div className="question-title">{question}</div>
<svg ref={svgRef}></svg>
</div>
);
}
export default QuestionGroupChart;