diff --git a/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx b/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx index 1098adad9004..77010e448e14 100644 --- a/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx +++ b/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx @@ -15,6 +15,7 @@ import { FlagStats } from './FlagStats/FlagStats'; import { Widget } from './Widget/Widget'; import { FlagsProjectChart } from './FlagsProjectChart/FlagsProjectChart'; import { ProjectHealthChart } from './ProjectHealthChart/ProjectHealthChart'; +import { TimeToProductionChart } from './TimeToProductionChart/TimeToProductionChart'; const StyledGrid = styled(Box)(({ theme }) => ({ display: 'grid', @@ -138,6 +139,17 @@ export const ExecutiveDashboard: VFC = () => { } /> + + + ); diff --git a/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx b/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx index 176ea1086f0b..c7a3977d9b02 100644 --- a/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx +++ b/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx @@ -7,6 +7,7 @@ import { } from 'openapi'; import { LineChart } from '../LineChart/LineChart'; import { getRandomColor } from '../executive-dashboard-utils'; +import { useProjectChartData } from '../useProjectChartData'; interface IFlagsProjectChartProps { projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends']; @@ -15,38 +16,7 @@ interface IFlagsProjectChartProps { export const FlagsProjectChart: VFC = ({ projectFlagTrends, }) => { - const theme = useTheme(); - const data = useMemo(() => { - const groupedFlagTrends = projectFlagTrends.reduce< - Record - >((groups, item) => { - if (!groups[item.project]) { - groups[item.project] = []; - } - groups[item.project].push(item); - return groups; - }, {}); - - const datasets = Object.entries(groupedFlagTrends).map( - ([project, trends]) => { - const color = getRandomColor(); - return { - label: project, - data: trends.map((item) => item.total), - borderColor: color, - backgroundColor: color, - fill: true, - }; - }, - ); - - const objectKeys = Object.keys(groupedFlagTrends); - - return { - labels: groupedFlagTrends[objectKeys[0]].map((item) => item.date), - datasets, - }; - }, [theme, projectFlagTrends]); + const data = useProjectChartData(projectFlagTrends, 'total'); return ; }; diff --git a/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx b/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx index da5b0e0e6b6f..08acf7f21002 100644 --- a/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx +++ b/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx @@ -7,6 +7,7 @@ import { } from 'openapi'; import { LineChart } from '../LineChart/LineChart'; import { getRandomColor } from '../executive-dashboard-utils'; +import { useProjectChartData } from '../useProjectChartData'; interface IFlagsProjectChartProps { projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends']; @@ -15,39 +16,7 @@ interface IFlagsProjectChartProps { export const ProjectHealthChart: VFC = ({ projectFlagTrends, }) => { - const theme = useTheme(); - - const data = useMemo(() => { - const groupedFlagTrends = projectFlagTrends.reduce< - Record - >((groups, item) => { - if (!groups[item.project]) { - groups[item.project] = []; - } - groups[item.project].push(item); - return groups; - }, {}); - - const datasets = Object.entries(groupedFlagTrends).map( - ([project, trends]) => { - const color = getRandomColor(); - return { - label: project, - data: trends.map((item) => item.health || 0), - borderColor: color, - backgroundColor: color, - fill: true, - }; - }, - ); - - const objectKeys = Object.keys(groupedFlagTrends); - - return { - labels: groupedFlagTrends[objectKeys[0]].map((item) => item.date), - datasets, - }; - }, [theme, projectFlagTrends]); + const data = useProjectChartData(projectFlagTrends, 'health'); return ; }; diff --git a/frontend/src/component/executiveDashboard/TimeToProductionChart/TimeToProductionChart.tsx b/frontend/src/component/executiveDashboard/TimeToProductionChart/TimeToProductionChart.tsx new file mode 100644 index 000000000000..f1f33be090cd --- /dev/null +++ b/frontend/src/component/executiveDashboard/TimeToProductionChart/TimeToProductionChart.tsx @@ -0,0 +1,22 @@ +import { useMemo, type VFC } from 'react'; +import 'chartjs-adapter-date-fns'; +import { useTheme } from '@mui/material'; +import { + ExecutiveSummarySchema, + ExecutiveSummarySchemaProjectFlagTrendsItem, +} from 'openapi'; +import { LineChart } from '../LineChart/LineChart'; +import { getRandomColor } from '../executive-dashboard-utils'; +import { useProjectChartData } from '../useProjectChartData'; + +interface IFlagsProjectChartProps { + projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends']; +} + +export const TimeToProductionChart: VFC = ({ + projectFlagTrends, +}) => { + const data = useProjectChartData(projectFlagTrends, 'timeToProduction'); + + return ; +}; diff --git a/frontend/src/component/executiveDashboard/useProjectChartData.ts b/frontend/src/component/executiveDashboard/useProjectChartData.ts new file mode 100644 index 000000000000..15633c58b4f1 --- /dev/null +++ b/frontend/src/component/executiveDashboard/useProjectChartData.ts @@ -0,0 +1,55 @@ +import { useMemo } from 'react'; +import { + ExecutiveSummarySchema, + ExecutiveSummarySchemaProjectFlagTrendsItem, +} from '../../openapi'; +import { getRandomColor } from './executive-dashboard-utils'; +import { useTheme } from '@mui/material'; + +type ProjectFlagTrends = ExecutiveSummarySchema['projectFlagTrends']; + +export const useProjectChartData = ( + projectFlagTrends: ProjectFlagTrends, + field: 'timeToProduction' | 'total' | 'health', +) => { + const theme = useTheme(); + + const data = useMemo(() => { + const groupedFlagTrends = projectFlagTrends.reduce< + Record + >((groups, item) => { + if (!groups[item.project]) { + groups[item.project] = []; + } + groups[item.project].push(item); + return groups; + }, {}); + + const datasets = Object.entries(groupedFlagTrends).map( + ([project, trends]) => { + const color = getRandomColor(); + return { + label: project, + data: trends.map((item) => { + return item[field] || 0; + }), + borderColor: color, + backgroundColor: color, + fill: true, + }; + }, + ); + + const objectKeys = Object.keys(groupedFlagTrends); + + const firstElementTrends = groupedFlagTrends[objectKeys[0]] || []; + const firstElementsDates = firstElementTrends.map((item) => item.date); + + return { + labels: firstElementsDates, + datasets, + }; + }, [theme, projectFlagTrends]); + + return data; +};