import dayjs from 'dayjs' import { ComponentProps, useState } from 'react' import { Bar, Cell, Legend, BarChart as RechartBarChart, Tooltip, XAxis, Label, YAxis, CartesianGrid, } from 'recharts' import { CHART_COLORS, DateTimeFormats } from 'components/ui/Charts/Charts.constants' import type { CategoricalChartState } from 'recharts/types/chart/types' import ChartHeader from './ChartHeader' import type { CommonChartProps, Datum } from './Charts.types' import { numberFormatter, useChartSize } from './Charts.utils' import NoDataPlaceholder from './NoDataPlaceholder' export interface BarChartProps extends CommonChartProps { yAxisKey: string xAxisKey: string customDateFormat?: string displayDateInUtc?: boolean onBarClick?: (datum: Datum, tooltipData?: CategoricalChartState) => void emptyStateMessage?: string showLegend?: boolean xAxisIsDate?: boolean XAxisProps?: ComponentProps YAxisProps?: ComponentProps showGrid?: boolean } const BarChart = ({ data, yAxisKey, xAxisKey, format, customDateFormat = DateTimeFormats.FULL, title, highlightedValue, highlightedLabel, displayDateInUtc, minimalHeader, valuePrecision, className = '', size = 'normal', emptyStateMessage, onBarClick, showLegend = false, xAxisIsDate = true, XAxisProps, YAxisProps, showGrid = false, }: BarChartProps) => { const { Container } = useChartSize(size) const [focusDataIndex, setFocusDataIndex] = useState(null) // Default props const _XAxisProps = XAxisProps || { interval: data.length - 2, angle: 0, tick: false, } const _YAxisProps = YAxisProps || { tickFormatter: (value) => numberFormatter(value, valuePrecision), tick: false, width: 0, } const day = (value: number | string) => (displayDateInUtc ? dayjs(value).utc() : dayjs(value)) function getHeaderLabel() { if (!xAxisIsDate) { if (!focusDataIndex) return highlightedLabel return data[focusDataIndex]?.[xAxisKey] } return ( (focusDataIndex !== null && data && data[focusDataIndex] !== undefined && day(data[focusDataIndex][xAxisKey]).format(customDateFormat)) || highlightedLabel ) } const resolvedHighlightedLabel = getHeaderLabel() const resolvedHighlightedValue = focusDataIndex !== null ? data[focusDataIndex]?.[yAxisKey] : highlightedValue if (data.length === 0) { return ( ) } return (
{ if (e.activeTooltipIndex !== focusDataIndex) { setFocusDataIndex(e.activeTooltipIndex) } }} onMouseLeave={() => setFocusDataIndex(null)} onClick={(tooltipData) => { // receives tooltip data https://github.com/recharts/recharts/blob/2a3405ff64a0c050d2cf94c36f0beef738d9e9c2/src/chart/generateCategoricalChart.tsx const datum = tooltipData?.activePayload?.[0]?.payload if (onBarClick) onBarClick(datum, tooltipData) }} > {showLegend && } {showGrid && } null} /> {data?.map((_entry: Datum, index: any) => ( ))} {data && (
{xAxisIsDate ? day(data[0][xAxisKey]).format(customDateFormat) : data[0][xAxisKey]} {xAxisIsDate ? day(data[data?.length - 1]?.[xAxisKey]).format(customDateFormat) : data[data?.length - 1]?.[xAxisKey]}
)}
) } export default BarChart