Add HorizontalBarChart and LineChart components; update package dependencies

This commit is contained in:
Vaibhav Surve 2025-04-09 17:37:27 +05:30
parent d4452ae19a
commit d0ab36799f
5 changed files with 327 additions and 6 deletions

View File

@ -27,7 +27,6 @@
<link rel="stylesheet" href="/assets/css/default.css" /> <link rel="stylesheet" href="/assets/css/default.css" />
<link rel="stylesheet" href="/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" /> <link rel="stylesheet" href="/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" />
<link rel="stylesheet" href="/assets/vendor/libs/apex-charts/apex-charts.css" />
<!-- Icons --> <!-- Icons -->
<link rel="stylesheet" href="/assets/vendor/fonts/boxicons.css" /> <link rel="stylesheet" href="/assets/vendor/fonts/boxicons.css" />
@ -83,7 +82,6 @@
<script src="/assets/vendor/libs/bs-stepper/bs-stepper.js"></script> <script src="/assets/vendor/libs/bs-stepper/bs-stepper.js"></script>
<script src="/assets/vendor/libs/bootstrap-select/bootstrap-select.js"></script> <script src="/assets/vendor/libs/bootstrap-select/bootstrap-select.js"></script>
<script src="/assets/vendor/libs/select2/select2.js"></script> <script src="/assets/vendor/libs/select2/select2.js"></script>
<script src="/assets/vendor/libs/apex-charts/apexcharts.js"></script>
<!-- <script src="/assets/vendor/libs/jquery-timepicker/jquery-timepicker.js" ></script> --> <!-- <script src="/assets/vendor/libs/jquery-timepicker/jquery-timepicker.js" ></script> -->
<script src="/assets/vendor/libs/flatpickr/flatpickr.js"></script> <script src="/assets/vendor/libs/flatpickr/flatpickr.js"></script>
<!-- Main JS --> <!-- Main JS -->

96
package-lock.json generated
View File

