diff options
Diffstat (limited to 'src/components/metrics/MetricCard.tsx')
| -rw-r--r-- | src/components/metrics/MetricCard.tsx | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/components/metrics/MetricCard.tsx b/src/components/metrics/MetricCard.tsx new file mode 100644 index 0000000..d15bcf1 --- /dev/null +++ b/src/components/metrics/MetricCard.tsx @@ -0,0 +1,56 @@ +import { useSpring } from '@react-spring/web'; +import { Column, Text } from '@umami/react-zen'; +import { AnimatedDiv } from '@/components/common/AnimatedDiv'; +import { ChangeLabel } from '@/components/metrics/ChangeLabel'; +import { formatNumber } from '@/lib/format'; + +export interface MetricCardProps { + value: number; + previousValue?: number; + change?: number; + label?: string; + reverseColors?: boolean; + formatValue?: (n: any) => string; + showLabel?: boolean; + showChange?: boolean; +} + +export const MetricCard = ({ + value = 0, + change = 0, + label, + reverseColors = false, + formatValue = formatNumber, + showLabel = true, + showChange = false, +}: MetricCardProps) => { + const diff = value - change; + const pct = ((value - diff) / diff) * 100; + const props = useSpring({ x: Number(value) || 0, from: { x: 0 } }); + const changeProps = useSpring({ x: Number(pct) || 0, from: { x: 0 } }); + + return ( + <Column + justifyContent="center" + paddingX="6" + paddingY="4" + borderRadius="3" + backgroundColor + border + > + {showLabel && ( + <Text weight="bold" wrap="nowrap"> + {label} + </Text> + )} + <Text size="8" weight="bold" wrap="nowrap"> + <AnimatedDiv title={value?.toString()}>{props?.x?.to(x => formatValue(x))}</AnimatedDiv> + </Text> + {showChange && ( + <ChangeLabel value={change} title={formatValue(change)} reverseColors={reverseColors}> + <AnimatedDiv>{changeProps?.x?.to(x => `${Math.abs(~~x)}%`)}</AnimatedDiv> + </ChangeLabel> + )} + </Column> + ); +}; |