import React from 'react'; import PropTypes from 'prop-types'; import { Card } from '@astryxdesign/core/Card'; import { Skeleton } from '@astryxdesign/core/Skeleton'; import { DT, STATUS } from 'themes/dt/tokens'; // ==============================|| STAT / KPI CARD ||============================== // // // Ultra-compact, dense, space-efficient enterprise KPI component. // Shared across Deliveries, Orders, Pricing, Tenants, Riders, Customers, Hubs, // Vehicles, Tripsheets, Exceptions, App Users, Reports and Dispatch. // // --------------------------------------------------------------------------- // ULTRA-COMPACT HORIZONTAL COMPOSITION (~48px target height) // --------------------------------------------------------------------------- // 1. Icon chip: 26px × 26px with 6px radius and subtle 7% tint (`${accent}12`). // Glyph size normalized to 14px. // 2. Value: 18px bold (`lineHeight: 1`, `fontVariantNumeric: 'tabular-nums'`). // 3. Label: 12px / 500 in secondary ink (`#64748b`), aligned horizontally on // the same baseline beside the value for maximum space efficiency and instant // (<1s) visual scanning. // 4. Tight elevation, flat white surface, 8px rounded corners, 7px 12px padding. // 5. Interactive/clickable hover support with smooth 150ms transition. Static // cards remain clean without hover distraction. // --------------------------------------------------------------------------- const MIN_HEIGHT = 48; const VARIANTS = { neutral: STATUS.muted, brand: DT.brand, blue: STATUS.info, green: STATUS.delivered, amber: STATUS.pending, red: STATUS.cancelled }; export default function StatCard({ title, value, icon, color, variant = 'brand', caption, loading = false, onClick, clickable, className = '', style = {} }) { const accent = color || VARIANTS[variant] || DT.brand; const isClickable = Boolean(onClick || clickable); return ( { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick(e); } } : undefined } style={{ position: 'relative', display: 'flex', alignItems: 'center', minHeight: MIN_HEIGHT, maxHeight: 56, padding: '7px 12px', background: DT.surface, border: `1px solid ${DT.borderSubtle}`, borderRadius: 8, boxShadow: '0 1px 2px rgba(15, 23, 42, 0.03)', cursor: isClickable ? 'pointer' : 'default', userSelect: isClickable ? 'none' : 'auto', boxSizing: 'border-box', overflow: 'hidden', width: '100%', ...style }} >
{icon && (
{icon}
)}
{loading ? ( ) : ( {value} )} {title}
{caption && ( {caption} )}
); } StatCard.propTypes = { title: PropTypes.node, value: PropTypes.node, icon: PropTypes.node, /** Raw accent hex. Takes precedence over `variant`. */ color: PropTypes.string, /** Semantic alias over the same palette, for call sites not importing STATUS. */ variant: PropTypes.oneOf(['neutral', 'brand', 'blue', 'green', 'amber', 'red']), caption: PropTypes.node, loading: PropTypes.bool, onClick: PropTypes.func, clickable: PropTypes.bool, className: PropTypes.string, style: PropTypes.object };