75 lines
2.0 KiB
TypeScript
75 lines
2.0 KiB
TypeScript
import { Grid } from '@/ui/Grid';
|
|
import { Icon } from '@/ui/Icon';
|
|
import { Stack } from '@/ui/Stack';
|
|
import { Text } from '@/ui/Text';
|
|
import { LucideIcon } from 'lucide-react';
|
|
|
|
interface BillingStatProps {
|
|
label: string;
|
|
value: string | number;
|
|
subValue?: string;
|
|
icon: LucideIcon;
|
|
variant?: 'default' | 'success' | 'warning' | 'danger' | 'info';
|
|
}
|
|
|
|
function BillingStat({ label, value, subValue, icon, variant = 'default' }: BillingStatProps) {
|
|
const colorMap = {
|
|
default: 'text-white',
|
|
success: 'text-performance-green',
|
|
warning: 'text-warning-amber',
|
|
danger: 'text-racing-red',
|
|
info: 'text-primary-blue',
|
|
};
|
|
|
|
const bgMap = {
|
|
default: 'bg-iron-gray/50',
|
|
success: 'bg-performance-green/10',
|
|
warning: 'bg-warning-amber/10',
|
|
danger: 'bg-racing-red/10',
|
|
info: 'bg-primary-blue/10',
|
|
};
|
|
|
|
return (
|
|
<Stack p={4} bg="bg-iron-gray/20" rounded="lg" border borderColor="border-charcoal-outline/50">
|
|
<Stack direction="row" align="center" gap={3} mb={2}>
|
|
<Stack p={2} rounded="md" bg={bgMap[variant]}>
|
|
<Icon icon={icon} size={4} color={colorMap[variant] as any} />
|
|
</Stack>
|
|
<Text size="xs" weight="medium" color="text-gray-500" uppercase letterSpacing="wider">
|
|
{label}
|
|
</Text>
|
|
</Stack>
|
|
<Stack>
|
|
<Text size="xl" weight="bold" color={colorMap[variant] as any}>
|
|
{value}
|
|
</Text>
|
|
{subValue && (
|
|
<Text size="xs" color="text-gray-500" block mt={0.5}>
|
|
{subValue}
|
|
</Text>
|
|
)}
|
|
</Stack>
|
|
</Stack>
|
|
);
|
|
}
|
|
|
|
interface BillingSummaryPanelProps {
|
|
stats: BillingStatProps[];
|
|
}
|
|
|
|
/**
|
|
* BillingSummaryPanel
|
|
*
|
|
* A semantic panel for displaying billing metrics.
|
|
* Dense, grid-based layout for financial data.
|
|
*/
|
|
export function BillingSummaryPanel({ stats }: BillingSummaryPanelProps) {
|
|
return (
|
|
<Grid cols={1} mdCols={2} lgCols={4} gap={4} mb={8}>
|
|
{stats.map((stat, index) => (
|
|
<BillingStat key={index} {...stat} />
|
|
))}
|
|
</Grid>
|
|
);
|
|
}
|