Your commit message

This commit is contained in:
Nalvazhuthi
2025-03-19 18:06:33 +05:30
parent 124e435504
commit 95ed64fc6f
33 changed files with 3115 additions and 10 deletions

View File

@@ -0,0 +1,130 @@
import React, { useEffect, useRef, useMemo } from "react";
import { Chart } from "chart.js/auto";
import { useThemeStore } from "../../../../../store/useThemeStore";
// 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);
const { themeColor } = useThemeStore();
// 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)
);
});

View File

@@ -0,0 +1,28 @@
import { useState } from "react";
import ToggleHeader from "../../../../ui/inputs/ToggleHeader";
import Widgets2D from "./Widgets2D";
import Widgets3D from "./Widgets3D";
import WidgetsTemplate from "./WidgetsTemplate";
const Widgets = () => {
const [activeOption, setActiveOption] = useState("2D");
const handleToggleClick = (option: string) => {
setActiveOption(option);
};
return (
<div className="widget-left-sideBar">
<ToggleHeader
options={["2D", "3D", "Templates"]}
activeOption={activeOption}
handleClick={handleToggleClick}
/>
{activeOption === "2D" && <Widgets2D />}
{activeOption === "3D" && <Widgets3D />}
{activeOption === "Templates" && <WidgetsTemplate />}
</div>
);
};
export default Widgets;

View File

@@ -0,0 +1,138 @@
import React from "react";
import { useWidgetStore } from "../../../../../store/useWidgetStore";
import { ChartType } from "chart.js/auto";
import ChartComponent from "./ChartComponent";
const chartTypes: ChartType[] = [
"bar",
"line",
"pie",
"doughnut",
"radar",
"polarArea",
];
const sampleData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
datasets: [
{
data: [65, 59, 80, 81, 56, 55, 40],
backgroundColor: "#6f42c1",
borderColor: "#ffffff",
borderWidth: 1,
},
],
};
interface WidgetProps {
type: ChartType;
index: number;
title: string;
}
const ChartWidget: React.FC<WidgetProps> = ({ type, index, title }) => {
const { setDraggedAsset } = useWidgetStore((state) => state);
return (
<div
className={`chart chart-${index + 1}`}
draggable
onDragStart={() => {
setDraggedAsset({
type,
id: `widget-${index + 1}`,
title,
panel: "top",
data: sampleData,
});
}}
onDragEnd={() => setDraggedAsset(null)}
>
<ChartComponent type={type} title={title} data={sampleData} />
</div>
);
};
const ProgressBarWidget = ({
id,
title,
data,
}: {
id: string;
title: string;
data: any;
}) => {
const { setDraggedAsset } = useWidgetStore((state) => state);
return (
<div
className="chart progressBar"
draggable
onDragStart={() => {
setDraggedAsset({
type: "progress",
id,
title,
panel: "top",
data,
});
}}
onDragEnd={() => setDraggedAsset(null)}
>
<div className="header">{title}</div>
{data.stocks.map((stock: any, index: number) => (
<div className="stock" key={index}>
<span className="stock-item">
<span className="stockValues">
<div className="key">{stock.key}</div>
<div className="value">{stock.value}</div>
</span>
<div className="stock-description">{stock.description}</div>
</span>
<div className="icon">Icon</div>
</div>
))}
</div>
);
};
const Widgets2D = () => {
return (
<div className="widget2D">
<div className="chart-container">
{chartTypes.map((type, index) => {
const widgetTitle = `Widget ${index + 1}`;
return (
<ChartWidget
key={index}
type={type}
index={index}
title={widgetTitle}
/>
);
})}
<ProgressBarWidget
id="widget-7"
title="Widget 7"
data={{
stocks: [
{ key: "units", value: 1000, description: "Initial stock" },
],
}}
/>
<ProgressBarWidget
id="widget-8"
title="Widget 8"
data={{
stocks: [
{ key: "units", value: 1000, description: "Initial stock" },
{ key: "units", value: 500, description: "Additional stock" },
],
}}
/>
</div>
</div>
);
};
export default Widgets2D;

View File

@@ -0,0 +1,11 @@
import React from 'react'
const Widgets3D = () => {
return (
<div>
Widgets3D
</div>
)
}
export default Widgets3D

View File

@@ -0,0 +1,12 @@
import React from 'react'
const WidgetsTemplate = () => {
return (
<div>
WidgetsTemplate
</div>
)
}
export default WidgetsTemplate