import 'chartjs-adapter-date-fns'; import { type FC, useMemo } from 'react'; import type { InstanceInsightsSchema } from 'openapi'; import { useProjectChartData } from 'component/insights/hooks/useProjectChartData'; import { fillGradientPrimary, LineChart, NotEnoughData, } from 'component/insights/components/LineChart/LineChart'; import { useTheme } from '@mui/material'; import type { GroupedDataByProject } from 'component/insights/hooks/useGroupedProjectTrends'; import { usePlaceholderData } from 'component/insights/hooks/usePlaceholderData'; interface ICreationArchiveChartProps { creationArchiveTrends: GroupedDataByProject< InstanceInsightsSchema['creationArchiveTrends'] >; isAggregate?: boolean; isLoading?: boolean; } type WeekData = { archivedFlags: number; totalCreatedFlags: number; week: string; date?: string; }; type RawWeekData = { archivedFlags: number; createdFlags: Record; week: string; date: string; }; export const CreationArchiveChart: FC = ({ creationArchiveTrends, isAggregate, isLoading, }) => { const creationArchiveData = useProjectChartData(creationArchiveTrends); const theme = useTheme(); const placeholderData = usePlaceholderData(); const aggregateHealthData = useMemo(() => { const labels: string[] = Array.from( new Set( creationArchiveData.datasets.flatMap((d) => d.data.map((item) => item.week), ), ), ); const weeks: WeekData[] = labels .map((label) => { return creationArchiveData.datasets .map((d) => d.data.find((item) => item.week === label)) .reduce( (acc: WeekData, item: RawWeekData) => { if (item) { acc.archivedFlags += item.archivedFlags || 0; const createdFlagsSum = item.createdFlags ? Object.values(item.createdFlags).reduce( (sum: number, count: number) => sum + count, 0, ) : 0; acc.totalCreatedFlags += createdFlagsSum; } if (!acc.date) { acc.date = item?.date; } return acc; }, { archivedFlags: 0, totalCreatedFlags: 0, week: label, } as WeekData, ); }) .sort((a, b) => (a.week > b.week ? 1 : -1)); return { datasets: [ { label: 'Number of created flags', data: weeks, borderColor: theme.palette.primary.light, backgroundColor: fillGradientPrimary, fill: true, order: 3, }, ], }; }, [creationArchiveData, theme]); const aggregateOrProjectData = isAggregate ? aggregateHealthData : creationArchiveData; const notEnoughData = useMemo( () => !isLoading && !creationArchiveData.datasets.some((d) => d.data.length > 1), [creationArchiveData, isLoading], ); const data = notEnoughData || isLoading ? placeholderData : aggregateOrProjectData; return ( : isLoading} /> ); };