Files
Doormilexpress_console/src/components/nearle_components/StatCard.js

78 lines
2.7 KiB
JavaScript

import PropTypes from 'prop-types';
import { Avatar, Box, Card, CardContent, Skeleton, Stack, Typography } from '@mui/material';
// ==============================|| STAT / KPI CARD (Doormile-style) ||============================== //
// Clean metric card: muted label, large value, a single soft-tinted rounded
// avatar holding the icon. No coloured top-stripe, no rainbow — colour appears
// only in the small avatar so a row of cards reads calm and corporate.
//
// `icon` is a rendered node, e.g. icon={<MdLocalShipping size={20} />}.
// `color` is a hex accent (defaults to brand purple); `caption` is the small
// muted line under the value (e.g. "96% of total").
export default function StatCard({ title, value, icon, color = '#C01227', caption, loading = false }) {
return (
<Card sx={{ height: '100%' }}>
<CardContent sx={{ p: { xs: 1.75, md: 2 }, '&:last-child': { pb: { xs: 1.75, md: 2 } } }}>
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={1}>
<Box sx={{ minWidth: 0, flex: 1 }}>
<Typography
variant="body2"
sx={{
fontWeight: 500,
color: 'text.secondary',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}
>
{title}
</Typography>
{loading ? (
<Skeleton variant="rounded" sx={{ width: 72, height: 30, mt: 0.5 }} animation="wave" />
) : (
<Typography
sx={{
mt: 0.25,
fontWeight: 700,
letterSpacing: '-0.015em',
color: 'grey.800',
lineHeight: 1.15,
fontSize: { xs: '1.375rem', md: '1.5rem' },
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis'
}}
>
{value}
</Typography>
)}
{caption && (
<Typography variant="caption" sx={{ display: 'block', mt: 0.5, color: 'text.secondary' }}>
{caption}
</Typography>
)}
</Box>
{icon && (
<Avatar
variant="rounded"
sx={{ width: 42, height: 42, borderRadius: 2, bgcolor: `${color}14`, color, flexShrink: 0 }}
>
{icon}
</Avatar>
)}
</Stack>
</CardContent>
</Card>
);
}
StatCard.propTypes = {
title: PropTypes.node,
value: PropTypes.node,
icon: PropTypes.node,
color: PropTypes.string,
caption: PropTypes.node,
loading: PropTypes.bool
};