import MaterialIcon from "@mui/material/Icon"; import * as d3 from "d3"; import { useEffect, useRef } from "react"; import { colorScheme, config } from "../config"; import { CategoryMetadata } from "../lib/metadata"; import "./Chart.css"; interface QuestionGroupChartProps { question: string; metadata?: CategoryMetadata; groupData: { response: string }[]; responses: string[]; xScale: d3.ScaleBand; } function makeDot( g: d3.Selection, dotX: number, dotY: number ) { const shape = config.dotShape; if (shape === "circle") { return g .append("circle") .attr("class", "dot") .attr("cx", dotX) .attr("cy", dotY) .attr("r", config.dotRadius); } else if (shape === "rect") { return g .append("rect") .attr("class", "dot") .attr("x", dotX - config.dotRadius) .attr("y", dotY - config.dotRadius) .attr("width", config.dotRadius * 2) .attr("height", config.dotRadius * 2); } throw new Error(`Unsupported shape: ${shape}`); } export function QuestionGroupChart({ question, metadata, 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 chartHeight = config.chartHeight; const chartWidth = xScale.range()[1]; const svg = d3 .select(svgRef.current) .attr("width", chartWidth) .attr("height", chartHeight); const g = svg.append("g"); // 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 - (row + 1) * (config.dotRadius * 2 + config.dotSpacing); makeDot(g, dotX, dotY).attr("fill", colorScheme[response] || "#666"); }); }); }, [groupData, responses, xScale, question]); return (
{metadata?.icon && {metadata.icon}} {question}

{metadata?.description || question}

); } export default QuestionGroupChart;