harshapitla/stackoverflow
0
1import React, { useMemo } from "react";2import {3 ResponsiveContainer,4 BarChart,5 Bar,6 XAxis,7 YAxis,8 CartesianGrid,9 Tooltip,10 Legend,11} from "recharts";12import ChartCard from "../components/charts/ChartCard";13 14/* ================= COLORS ================= */15const COLORS = {16 Remote: "#4f46e5",17 Hybrid: "#22c55e",18 "In-person": "#f97316",19};20 21/* ================= ORDER HELPER ================= */22const ORG_ORDER = [23 "Just me - I am a freelancer, sole proprietor, etc.",24 "2 to 9 employees",25 "10 to 19 employees",26 "20 to 99 employees",27 "100 to 499 employees",28 "500 to 999 employees",29 "1,000 to 4,999 employees",30 "5,000 to 9,999 employees",31 "10,000 or more employees",32 "I don’t know",33];34 35function simplifyLabel(label) {36 if (label.includes("Just me")) return "Freelancer";37 if (label.includes("10,000")) return "10k+";38 return label.replace(" employees", "");39}40 41/* ================= MAIN COMPONENT ================= */42export default function OrgSizeVsRemoteWorkChart({ rows = [] }) {43 const chartData = useMemo(() => {44 if (!Array.isArray(rows)) return [];45 46 const map = {};47 48 rows.forEach((row) => {49 const size = row.OrgSize;50 const remote = row.RemoteWork;51 52 if (!size || size === "NA" || !remote || remote === "NA") return;53 54 if (!map[size]) {55 map[size] = {56 size,57 simpleLabel: simplifyLabel(size),58 Remote: 0,59 Hybrid: 0,60 "In-person": 0,61 total: 0,62 };63 }64 65 if (remote.includes("Remote")) map[size].Remote += 1;66 else if (remote.includes("Hybrid")) map[size].Hybrid += 1;67 else if (remote.includes("person")) map[size]["In-person"] += 1;68 69 map[size].total += 1;70 });71 72 // Convert counts to percentages for better comparison across sizes73 return ORG_ORDER.map((size) => {74 const d = map[size];75 if (!d || d.total === 0) return null;76 return {77 name: d.simpleLabel,78 Remote: (d.Remote / d.total) * 100,79 Hybrid: (d.Hybrid / d.total) * 100,80 "In-person": (d["In-person"] / d.total) * 100,81 totalCount: d.total,82 };83 }).filter(Boolean);84 }, [rows]);85 86 if (!chartData.length) {87 return (88 <ChartCard89 title="Organization Size vs Remote Work"90 subtitle="Flexibility by company scale"91 >92 <p className="small">No data available.</p>93 </ChartCard>94 );95 }96 97 return (98 <ChartCard99 title="Organization Size vs Remote Work"100 subtitle="Flexibility by company scale (Percentage)"101 >102 <ResponsiveContainer width="100%" height={450}>103 <BarChart104 data={chartData}105 layout="vertical"106 margin={{ top: 20, right: 30, left: 100, bottom: 20 }}107 >108 <CartesianGrid strokeDasharray="3 3" />109 <XAxis type="number" unit="%" />110 <YAxis111 type="category"112 dataKey="name"113 width={100}114 tick={{ fontSize: 11 }}115 />116 <Tooltip117 formatter={(value, name, props) => [`${value.toFixed(1)}%`, name]}118 />119 <Legend />120 <Bar dataKey="Remote" stackId="a" fill={COLORS.Remote} />121 <Bar dataKey="Hybrid" stackId="a" fill={COLORS.Hybrid} />122 <Bar dataKey="In-person" stackId="a" fill={COLORS["In-person"]} />123 </BarChart>124 </ResponsiveContainer>125 <div style={{ marginTop: 12 }}>126 <strong>Key Insights</strong>127 <ul style={{ marginTop: 8, paddingLeft: 18 }}>128 <li>129 <strong>Smaller organizations and freelancers</strong> tend to have130 higher remote flexibility.131 </li>132 <li>133 <strong>Mid-to-large enterprises</strong> often favor hybrid models134 to balance scale and collaboration.135 </li>136 </ul>137 </div>138 </ChartCard>139 );140}141 