marco.pms.web/src/components/Charts/HorizontalBarChart.jsx

143 lines
3.5 KiB
JavaScript

import React from "react";
import ReactApexChart from "react-apexcharts";
import PropTypes from "prop-types";
const HorizontalBarChart = ({
seriesData = [],
categories = [],
colors = [
"#1E90FF",
"#00BFFF",
"#9370DB",
"#6A0DAD",
"#A9A9A9",
"#6A5ACD",
"#FFA500",
"#FF4500",
"#20B2AA",
"#708090",
],
loading = false,
}) => {
// Show loading state
if (loading) {
return (
<div className="w-full h-[380px] flex items-center justify-center bg-gray-100 rounded-xl">
<span className="text-gray-500">Loading chart...</span>
{/* Replace this with a skeleton or spinner if you prefer */}
</div>
);
}
// 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>;
}
// Combine seriesData and categories, then sort in descending order
const combined = seriesData.map((value, index) => ({
value,
label: categories[index],
}));
const sorted = combined.sort((a, b) => b.value - a.value);
// Extract sorted values
const sortedSeriesData = sorted.map((item) => item.value);
const sortedCategories = sorted.map((item) => item.label);
// Replace 0 with 1 for visual purposes, but display "0%" in labels
const adjustedSeriesData = sortedSeriesData.map((val) =>
val === 0 ? 0.5 : val
);
// Dynamically adjust chart height if only one data point
const chartHeight = seriesData.length === 1 ? 80 : 380;
const chartOptions = {
chart: {
type: "bar",
height: chartHeight,
toolbar: { show: false },
},
grid: { show: false },
plotOptions: {
bar: {
barHeight: seriesData.length === 1 ? "30%" : "60%",
distributed: true,
horizontal: true,
borderRadius: 3,
borderRadiusApplication: "end",
dataLabels: {
position: "top",
},
},
},
colors,
dataLabels: {
enabled: true,
textAnchor: "center",
style: {
colors: ["#000"], // Black labels
fontSize: "8px",
},
formatter: function (_, opt) {
const originalVal = sortedSeriesData[opt.dataPointIndex]; // Show real value
return `${originalVal}%`;
},
offsetX: 10,
dropShadow: { enabled: false },
},
stroke: {
width: 1,
colors: ["#fff"],
},
xaxis: {
categories: sortedCategories,
axisBorder: { show: false },
axisTicks: { show: false },
labels: { show: false },
},
yaxis: {
labels: { show: false },
axisBorder: { show: false },
axisTicks: { show: false },
},
legend: {
show: true,
},
tooltip: {
x: { show: true },
y: {
formatter: function (val) {
return (val < 1 ? Math.floor(val) : val) + "%";
},
},
},
};
return (
<div className="w-full">
<ReactApexChart
options={chartOptions}
series={[{ data: adjustedSeriesData, name: "Complete Work" }]}
type="bar"
height={chartHeight}
/>
</div>
);
};
HorizontalBarChart.propTypes = {
seriesData: PropTypes.arrayOf(PropTypes.number),
categories: PropTypes.arrayOf(PropTypes.string),
colors: PropTypes.arrayOf(PropTypes.string),
loading: PropTypes.bool,
};
export default HorizontalBarChart;