CE-604 Adding chartSubheaderData; updating styles

This commit is contained in:
2023-10-20 10:32:00 -05:00
parent 970c9f262c
commit b903e6bef9
3 changed files with 81 additions and 33 deletions

View File

@ -28,6 +28,7 @@ import {Bar} from "react-chartjs-2";
import {useNavigate} from "react-router-dom"; import {useNavigate} from "react-router-dom";
import colors from "qqq/assets/theme/base/colors"; import colors from "qqq/assets/theme/base/colors";
import {chartColors, DefaultChartData} from "qqq/components/widgets/charts/DefaultChartData"; import {chartColors, DefaultChartData} from "qqq/components/widgets/charts/DefaultChartData";
import ChartSubheaderWithData, {ChartSubheaderData} from "qqq/components/widgets/components/ChartSubheaderWithData";
ChartJS.register( ChartJS.register(
CategoryScale, CategoryScale,
@ -39,18 +40,32 @@ ChartJS.register(
); );
export const options = { export const options = {
maintainAspectRatio: false,
responsive: true, responsive: true,
animation: { animation: {
duration: 0 duration: 0
}, },
plugins: {
legend: {
position: "bottom",
labels: {
usePointStyle: true,
pointStyle: "circle",
pointStyleWidth: 3,
padding: 20
}
}
},
scales: { scales: {
x: { x: {
stacked: true, stacked: true,
grid: {offset: false}, grid: {display: false},
ticks: {autoSkip: false, maxRotation: 90} ticks: {autoSkip: false, maxRotation: 90}
}, },
y: { y: {
stacked: true, stacked: true,
position: "right",
ticks: {precision: 0}
}, },
}, },
}; };
@ -58,10 +73,12 @@ export const options = {
interface Props interface Props
{ {
data: DefaultChartData; data: DefaultChartData;
chartSubheaderData?: ChartSubheaderData;
} }
const {gradients} = colors; const {gradients} = colors;
function StackedBarChart({data}: Props): JSX.Element
function StackedBarChart({data, chartSubheaderData}: Props): JSX.Element
{ {
const navigate = useNavigate(); const navigate = useNavigate();
@ -70,23 +87,30 @@ function StackedBarChart({data}: Props): JSX.Element
const handleClick = (e: Array<{}>) => const handleClick = (e: Array<{}>) =>
{ {
if(e && e.length > 0 && data?.urls && data?.urls.length) if (e && e.length > 0 && data?.urls && data?.urls.length)
{ {
// @ts-ignore // @ts-ignore
navigate(data.urls[e[0]["index"]]); navigate(data.urls[e[0]["index"]]);
} }
console.log(e); console.log(e);
} };
useEffect(() => useEffect(() =>
{ {
if(data) if (data)
{ {
data?.datasets.forEach((dataset: any, index: number) => data?.datasets.forEach((dataset: any, index: number) =>
{ {
if (!dataset.backgroundColor) if (!dataset.backgroundColor)
{ {
dataset.backgroundColor = gradients[chartColors[index]].state; if (gradients[chartColors[index]])
{
dataset.backgroundColor = gradients[chartColors[index]].state;
}
else
{
dataset.backgroundColor = chartColors[index];
}
} }
}); });
setStateData(stateData); setStateData(stateData);
@ -95,8 +119,13 @@ function StackedBarChart({data}: Props): JSX.Element
return data ? ( return data ? (
<Box p={3}><Bar data={data} options={options} getElementsAtEvent={handleClick} /></Box> <Box p={3} pt={1}>
) : <Skeleton sx={{marginLeft: "20px", marginRight: "20px", height: "200px"}} /> ; {chartSubheaderData && (<ChartSubheaderWithData chartSubheaderData={chartSubheaderData} />)}
<Box width="100%" height="250px">
<Bar data={data} options={options} getElementsAtEvent={handleClick} />
</Box>
</Box>
) : <Skeleton sx={{marginLeft: "20px", marginRight: "20px", height: "200px"}} />;
} }
export default StackedBarChart; export default StackedBarChart;

View File

@ -30,6 +30,7 @@ import {useNavigate} from "react-router-dom";
import MDTypography from "qqq/components/legacy/MDTypography"; import MDTypography from "qqq/components/legacy/MDTypography";
import {chartColors} from "qqq/components/widgets/charts/DefaultChartData"; import {chartColors} from "qqq/components/widgets/charts/DefaultChartData";
import configs from "qqq/components/widgets/charts/piechart/PieChartConfigs"; import configs from "qqq/components/widgets/charts/piechart/PieChartConfigs";
import ChartSubheaderWithData, {ChartSubheaderData} from "qqq/components/widgets/components/ChartSubheaderWithData";
////////////////////////////////////////// //////////////////////////////////////////
// structure of expected bar chart data // // structure of expected bar chart data //
@ -51,12 +52,13 @@ interface Props
{ {
description?: string; description?: string;
chartData: PieChartData; chartData: PieChartData;
chartSubheaderData?: ChartSubheaderData;
[key: string]: any; [key: string]: any;
} }
function PieChart({description, chartData}: Props): JSX.Element function PieChart({description, chartData, chartSubheaderData}: Props): JSX.Element
{ {
const navigate = useNavigate(); const navigate = useNavigate();
const [dataLoaded, setDataLoaded] = useState(false); const [dataLoaded, setDataLoaded] = useState(false);
@ -69,7 +71,7 @@ function PieChart({description, chartData}: Props): JSX.Element
useEffect(() => useEffect(() =>
{ {
if(chartData) if (chartData)
{ {
setDataLoaded(true); setDataLoaded(true);
} }
@ -77,19 +79,22 @@ function PieChart({description, chartData}: Props): JSX.Element
const handleClick = (e: Array<{}>) => const handleClick = (e: Array<{}>) =>
{ {
if(e && e.length > 0 && chartData?.dataset?.urls && chartData?.dataset?.urls.length) if (e && e.length > 0 && chartData?.dataset?.urls && chartData?.dataset?.urls.length)
{ {
// @ts-ignore // @ts-ignore
navigate(chartData.dataset.urls[e[0]["index"]]); navigate(chartData.dataset.urls[e[0]["index"]]);
} }
} };
return ( return (
<Card sx={{minHeight: "400px", boxShadow: "none", height: "100%", width: "100%", display: "flex", flexGrow: 1, border: 0}}> <Card sx={{boxShadow: "none", height: "100%", width: "100%", display: "flex", flexGrow: 1, border: 0}}>
<Box mt={3}> <Box mt={1}>
<Box px={3}>
{chartSubheaderData && (<ChartSubheaderWithData chartSubheaderData={chartSubheaderData} />)}
</Box>
<Grid container alignItems="center"> <Grid container alignItems="center">
<Grid item xs={12} justifyContent="center"> <Grid item xs={12} justifyContent="center">
<Box width="100%" height="80%" py={2} pr={2} pl={2}> <Box width="100%" height="250px" py={2} pr={2} pl={2}>
{useMemo( {useMemo(
() => ( () => (
<Pie data={data} options={options} getElementsAtEvent={handleClick} /> <Pie data={data} options={options} getElementsAtEvent={handleClick} />
@ -98,32 +103,35 @@ function PieChart({description, chartData}: Props): JSX.Element
)} )}
</Box> </Box>
{ {
! chartData && ( !chartData && (
<Box sx={{ <Box sx={{
position: "absolute", position: "absolute",
top: "40%", top: "40%",
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
display: "flex", display: "flex",
justifyContent: "center"}}> justifyContent: "center"
<Skeleton sx={{width: "150px", height: "150px"}} variant="circular"/> }}>
<Skeleton sx={{width: "150px", height: "150px"}} variant="circular" />
</Box> </Box>
) )
} }
</Grid> </Grid>
</Grid> </Grid>
<Divider />
{ {
description && ( description && (
<Grid container> <>
<Grid item xs={12}> <Divider />
<Box pb={2} px={2} display="flex" flexDirection={{xs: "column", sm: "row"}} mt="auto"> <Grid container>
<MDTypography variant="button" color="text" fontWeight="light"> <Grid item xs={12}>
{parse(description)} <Box pb={2} px={2} display="flex" flexDirection={{xs: "column", sm: "row"}} mt="auto">
</MDTypography> <MDTypography variant="button" color="text" fontWeight="light">
</Box> {parse(description)}
</MDTypography>
</Box>
</Grid>
</Grid> </Grid>
</Grid> </>
) )
} }
</Box> </Box>

View File

@ -30,10 +30,16 @@ function configs(labels: any, datasets: any)
if (datasets.backgroundColors) if (datasets.backgroundColors)
{ {
datasets.backgroundColors.forEach((color: string) => datasets.backgroundColors.forEach((color: string) =>
gradients[color] {
? backgroundColors.push(gradients[color].state) if (gradients[color])
: backgroundColors.push(dark.main) {
); backgroundColors.push(gradients[color].state);
}
else
{
backgroundColors.push(color);
}
});
} }
else else
{ {
@ -58,12 +64,17 @@ function configs(labels: any, datasets: any)
], ],
}, },
options: { options: {
maintainAspectRatio: true, maintainAspectRatio: false,
responsive: true, responsive: true,
aspectRatio: 2,
plugins: { plugins: {
legend: { legend: {
position: "bottom", position: "bottom",
labels: {
usePointStyle: true,
pointStyle: "circle",
pointStyleWidth: 3,
padding: 20
}
}, },
}, },
scales: { scales: {