Skip to content

Instantly share code, notes, and snippets.

@Mazyod
Created March 14, 2025 10:00
Show Gist options
  • Save Mazyod/893e10d88f26eb6cb0efbcf4690a3d00 to your computer and use it in GitHub Desktop.
Save Mazyod/893e10d88f26eb6cb0efbcf4690a3d00 to your computer and use it in GitHub Desktop.
Recharts Dynamic Dashboard Example

React Dynamic Dashboard

Using recharts to create a dynamic dashboard.

image

import React, { useMemo } from 'react';
import {
LineChart,
Line,
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
PieChart,
Pie,
Cell
} from 'recharts';
// Global variables
const COLORS = [
'#8884d8', // purple
'#82ca9d', // green
'#ffc658', // yellow
'#ff8042', // orange
'#0088fe', // blue
'#00c49f', // teal
'#ff6b6b', // red
'#a4de6c' // light green
];
// Sample data
const DATA = [
{ name: 'Jan', revenue: 4000, profit: 2400, costs: 1600, customers: 120 },
{ name: 'Feb', revenue: 3000, profit: 1398, costs: 1602, customers: 98 },
{ name: 'Mar', revenue: 2000, profit: 9800, costs: 1950, customers: 150 },
{ name: 'Apr', revenue: 2780, profit: 3908, costs: 1800, customers: 130 },
{ name: 'May', revenue: 1890, profit: 4800, costs: 1700, customers: 110 },
{ name: 'Jun', revenue: 2390, profit: 3800, costs: 1550, customers: 105 },
{ name: 'Jul', revenue: 3490, profit: 4300, costs: 1750, customers: 140 },
];
// Dynamic Line Chart Component
const DynamicLineChart = ({ data, title = "Line Chart", height = 250 }) => {
const dataKeys = useMemo(() => {
if (!data || data.length === 0) return [];
return Object.keys(data[0]).filter(key => key !== 'name');
}, [data]);
if (!data || data.length === 0) {
return <div>No data available</div>;
}
return (
<div className="w-full">
<h3 className="text-lg font-semibold mb-2">{title}</h3>
<div style={{ height: `${height}px`, width: '100%' }}>
<ResponsiveContainer width="100%" height="100%">
<LineChart
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
{dataKeys.map((key, index) => (
<Line
key={key}
type="monotone"
dataKey={key}
stroke={COLORS[index % COLORS.length]}
activeDot={{ r: 8 }}
strokeWidth={2}
/>
))}
</LineChart>
</ResponsiveContainer>
</div>
</div>
);
};
// Dynamic Pie Chart Component
const DynamicPieChart = ({ data, title, height = 250, dataKey }) => {
const dataKeys = useMemo(() => {
if (!data || data.length === 0) return [];
return Object.keys(data[0]).filter(key => key !== 'name');
}, [data]);
const pieData = useMemo(() => {
if (!data || data.length === 0 || (!dataKey && dataKeys.length === 0)) return [];
const keyToUse = dataKey || dataKeys[0];
return data.map(item => ({
name: item.name,
value: item[keyToUse]
}));
}, [data, dataKeys, dataKey]);
if (!data || data.length === 0 || (!dataKey && dataKeys.length === 0)) {
return <div>No data available</div>;
}
const keyName = dataKey || dataKeys[0];
const dataKeyName = keyName ? keyName.charAt(0).toUpperCase() + keyName.slice(1) : 'Data';
const chartTitle = title || `Distribution of ${dataKeyName}`;
return (
<div className="w-full">
<h3 className="text-lg font-semibold mb-2">{chartTitle}</h3>
<div style={{ height: `${height}px`, width: '100%' }}>
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie
data={pieData}
cx="50%"
cy="50%"
labelLine={true}
outerRadius={80}
fill="#8884d8"
dataKey="value"
nameKey="name"
label={({ name, percent }) => `${name}: ${(percent * 100).toFixed(0)}%`}
>
{pieData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip formatter={(value, name, props) => {
const total = pieData.reduce((sum, entry) => sum + entry.value, 0);
return [`${value} (${((value / total) * 100).toFixed(1)}%)`, name];
}} />
<Legend />
</PieChart>
</ResponsiveContainer>
</div>
</div>
);
};
// Multiple Pie Charts Component
const MultiPieCharts = ({ data, height = 250 }) => {
const dataKeys = useMemo(() => {
if (!data || data.length === 0) return [];
return Object.keys(data[0]).filter(key => key !== 'name');
}, [data]);
if (!data || data.length === 0 || dataKeys.length === 0) {
return <div>No data available</div>;
}
return (
<div className="w-full">
<h3 className="text-lg font-semibold mb-4">Data Distribution</h3>
<div className="flex flex-wrap">
{dataKeys.map(key => (
<div
key={key}
className="p-2"
style={{ width: '300px' }}
>
<DynamicPieChart
data={data}
dataKey={key}
height={height}
/>
</div>
))}
</div>
</div>
);
};
// Dynamic Stacked Bar Chart Component
const DynamicStackedBarChart = ({ data = DATA }) => {
const dataKeys = useMemo(() => {
if (!data || data.length === 0) return [];
return Object.keys(data[0]).filter(key => key !== 'name');
}, [data]);
return (
<div className="w-full">
<h3 className="text-lg font-semibold mb-2">Monthly Data Breakdown</h3>
<div className="h-64 w-full">
<ResponsiveContainer width="100%" height="100%">
<BarChart
data={data}
margin={{
top: 20,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip
formatter={(value, name) => [
`${value}`,
name.charAt(0).toUpperCase() + name.slice(1)
]}
/>
<Legend />
{dataKeys.map((key, index) => (
<Bar
key={key}
dataKey={key}
stackId="a"
fill={COLORS[index % COLORS.length]}
name={key.charAt(0).toUpperCase() + key.slice(1)}
/>
))}
</BarChart>
</ResponsiveContainer>
</div>
</div>
);
};
// Main Dashboard Component
const ComprehensiveDashboard = () => {
return (
<div className="w-full p-4">
<h2 className="text-xl font-bold mb-4 text-center">Company Performance Dashboard</h2>
<div className="w-full mb-8">
<DynamicLineChart
data={DATA}
title="Trends over Time"
height={250}
/>
</div>
<div className="w-full mb-8">
<DynamicStackedBarChart data={DATA} />
</div>
<div className="w-full">
<MultiPieCharts
data={DATA}
height={220}
/>
</div>
</div>
);
};
export default ComprehensiveDashboard;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment