import React from "react"; import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, PointElement, LineController, BarController, LineElement, Title, Tooltip, Legend, Filler, } from "chart.js"; import { Chart } from "react-chartjs-2"; import util from "../../lib/util"; import constants from "../../lib/common/constants"; type MonthKeys = keyof typeof constants.month; const plugins = [{ id: 'corsair', defaults: { width: 1, color: '#22222', dash: [3, 3], }, afterInit: (chart: any) => { chart.corsair = { x: 0 } }, afterEvent: (chart: any, args: any) => { const {inChartArea} = args const {x} = args.event chart.corsair = {x, draw: inChartArea} chart.draw() }, beforeDatasetsDraw: (chart: any, opts: any) => { const corsair = chart.corsair; if (!corsair?.draw) return; if (!chart.chartArea) return; const { ctx, chartArea } = chart; const { top, bottom, left, right } = chartArea; if (corsair.x < left || corsair.x > right) return; ctx.save(); ctx.beginPath(); ctx.lineWidth = opts.width ?? 1; ctx.strokeStyle = opts.color ?? '#999'; ctx.setLineDash(opts.dash ?? []); ctx.moveTo(corsair.x, bottom); ctx.lineTo(corsair.x, top); ctx.stroke(); ctx.setLineDash([]); ctx.restore(); } }] ChartJS.register( LineController, BarController, CategoryScale, LinearScale, BarElement, PointElement, LineElement, Title, Tooltip, Legend, Filler, plugins ); interface Props { rateData: any; days: number } function formatRupee(value: number): string { if (value < 100) return `${value}`; // No suffix for values below 100 const suffixes = [ { threshold: 1e7, suffix: "Cr" }, // Crore { threshold: 1e5, suffix: "L" }, // Lakh { threshold: 1e3, suffix: "K" }, // Thousand { threshold: 100, suffix: "H" }, // Hundred ]; for (const { threshold, suffix } of suffixes) { if (value >= threshold) { return `${(value / threshold).toFixed(0)}${suffix}`; } } return `${value}`; // Fallback } const MultiTypeChart = (props: Props) => { const { rateData, days } = props; // const searchParams = useSearchParams(); // const period = searchParams.get("period"); // const days = 30 | 180 | 365; const lastNDays = util.getLastNDaysArray(days); const dailyReport = rateData?.length > 0 ? rateData?.map((rate: any) => ({ ...rate, date: rate.created_at.split("T")[0], })) : []; const reportLookup = dailyReport?.reduce((acc: any, report: any) => { const formattedDate = util.formatDateDDMMYY(report.date); acc[formattedDate] = { customer_price: report.customer_price, ton: report.ton, }; return acc; }, {}); const mappedReports = lastNDays?.map((date) => ({ date, customer_price: reportLookup[date] ? reportLookup[date].customer_price : null, ton: reportLookup[date] ? reportLookup[date].ton : null, })); const reversedReports = mappedReports.reverse(); const labels = reversedReports?.map((d: any) => { const splitDate = d.date.split("-") as [string, MonthKeys, string]; return `${splitDate[0]}-${constants.month[splitDate[1]]}-${splitDate[2]}`; }); const frieght = reversedReports?.map((d: any) => d.customer_price); const ton = reversedReports?.map((d: any) => d.ton); const data = { labels, datasets: [ { type: "line" as const, label: "Metric Tonne", data: ton, borderColor: "rgba(255, 94, 0, 0)", backgroundColor: "rgba(255, 94, 0, 0)", fill: false, yAxisID: "y1", }, { type: "line" as const, label: "Freight Rate", data: frieght, backgroundColor: "rgba(49, 110, 252, 0.3)", borderColor: "rgba(49, 110, 252, 1)", borderWidth: 2, fill: true, tension: 0.1, yAxisID: "y", xAxisID: "x", }, ], }; const options: any = { elements: { point: { radius: 0, }, }, responsive: true, maintainAspectRatio: false, spanGaps: true, interaction: { mode: "index" as const, intersect: false, }, tooltips: { mode: "index", intersect: false, }, hover: { mode: "index", intersect: false, }, plugins: { legend: { display: false, position: "bottom", align: "start", } }, scales: { y1: { type: "linear", display: false, position: "right", grid: { drawOnChartArea: false, // only want the grid lines for one axis to show up }, ticks: { callback: function (value: any) { return value.toFixed(0); // Format y1-axis values as tens }, }, }, y: { type: "linear", display: true, position: "left", ticks: { maxTicksLimit: 5, callback: function (value: number) { return "₹" + formatRupee(value).toLocaleString(); // Format y-axis values as thousands }, }, }, x: { ticks: { display: true, maxTicksLimit: days === 365 ? 12 : days === 180 ? 6 : 30, callback: function (_: any, index: any) { const date = labels[index] const splitDate = date.split("-"); const xLabel = days === 30 ? `${splitDate[0]}-${splitDate[1]}` : `${splitDate[1]}-${splitDate[2]}` return xLabel; }, }, }, }, }; return ; }; export default MultiTypeChart;