Files
react-test/docs/data/material/getting-started/templates/dashboard/components/StatCard.js
how2ice 005cf56baf
Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
init project
2025-12-12 14:26:25 +09:00

131 lines
3.8 KiB
JavaScript

import { useTheme } from '@mui/material/styles';
import PropTypes from 'prop-types';
import Box from '@mui/material/Box';
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import Chip from '@mui/material/Chip';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { SparkLineChart } from '@mui/x-charts/SparkLineChart';
import { areaElementClasses } from '@mui/x-charts/LineChart';
function getDaysInMonth(month, year) {
const date = new Date(year, month, 0);
const monthName = date.toLocaleDateString('en-US', {
month: 'short',
});
const daysInMonth = date.getDate();
const days = [];
let i = 1;
while (days.length < daysInMonth) {
days.push(`${monthName} ${i}`);
i += 1;
}
return days;
}
function AreaGradient({ color, id }) {
return (
<defs>
<linearGradient id={id} x1="50%" y1="0%" x2="50%" y2="100%">
<stop offset="0%" stopColor={color} stopOpacity={0.3} />
<stop offset="100%" stopColor={color} stopOpacity={0} />
</linearGradient>
</defs>
);
}
AreaGradient.propTypes = {
color: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
};
function StatCard({ title, value, interval, trend, data }) {
const theme = useTheme();
const daysInWeek = getDaysInMonth(4, 2024);
const trendColors = {
up:
theme.palette.mode === 'light'
? theme.palette.success.main
: theme.palette.success.dark,
down:
theme.palette.mode === 'light'
? theme.palette.error.main
: theme.palette.error.dark,
neutral:
theme.palette.mode === 'light'
? theme.palette.grey[400]
: theme.palette.grey[700],
};
const labelColors = {
up: 'success',
down: 'error',
neutral: 'default',
};
const color = labelColors[trend];
const chartColor = trendColors[trend];
const trendValues = { up: '+25%', down: '-25%', neutral: '+5%' };
return (
<Card variant="outlined" sx={{ height: '100%', flexGrow: 1 }}>
<CardContent>
<Typography component="h2" variant="subtitle2" gutterBottom>
{title}
</Typography>
<Stack
direction="column"
sx={{ justifyContent: 'space-between', flexGrow: '1', gap: 1 }}
>
<Stack sx={{ justifyContent: 'space-between' }}>
<Stack
direction="row"
sx={{ justifyContent: 'space-between', alignItems: 'center' }}
>
<Typography variant="h4" component="p">
{value}
</Typography>
<Chip size="small" color={color} label={trendValues[trend]} />
</Stack>
<Typography variant="caption" sx={{ color: 'text.secondary' }}>
{interval}
</Typography>
</Stack>
<Box sx={{ width: '100%', height: 50 }}>
<SparkLineChart
color={chartColor}
data={data}
area
showHighlight
showTooltip
xAxis={{
scaleType: 'band',
data: daysInWeek, // Use the correct property 'data' for xAxis
}}
sx={{
[`& .${areaElementClasses.root}`]: {
fill: `url(#area-gradient-${value})`,
},
}}
>
<AreaGradient color={chartColor} id={`area-gradient-${value}`} />
</SparkLineChart>
</Box>
</Stack>
</CardContent>
</Card>
);
}
StatCard.propTypes = {
data: PropTypes.arrayOf(PropTypes.number).isRequired,
interval: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
trend: PropTypes.oneOf(['down', 'neutral', 'up']).isRequired,
value: PropTypes.string.isRequired,
};
export default StatCard;