Untitled
"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> ); };
Leave a Comment