mirror of
https://github.com/supabase/supabase.git
synced 2026-06-16 02:26:42 +08:00
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
115 lines
3.6 KiB
TypeScript
115 lines
3.6 KiB
TypeScript
import dayjs from 'dayjs'
|
|
import {
|
|
Bar,
|
|
CartesianGrid,
|
|
Cell,
|
|
ComposedChart,
|
|
ResponsiveContainer,
|
|
Tooltip,
|
|
XAxis,
|
|
YAxis,
|
|
} from 'recharts'
|
|
import { cn } from 'ui'
|
|
|
|
import { Attribute, COLOR_MAP } from './Usage.constants'
|
|
import { MultiAttributeTooltipContent, SingleAttributeTooltipContent } from './UsageChartTooltips'
|
|
import { DataPoint } from '@/data/analytics/constants'
|
|
|
|
// [Joshen] This BarChart is specifically for usage, hence not a reusable component, and not
|
|
// replacing the existing BarChart in ui/Charts
|
|
|
|
export interface UsageBarChartProps {
|
|
data: DataPoint[]
|
|
name: string // Used within the tooltip
|
|
attributes: Attribute[]
|
|
unit: 'bytes' | 'absolute' | 'percentage' | 'hours' | 'gigabytes'
|
|
yLimit?: number
|
|
yMin?: number
|
|
yLeftMargin?: number
|
|
yFormatter?: (value: number | string) => string
|
|
tooltipFormatter?: (value: number | string) => string
|
|
}
|
|
|
|
const UsageBarChart = ({
|
|
data,
|
|
name,
|
|
attributes,
|
|
unit,
|
|
yLimit,
|
|
yLeftMargin = 10,
|
|
yFormatter,
|
|
yMin,
|
|
tooltipFormatter,
|
|
}: UsageBarChartProps) => {
|
|
const yDomain = [yMin ?? 0, Math.max(yMin ?? 0, yLimit ?? 0)]
|
|
|
|
return (
|
|
<div className="w-full h-[200px]">
|
|
<ResponsiveContainer width="100%" height={200}>
|
|
<ComposedChart data={data} margin={{ top: 0, right: 0, left: yLeftMargin, bottom: 0 }}>
|
|
<CartesianGrid
|
|
vertical={false}
|
|
strokeDasharray="3 3"
|
|
className="stroke-border-stronger"
|
|
/>
|
|
<XAxis dataKey="periodStartFormatted" />
|
|
<YAxis
|
|
width={40}
|
|
axisLine={false}
|
|
tickLine={{ stroke: 'none' }}
|
|
domain={yDomain}
|
|
tickFormatter={yFormatter}
|
|
/>
|
|
<Tooltip
|
|
content={(props) => {
|
|
const { active, payload } = props
|
|
if (active && payload && payload.length) {
|
|
const dataPeriod = dayjs(payload[0].payload.period_start)
|
|
const isAfterToday = dataPeriod.startOf('day').isAfter(dayjs().startOf('day'))
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'border bg-surface-100 rounded-md px-2 py-2',
|
|
attributes.length > 1 && !isAfterToday ? 'w-[250px]' : 'w-[170px]'
|
|
)}
|
|
>
|
|
{attributes.length > 1 ? (
|
|
<MultiAttributeTooltipContent
|
|
attributes={attributes}
|
|
values={payload}
|
|
isAfterToday={isAfterToday}
|
|
tooltipFormatter={tooltipFormatter}
|
|
unit={unit}
|
|
/>
|
|
) : (
|
|
<SingleAttributeTooltipContent
|
|
name={name}
|
|
unit={unit}
|
|
value={payload[0].value}
|
|
tooltipFormatter={tooltipFormatter}
|
|
isAfterToday={isAfterToday}
|
|
/>
|
|
)}
|
|
<p className="text-xs text-foreground-light mt-1">
|
|
{dataPeriod.format('DD MMM YYYY')}
|
|
</p>
|
|
</div>
|
|
)
|
|
} else return null
|
|
}}
|
|
/>
|
|
{attributes?.map((attr) => (
|
|
<Bar key={attr.key} dataKey={attr.key} stackId="a">
|
|
{data.map((entry) => {
|
|
return <Cell key={`${entry.period_start}`} className={COLOR_MAP[attr.color].bar} />
|
|
})}
|
|
</Bar>
|
|
))}
|
|
</ComposedChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default UsageBarChart
|