@ -12,6 +12,7 @@
"@reduxjs/toolkit": "^2.5.0", "@reduxjs/toolkit": "^2.5.0",
"@types/web": "^0.0.216", "@types/web": "^0.0.216",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"apexcharts": "^4.5.0",
"axios": "^1.7.9", "axios": "^1.7.9",
"axios-retry": "^4.5.0", "axios-retry": "^4.5.0",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
@ -22,6 +23,7 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"perfect-scrollbar": "^1.5.5", "perfect-scrollbar": "^1.5.5",
"react": "^18.2.0", "react": "^18.2.0",
"react-apexcharts": "^1.7.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",
@ -1116,6 +1118,62 @@
"win32" "win32"
] ]
}, },
"node_modules/@svgdotjs/svg.draggable.js": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.6.tgz",
"integrity": "sha512-7iJFm9lL3C40HQcqzEfezK2l+dW2CpoVY3b77KQGqc8GXWa6LhhmX5Ckv7alQfUXBuZbjpICZ+Dvq1czlGx7gA==",
"license": "MIT",
"peerDependencies": {
"@svgdotjs/svg.js": "^3.2.4"
}
},
"node_modules/@svgdotjs/svg.filter.js": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.9.tgz",
"integrity": "sha512-/69XMRCDoam2HgC4ldHIaDgeQf1ViHIsa0Ld4uWgiXtZ+E24DWHe/9Ib6kbNiZ7WRIdlVokUDR1Fg0kjIpkfbw==",
"license": "MIT",
"dependencies": {
"@svgdotjs/svg.js": "^3.2.4"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/@svgdotjs/svg.js": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.4.tgz",
"integrity": "sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Fuzzyma"
}
},
"node_modules/@svgdotjs/svg.resize.js": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz",
"integrity": "sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA==",
"license": "MIT",
"engines": {
"node": ">= 14.18"
},
"peerDependencies": {
"@svgdotjs/svg.js": "^3.2.4",
"@svgdotjs/svg.select.js": "^4.0.1"
}
},
"node_modules/@svgdotjs/svg.select.js": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@svgdotjs/svg.select.js/-/svg.select.js-4.0.2.tgz",
"integrity": "sha512-5gWdrvoQX3keo03SCmgaBbD+kFftq0F/f2bzCbNnpkkvW6tk4rl4MakORzFuNjvXPWwB4az9GwuvVxQVnjaK2g==",
"license": "MIT",
"engines": {
"node": ">= 14.18"
},
"peerDependencies": {
"@svgdotjs/svg.js": "^3.2.4"
}
},
"node_modules/@swc/core": { "node_modules/@swc/core": {
"version": "1.10.1", "version": "1.10.1",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.1.tgz", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.1.tgz",
@ -1656,6 +1714,12 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true "peer": true
}, },
"node_modules/@yr/monotone-cubic-spline": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==",
"license": "MIT"
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.14.0", "version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
@ -1758,6 +1822,20 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1" "url": "https://github.com/chalk/ansi-styles?sponsor=1"
} }
}, },
"node_modules/apexcharts": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.5.0.tgz",
"integrity": "sha512-E7ZkrVqPNBUWy/Rmg8DEIqHNBmElzICE/oxOX5Ekvs2ICQUOK/VkEkMH09JGJu+O/EA0NL31hxlmF+wrwrSLaQ==",
"license": "MIT",
"dependencies": {
"@svgdotjs/svg.draggable.js": "^3.0.4",
"@svgdotjs/svg.filter.js": "^3.0.8",
"@svgdotjs/svg.js": "^3.2.4",
"@svgdotjs/svg.resize.js": "^2.0.2",
"@svgdotjs/svg.select.js": "^4.0.1",
"@yr/monotone-cubic-spline": "^1.0.3"
}
},
"node_modules/argparse": { "node_modules/argparse": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@ -4000,7 +4078,6 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -4261,7 +4338,6 @@
"version": "15.8.1", "version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.4.0", "loose-envify": "^1.4.0",
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
@ -4323,6 +4399,19 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-apexcharts": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.7.0.tgz",
"integrity": "sha512-03oScKJyNLRf0Oe+ihJxFZliBQM9vW3UWwomVn4YVRTN1jsIR58dLWt0v1sb8RwJVHDMbeHiKQueM0KGpn7nOA==",
"license": "MIT",
"dependencies": {
"prop-types": "^15.8.1"
},
"peerDependencies": {
"apexcharts": ">=4.0.0",
"react": ">=0.13"
}
},
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
@ -4354,8 +4443,7 @@
"node_modules/react-is": { "node_modules/react-is": {
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
"dev": true
}, },
"node_modules/react-redux": { "node_modules/react-redux": {
"version": "9.2.0", "version": "9.2.0",

View File

@ -15,6 +15,7 @@
"@reduxjs/toolkit": "^2.5.0", "@reduxjs/toolkit": "^2.5.0",
"@types/web": "^0.0.216", "@types/web": "^0.0.216",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"apexcharts": "^4.5.0",
"axios": "^1.7.9", "axios": "^1.7.9",
"axios-retry": "^4.5.0", "axios-retry": "^4.5.0",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
@ -25,6 +26,7 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"perfect-scrollbar": "^1.5.5", "perfect-scrollbar": "^1.5.5",
"react": "^18.2.0", "react": "^18.2.0",
"react-apexcharts": "^1.7.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-redux": "^9.2.0", "react-redux": "^9.2.0",

View File

@ -0,0 +1,130 @@
import React from "react";
import ReactApexChart from "react-apexcharts";
import PropTypes from "prop-types";
const HorizontalBarChart = ({
seriesData = [],
categories = [],
colors = [
"#1E90FF", // Dodger Blue - Primary
"#00BFFF", // Deep Sky Blue - Info
"#9370DB", // Medium Purple - Success (replacing Lime Green)
"#6A0DAD", // Amethyst Purple - On Route (replacing Forest Green)
"#A9A9A9", // Dark Gray - Neutral
"#6A5ACD", // Slate Blue - Secondary
"#FFA500", // Orange - Warning
"#FF4500", // Orange Red - Danger
"#20B2AA", // Light Sea Green - Late
"#708090", // Slate Gray - Muted
],
}) => {
// Guard clause for invalid or incomplete data
const hasValidData =
Array.isArray(seriesData) &&
seriesData.length > 0 &&
Array.isArray(categories) &&
categories.length === seriesData.length;
if (!hasValidData) {
return <div className="text-center text-gray-500">No data to display</div>;
}
const chartOptions = {
chart: {
type: "bar",
height: 380,
toolbar: {
show: false, // This removes the menu
},
},
grid: {
show: false
},
plotOptions: {
bar: {
barHeight: "80%",
distributed: true,
horizontal: true,
dataLabels: {
position: "center",
},
},
},
colors,
dataLabels: {
enabled: true,
textAnchor: "start",
style: {
colors: ["#000"], // Switch to black for better visibility
},
formatter: function (val, opt) {
return `${opt.w.globals.labels[opt.dataPointIndex]}: ${val}`;
},
offsetX: 10, // Push label slightly to the right
dropShadow: {
enabled: false,
},
},
stroke: {
width: 1,
colors: ["#fff"],
},
xaxis: {
categories,
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
labels: {
show: false,
},
},
yaxis: {
labels: {
show: false,
},
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
},
tooltip: {
theme: "dark",
x: {
show: false,
},
y: {
title: {
formatter: () => "",
},
},
},
};
return (
<div className="w-full">
<ReactApexChart
options={chartOptions}
series={[{ data: seriesData }]}
type="bar"
height={380}
/>
</div>
);
};
HorizontalBarChart.propTypes = {
seriesData: PropTypes.arrayOf(PropTypes.number),
categories: PropTypes.arrayOf(PropTypes.string),
colors: PropTypes.arrayOf(PropTypes.string),
};
export default HorizontalBarChart;

View File

@ -0,0 +1,103 @@
import React from "react";
import ReactApexChart from "react-apexcharts";
import PropTypes from "prop-types";
const LineChart = ({
seriesData = [],
categories = [],
colors = ["#1E90FF", "#FF6347"], // default: Dodger Blue & Tomato
}) => {
const hasValidData =
Array.isArray(seriesData) &&
seriesData.length > 0 &&
Array.isArray(categories) &&
categories.length > 0;
if (!hasValidData) {
return <div className="text-center text-gray-500">No data to display</div>;
}
const chartOptions = {
chart: {
type: "line",
height: 350,
zoom: { enabled: false },
toolbar: { show: false },
background: 'transparent'
},
colors,
dataLabels: {
enabled: false // Hide value labels on dots
},
stroke: {
curve: 'straight'
},
grid: {
show: false,
xaxis: {
lines: {
show: false
}
},
yaxis: {
lines: {
show: false
}
}
},
markers: {
size: 5, // Increase dot visibility
strokeWidth: 0,
hover: {
size: 7
}
},
xaxis: {
categories,
labels: { show: false },
axisBorder: { show: false },
axisTicks: { show: false },
tooltip: { enabled: false }
},
yaxis: {
labels: { show: false },
axisBorder: { show: false },
axisTicks: { show: false },
min: 0
},
legend: {
show: true // Optional: Hide legend if not needed
},
tooltip: {
enabled: true // Keep this if you want value on hover
}
};
return (
<div className="w-full">
<ReactApexChart
options={chartOptions}
series={seriesData}
type="line"
height={350}
/>
</div>
);
};
LineChart.propTypes = {
seriesData: PropTypes.arrayOf(
PropTypes.shape({
name: PropTypes.string.isRequired,
data: PropTypes.arrayOf(PropTypes.number).isRequired
})
),
categories: PropTypes.arrayOf(PropTypes.string),
colors: PropTypes.arrayOf(PropTypes.string),
title: PropTypes.string
};
export default LineChart;