Untitled
unknown
plain_text
a year ago
5.1 kB
13
Indexable
"use client";
import React from "react";
import {
Area,
AreaChart,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
CartesianGrid,
} from "recharts";
// Function to format Y-axis values
const formatNumber = (num) => {
if (num >= 1000000000) {
return Math.round(num / 1000000000) + "B"; // For billions
} else if (num >= 1000000) {
return Math.round(num / 1000000) + "M"; // For millions
} else if (num >= 1000) {
return Math.round(num / 1000) + "K"; // For thousands
} else {
return num?.toString(); // For numbers less than 1000
}
};
// Updated formatYAxis function to use formatNumber
const formatYAxis = (chartItem) => {
return formatNumber(chartItem);
};
const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip bg-white px-8 py-1 rounded-full border-2 border-slate-300">
<p className="label text-sm ">{`${formatNumber(payload[0].value)}`}</p>
</div>
);
}
return null;
};
// Function to generate X-axis labels based on the selected period
const generateXAxisLabels = (selectedPeriod) => {
const currentDate = new Date();
const currentMonth = currentDate.getMonth();
const monthNames = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
if (selectedPeriod === "6m") {
let labels = [];
for (let i = 5; i >= 0; i--) {
let monthIndex = (currentMonth - i + 12) % 12;
labels.push(monthNames[monthIndex]);
}
return labels;
}
// Default behavior for other periods
switch (selectedPeriod) {
case "7d":
return ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
case "30d":
return ["Week 1", "Week 2", "Week 3", "Week 4"];
case "12m":
return monthNames;
default:
return [];
}
};
export const Chart = ({ data, selectedPeriod, isLoading }) => {
const xAxisLabels = generateXAxisLabels(selectedPeriod);
// Prepare chart data to ensure all X-axis labels are included
let chartData = xAxisLabels.map((label) => {
const item = data?.find((d) => d.typeValue === label);
const increasedValue = item ? Math.round((item.value * 1.2) / 10) * 10 : 0; // Increase by 20% and round to nearest 10
return {
name: label,
value: increasedValue,
};
});
const hasData = chartData.some((item) => item.value !== 0);
// Calculate the maximum value for the Y-axis
const maxValue = Math.max(...chartData.map((item) => item.value));
// Calculate tick interval and max Y-axis value to always have 5 ticks
const tickInterval = maxValue > 0 ? Math.ceil(maxValue / 5) : 1;
const maxYAxisValue = tickInterval * 5; // Ensure we have exactly 5 ticks
// Generate tick values for the Y-axis
const yAxisTicks = Array.from({ length: 6 }, (_, i) => i * tickInterval); // Includes 0 to maxYAxisValue
return (
<div className="mb-10">
<ResponsiveContainer width={"100%"} minHeight={300}>
<AreaChart
data={chartData}
margin={{ left: 15, right: 15, top: 10, bottom: 10 }}
>
<defs>
<linearGradient id="colorPv" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#EEF6FF" stopOpacity={0.8} />
<stop offset="95%" stopColor="#DADEFF" stopOpacity={0} />
</linearGradient>
</defs>
{hasData && <CartesianGrid strokeDasharray="3 3" vertical={false} />}
<XAxis
dataKey="name"
axisLine={{ stroke: "#DADEFE" }}
tickLine={true}
// padding={{ left: 15, right: 15 }}
interval={0} // Ensure every tick is displayed
tick={{
dy: 15, // Add space between the X-axis values and the axis line
}}
/>
{hasData && (
<YAxis
axisLine={false}
tickFormatter={formatYAxis}
tick={{
fill: "#999",
fontSize: 14,
}}
domain={[0, maxYAxisValue]} // Set Y-axis domain
ticks={yAxisTicks} // Set specific tick values
/>
)}
<Tooltip content={<CustomTooltip />} />
<Area
type="monotone"
dataKey="value"
stroke={hasData ? "#347DFD" : "none"}
strokeWidth={3}
fillOpacity={4}
fill="url(#colorPv)"
/>
{!hasData && !isLoading && (
<text
x="50%"
y="50%"
textAnchor="middle"
dominantBaseline="middle"
style={{ fontSize: "16px", fill: "#888" }}
>
No data available
</text>
)}
</AreaChart>
</ResponsiveContainer>
</div>
);
};
Editor is loading...
Leave a Comment