import { fancyMinutes, useNumber } from '@/hooks/use-numer-formatter'; import { cn } from '@/utils/cn'; import AutoSizer from 'react-virtualized-auto-sizer'; import { Area, AreaChart, Tooltip } from 'recharts'; import { formatDate, timeAgo } from '@/utils/date'; import { getChartColor } from '@/utils/theme'; import { getPreviousMetric } from '@openpanel/common'; import { useEffect, useRef, useState } from 'react'; import { ChartTooltipContainer, ChartTooltipHeader, ChartTooltipItem, } from '../charts/chart-tooltip'; import { PreviousDiffIndicatorPure, getDiffIndicator, } from '../report-chart/common/previous-diff-indicator'; import { Skeleton } from '../skeleton'; import { Tooltiper } from '../ui/tooltip'; interface MetricCardProps { id: string; data: { current: number; previous?: number; date: string; }[]; metric: { current: number; previous?: number | null; }; unit?: '' | 'date' | 'timeAgo' | 'min' | '%' | 'currency'; label: string; onClick?: () => void; active?: boolean; inverted?: boolean; isLoading?: boolean; } export function OverviewMetricCard({ id, data, metric, unit, label, onClick, active, inverted = false, isLoading = false, }: MetricCardProps) { const [currentIndex, setCurrentIndex] = useState(null); const number = useNumber(); const { current, previous } = metric; const timer = useRef(null); useEffect(() => { if (timer.current) { clearTimeout(timer.current); } if (currentIndex) { timer.current = setTimeout(() => { setCurrentIndex(null); }, 1000); } return () => { if (timer.current) { clearTimeout(timer.current); } }; }, [currentIndex]); const renderValue = (value: number, unitClassName?: string, short = true) => { if (unit === 'date') { return <>{formatDate(new Date(value))}; } if (unit === 'timeAgo') { return <>{timeAgo(new Date(value))}; } if (unit === 'min') { return <>{fancyMinutes(value)}; } if (unit === 'currency') { // Revenue is stored in cents, convert to dollars return <>{number.currency(value / 100)}; } return ( <> {short ? number.short(value) : number.format(value)} {unit && {unit}} ); }; const graphColors = getDiffIndicator( inverted, getPreviousMetric(current, previous)?.state, '#6ee7b7', // green '#fda4af', // red '#93c5fd', // blue ); const renderTooltip = () => { if (currentIndex) { return ( {formatDate(new Date(data[currentIndex]?.date))}:{' '} {renderValue( data[currentIndex].current, 'ml-1 font-light text-xl', false, )} ); } return ( {label}:{' '} {renderValue(metric.current, 'ml-1 font-light text-xl', false)} ); }; return ( ); } export function OverviewMetricCardNumber({ label, value, enhancer, className, isLoading, }: { label: React.ReactNode; value: React.ReactNode; enhancer?: React.ReactNode; className?: string; isLoading?: boolean; }) { return (
{label}
{isLoading ? (
) : (
{value}
{enhancer}
)}
); }