Add HorizontalBarChart and LineChart components; update package dependencies
This commit is contained in:
parent
d4452ae19a
commit
d0ab36799f
@ -27,7 +27,6 @@
|
||||
<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/apex-charts/apex-charts.css" />
|
||||
|
||||
<!-- Icons -->
|
||||
<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/bootstrap-select/bootstrap-select.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/flatpickr/flatpickr.js"></script>
|
||||
<!-- Main JS -->
|
||||
|
96
package-lock.json
generated
96
package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"@reduxjs/toolkit": "^2.5.0",
|
||||
"@types/web": "^0.0.216",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"apexcharts": "^4.5.0",
|
||||
"axios": "^1.7.9",
|
||||
"axios-retry": "^4.5.0",
|
||||
"dotenv": "^16.4.7",
|
||||
@ -22,6 +23,7 @@
|
||||
"moment": "^2.30.1",
|
||||
"perfect-scrollbar": "^1.5.5",
|
||||
"react": "^18.2.0",
|
||||
"react-apexcharts": "^1.7.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"react-redux": "^9.2.0",
|
||||
@ -1116,6 +1118,62 @@
|
||||
"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": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.1.tgz",
|
||||
@ -1656,6 +1714,12 @@
|
||||
"license": "Apache-2.0",
|
||||
"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": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
@ -1758,6 +1822,20 @@
|
||||
"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": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
@ -4000,7 +4078,6 @@
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -4261,7 +4338,6 @@
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
@ -4323,6 +4399,19 @@
|
||||
"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": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
@ -4354,8 +4443,7 @@
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "9.2.0",
|
||||
|
@ -15,6 +15,7 @@
|
||||
"@reduxjs/toolkit": "^2.5.0",
|
||||
"@types/web": "^0.0.216",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"apexcharts": "^4.5.0",
|
||||
"axios": "^1.7.9",
|
||||
"axios-retry": "^4.5.0",
|
||||
"dotenv": "^16.4.7",
|
||||
@ -25,6 +26,7 @@
|
||||
"moment": "^2.30.1",
|
||||
"perfect-scrollbar": "^1.5.5",
|
||||
"react": "^18.2.0",
|
||||
"react-apexcharts": "^1.7.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"react-redux": "^9.2.0",
|
||||
|
130
src/components/Charts/HorizontalBarChart.jsx
Normal file
130
src/components/Charts/HorizontalBarChart.jsx
Normal 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;
|
103
src/components/Charts/LineChart.jsx
Normal file
103
src/components/Charts/LineChart.jsx
Normal 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;
|
Loading…
x
Reference in New Issue
Block a user