Files
gridpilot.gg/apps/website/components/sponsors/BillingSummaryPanel.tsx
2026-01-18 23:24:30 +01:00

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>
);
}