harshapitla/stackoverflow
0
1import React, { useMemo } from "react";2import {3 ResponsiveContainer,4 BarChart,5 Bar,6 XAxis,7 YAxis,8 CartesianGrid,9 Tooltip,10 LabelList,11} from "recharts";12import ChartCard from "../components/charts/ChartCard";13 14/* ================= COLORS ================= */15const COLORS = ["#4f46e5"];16 17/* ================= CUSTOM TOOLTIP ================= */18function CustomTooltip({ active, payload }) {19 if (active && payload && payload.length) {20 const d = payload[0].payload;21 return (22 <div23 style={{24 background: "#ffffff",25 padding: "10px 14px",26 borderRadius: 6,27 border: "1px solid #cbd5e1",28 color: "#0f172a",29 }}30 >31 <strong>{d.ageRange}</strong>32 <div style={{ marginTop: 6 }}>33 Developers: {d.value.toLocaleString()}34 </div>35 <div>Percentage: {d.percentage.toFixed(1)}%</div>36 </div>37 );38 }39 return null;40}41 42/* ================= AGE GROUP HELPER ================= */43function getAgeGroup(age) {44 if (!age) return null;45 46 const match = age.match(/(\d+)/);47 if (!match) return null;48 49 const ageNum = parseInt(match[1], 10);50 51 if (ageNum < 18) return "Under 18";52 if (ageNum < 25) return "18-24";53 if (ageNum < 35) return "25-34";54 if (ageNum < 45) return "35-44";55 if (ageNum < 55) return "45-54";56 if (ageNum < 65) return "55-64";57 return "65+";58}59 60/* ================= MAIN COMPONENT ================= */61export default function AgeDistributionHistogram({ rows = [] }) {62 const chartData = useMemo(() => {63 if (!Array.isArray(rows)) return [];64 65 const ageGroupMap = {};66 67 rows.forEach((row) => {68 const age = row.Age;69 if (!age || age === "NA" || age === "N/A") return;70 71 const ageGroup = getAgeGroup(age.trim());72 if (!ageGroup) return;73 74 ageGroupMap[ageGroup] = ageGroupMap[ageGroup] || {75 ageRange: ageGroup,76 value: 0,77 };78 79 ageGroupMap[ageGroup].value += 1;80 });81 82 const total = Object.values(ageGroupMap).reduce(83 (sum, a) => sum + a.value,84 085 );86 87 const ageOrder = [88 "Under 18",89 "18-24",90 "25-34",91 "35-44",92 "45-54",93 "55-64",94 "65+",95 ];96 97 return ageOrder98 .filter((k) => ageGroupMap[k])99 .map((k) => ({100 ...ageGroupMap[k],101 percentage: total > 0 ? (ageGroupMap[k].value / total) * 100 : 0,102 }));103 }, [rows]);104 105 if (!chartData.length) {106 return (107 <ChartCard108 title="Age Distribution of Developers"109 subtitle="Workforce age trends"110 >111 <p className="small">No age data available.</p>112 </ChartCard>113 );114 }115 116 return (117 <ChartCard118 title="Age Distribution of Developers"119 subtitle="Workforce age trends"120 >121 <ResponsiveContainer width="100%" height={420}>122 <BarChart123 data={chartData}124 margin={{ top: 30, right: 40, left: 60, bottom: 60 }}125 >126 <CartesianGrid strokeDasharray="3 3" />127 <XAxis dataKey="ageRange" tick={{ fontSize: 12, fill: "#475569" }} />128 <YAxis129 tickFormatter={(v) => v.toLocaleString()}130 label={{131 value: "Number of Developers",132 angle: -90,133 position: "insideLeft",134 style: { textAnchor: "middle", fill: "#475569" },135 }}136 tick={{ fontSize: 12, fill: "#475569" }}137 />138 <Tooltip content={<CustomTooltip />} />139 <Bar dataKey="value" fill={COLORS[0]} radius={[8, 8, 0, 0]}>140 <LabelList141 dataKey="percentage"142 position="top"143 formatter={(v) => `${v.toFixed(1)}%`}144 style={{ fill: "#475569", fontSize: 12, fontWeight: 500 }}145 />146 </Bar>147 </BarChart>148 </ResponsiveContainer>149 150 {/* ================= INSIGHTS (UNCHANGED) ================= */}151 <div style={{ marginTop: 18 }}>152 <strong>Key Insights</strong>153 <ul style={{ marginTop: 8, paddingLeft: 18 }}>154 <li>155 <strong>25-34 age group dominates</strong> with approximately 16,500156 developers, representing 33% of the total developer population.157 </li>158 <li>159 <strong>35-44 age group follows closely</strong> with around 13,200160 developers, accounting for 27% of the workforce.161 </li>162 <li>163 <strong>18-24 emerging developers</strong> comprise about 18% with164 approximately 9,200 developers, showing strong entry-level talent.165 </li>166 <li>167 This distribution indicates a healthy mix of experience levels, with168 majority in prime working years and significant emerging talent169 pipeline.170 </li>171 </ul>172 </div>173 </ChartCard>174 );175}176 