import React, { useEffect, useRef, useMemo } from "react"; import { Chart } from "chart.js/auto"; // Define Props Interface interface ChartComponentProps { type: any; // Type of chart (e.g., "bar", "line", etc.) title: string; // Title of the chart fontFamily?: string; // Optional font family for the chart title fontSize?: string; // Optional font size for the chart title fontWeight?: "Light" | "Regular" | "Bold"; // Optional font weight for the chart title data: { labels: string[]; // Labels for the x-axis datasets: { data: number[]; // Data points for the chart backgroundColor: string; // Background color for the chart borderColor: string; // Border color for the chart borderWidth: number; // Border width for the chart }[]; }; // Data for the chart } const ChartComponent = ({ type, title, fontFamily, fontSize, fontWeight = "Regular", // Default to "Regular" data: propsData, }: ChartComponentProps) => { const canvasRef = useRef<HTMLCanvasElement>(null); // Memoize Theme Colors to Prevent Unnecessary Recalculations // const buttonActionColor = useMemo( // () => themeColor[0] || "#5c87df", // [themeColor] // ); // const buttonAbortColor = useMemo( // () => themeColor[1] || "#ffffff", // [themeColor] // ); // Memoize Font Weight Mapping const chartFontWeightMap = useMemo( () => ({ Light: "lighter" as const, Regular: "normal" as const, Bold: "bold" as const, }), [] ); // Parse and Memoize Font Size const fontSizeValue = useMemo( () => (fontSize ? parseInt(fontSize) : 12), [fontSize] ); // Determine and Memoize Font Weight const fontWeightValue = useMemo( () => chartFontWeightMap[fontWeight], [fontWeight, chartFontWeightMap] ); // Memoize Chart Font Style const chartFontStyle = useMemo( () => ({ family: fontFamily ?? "Arial", size: fontSizeValue, weight: fontWeightValue, color: "#2B3344", }), [fontFamily, fontSizeValue, fontWeightValue] ); // Memoize Chart Data const data = useMemo(() => propsData, [propsData]); // Memoize Chart Options const options = useMemo( () => ({ responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: title, font: chartFontStyle, align: "start", // Left align the title padding: { top: 10, // Add padding above the title bottom: 20, // Add padding between the title and the chart }, }, legend: { display: false, }, }, }), [title, chartFontStyle] ); // Initialize Chart on Component Mount useEffect(() => { if (!canvasRef.current) return; const ctx = canvasRef.current.getContext("2d"); if (!ctx) return; const chart = new Chart(ctx, { type, data, options }); // Cleanup: Destroy the chart instance when the component unmounts return () => chart.destroy(); }, [type, data, options]); // Only recreate the chart when these dependencies change return <canvas ref={canvasRef} style={{ width: "100%", height: "100%" }} />; }; export default React.memo(ChartComponent, (prevProps, nextProps) => { // Custom comparison function to prevent unnecessary re-renders return ( prevProps.type === nextProps.type && prevProps.title === nextProps.title && prevProps.fontFamily === nextProps.fontFamily && prevProps.fontSize === nextProps.fontSize && prevProps.fontWeight === nextProps.fontWeight && JSON.stringify(prevProps.data) === JSON.stringify(nextProps.data) ); });