upd: tampilan
This commit is contained in:
96
src/frontend/components/SummaryCard.tsx
Normal file
96
src/frontend/components/SummaryCard.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { Card, Group, Text, ThemeIcon, Stack, Progress, Badge } from '@mantine/core'
|
||||
import { IconType } from 'react-icons'
|
||||
import { TbTrendingUp, TbTrendingDown } from 'react-icons/tb'
|
||||
|
||||
interface SummaryCardProps {
|
||||
title: string
|
||||
value: string | number
|
||||
icon: IconType
|
||||
color?: string
|
||||
trend?: {
|
||||
value: string
|
||||
positive: boolean
|
||||
}
|
||||
progress?: {
|
||||
value: number
|
||||
label: string
|
||||
}
|
||||
isError?: boolean
|
||||
}
|
||||
|
||||
export function SummaryCard({
|
||||
title,
|
||||
value,
|
||||
icon: Icon,
|
||||
color = 'brand-blue',
|
||||
trend,
|
||||
progress,
|
||||
isError
|
||||
}: SummaryCardProps) {
|
||||
return (
|
||||
<Card
|
||||
withBorder
|
||||
padding="xl"
|
||||
radius="2xl"
|
||||
className="glass"
|
||||
styles={(theme) => ({
|
||||
root: {
|
||||
backgroundColor: isError && Number(value) > 0 ? 'rgba(239, 68, 68, 0.05)' : 'rgba(30, 41, 59, 0.4)',
|
||||
borderColor: isError && Number(value) > 10 ? 'rgba(239, 68, 68, 0.3)' : 'rgba(255, 255, 255, 0.08)',
|
||||
transition: 'transform 0.2s ease',
|
||||
'&:hover': {
|
||||
transform: 'translateY(-4px)',
|
||||
}
|
||||
}
|
||||
})}
|
||||
>
|
||||
<Group justify="space-between" mb="md">
|
||||
<ThemeIcon
|
||||
size={48}
|
||||
radius="lg"
|
||||
variant="light"
|
||||
color={isError ? 'red' : color}
|
||||
>
|
||||
<Icon size={26} />
|
||||
</ThemeIcon>
|
||||
|
||||
{trend && (
|
||||
<Badge
|
||||
variant="light"
|
||||
color={trend.positive ? 'teal' : 'red'}
|
||||
leftSection={trend.positive ? <TbTrendingUp size={14} /> : <TbTrendingDown size={14} />}
|
||||
>
|
||||
{trend.value}
|
||||
</Badge>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<Stack gap={2}>
|
||||
<Text size="xs" fw={700} c="dimmed" style={{ letterSpacing: '0.05em' }}>
|
||||
{title.toUpperCase()}
|
||||
</Text>
|
||||
<Text size="2.4rem" fw={900} style={{ fontFamily: 'Outfit, sans-serif', letterSpacing: '-1px' }}>
|
||||
{value}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
{progress && (
|
||||
<Box mt="md">
|
||||
<Group justify="space-between" mb={4}>
|
||||
<Text size="xs" c="dimmed" fw={600}>{progress.label}</Text>
|
||||
<Text size="xs" fw={700}>{progress.value}%</Text>
|
||||
</Group>
|
||||
<Progress
|
||||
value={progress.value}
|
||||
color={color}
|
||||
size="sm"
|
||||
radius="xl"
|
||||
styles={{ section: { transition: 'width 1s ease' } }}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
import { Box } from '@mantine/core'
|
||||
Reference in New Issue
Block a user