import { useRechartDataModel } from '@/hooks/use-rechart-data-model'; import { useVisibleSeries } from '@/hooks/use-visible-series'; import { useTRPC } from '@/integrations/trpc/react'; import { pushModal } from '@/modals'; import type { IChartData } from '@/trpc/client'; import { cn } from '@/utils/cn'; import { getChartColor } from '@/utils/theme'; import { useQuery } from '@tanstack/react-query'; import { isSameDay, isSameHour, isSameMonth, isSameWeek } from 'date-fns'; import { last } from 'ramda'; import React, { useCallback } from 'react'; import { Area, CartesianGrid, ComposedChart, Customized, Legend, Line, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts'; import { useDashedStroke } from '@/hooks/use-dashed-stroke'; import { useXAxisProps, useYAxisProps } from '../common/axis'; import { SolidToDashedGradient } from '../common/linear-gradient'; import { ReportChartTooltip } from '../common/report-chart-tooltip'; import { ReportTable } from '../common/report-table'; import { SerieIcon } from '../common/serie-icon'; import { SerieName } from '../common/serie-name'; import { useReportChartContext } from '../context'; interface Props { data: IChartData; } export function Chart({ data }: Props) { const { report: { previous, interval, projectId, startDate, endDate, range, lineType, }, isEditMode, options: { hideXAxis, hideYAxis }, } = useReportChartContext(); const trpc = useTRPC(); const references = useQuery( trpc.reference.getChartReferences.queryOptions( { projectId, startDate, endDate, range, }, { staleTime: 1000 * 60 * 10, }, ), ); const { series, setVisibleSeries } = useVisibleSeries(data); const rechartData = useRechartDataModel(series); let dotIndex = undefined; if (range === 'today') { // Find closest index based on times dotIndex = rechartData.findIndex((item) => { return isSameHour(item.date, new Date()); }); } const lastSerieDataItem = last(series[0]?.data || [])?.date || new Date(); const useDashedLastLine = (() => { if (range === 'today') { return true; } if (interval === 'hour') { return isSameHour(lastSerieDataItem, new Date()); } if (interval === 'day') { return isSameDay(lastSerieDataItem, new Date()); } if (interval === 'month') { return isSameMonth(lastSerieDataItem, new Date()); } if (interval === 'week') { return isSameWeek(lastSerieDataItem, new Date()); } return false; })(); const CustomLegend = useCallback(() => { return (
{series.map((serie) => (
))}
); }, [series]); const yAxisProps = useYAxisProps({ hide: hideYAxis, }); const xAxisProps = useXAxisProps({ hide: hideXAxis, interval, }); const handleChartClick = useCallback((e: any) => { if (e?.activePayload?.[0]) { const clickedData = e.activePayload[0].payload; if (clickedData.date) { pushModal('AddReference', { datetime: new Date(clickedData.date).toISOString(), }); } } }, []); const { getStrokeDasharray, calcStrokeDasharray, handleAnimationEnd } = useDashedStroke({ dotIndex, }); return (
{references.data?.map((ref) => ( ))} } /> } /> {series.map((serie) => { const color = getChartColor(serie.index); return ( ); })} {series.map((serie) => { const color = getChartColor(serie.index); return ( ); })} {previous && series.map((serie) => { const color = getChartColor(serie.index); return ( ); })}
{isEditMode && ( )}
); }