diff --git a/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.test.ts b/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.test.ts index 744144b84ff..6948fa0fbaa 100644 --- a/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.test.ts +++ b/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.test.ts @@ -10,25 +10,39 @@ describe('useAvgTimeToProduction', () => { expect(result.current).toBe(0); }); - test('calculates result.current time to production correctly', () => { + test('calculates average time to production based on the latest date correctly', () => { const projectsData = { - project1: [{ timeToProduction: 10 }, { timeToProduction: 20 }], - project2: [{ timeToProduction: 15 }, { timeToProduction: 25 }], + project1: [ + { timeToProduction: 10, date: '2023-01-01' }, + { timeToProduction: 20, date: '2023-02-01' }, + ], + project2: [ + { timeToProduction: 15, date: '2023-01-15' }, + { timeToProduction: 25, date: '2023-02-15' }, + ], } as any; const { result } = renderHook(() => useAvgTimeToProduction(projectsData), ); - expect(result.current).toBe(17.5); + // Expect average of the latest timeToProductions (20 from project1 and 25 from project2) + expect(result.current).toBe(22.5); }); - test('ignores projects without time to production data', () => { + test('ignores projects without time to production data in their latest entries', () => { const projectsData = { - project1: [{ timeToProduction: 10 }, { timeToProduction: 20 }], - project2: [], + project1: [ + { timeToProduction: 10, date: '2023-01-01' }, + { timeToProduction: 20, date: '2023-02-01' }, + ], + project2: [ + { date: '2023-01-15' }, + { timeToProduction: 25, date: '2023-01-10' }, + ], } as any; const { result } = renderHook(() => useAvgTimeToProduction(projectsData), ); - expect(result.current).toBe(7.5); + // Since project2's latest entry doesn't have timeToProduction, only project1's latest is considered + expect(result.current).toBe(20); }); }); diff --git a/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.ts b/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.ts index b91f60d3068..8697d883fca 100644 --- a/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.ts +++ b/frontend/src/component/executiveDashboard/hooks/useAvgTimeToProduction.ts @@ -1,14 +1,20 @@ import { useMemo } from 'react'; -import type { ExecutiveSummarySchema } from 'openapi'; +import type { + ExecutiveSummarySchema, + ExecutiveSummarySchemaProjectFlagTrendsItem, +} from 'openapi'; import type { GroupedDataByProject } from './useGroupedProjectTrends'; +const validTrend = (trend: ExecutiveSummarySchemaProjectFlagTrendsItem) => + Boolean(trend) && Boolean(trend.timeToProduction); + export const useAvgTimeToProduction = ( projectsData: GroupedDataByProject< ExecutiveSummarySchema['projectFlagTrends'] >, ) => useMemo(() => { - const totalProjects = Object.keys(projectsData).length; + let totalProjects = Object.keys(projectsData).length; if (totalProjects === 0) { return 0; @@ -16,16 +22,22 @@ export const useAvgTimeToProduction = ( const totalAvgTimeToProduction = Object.entries(projectsData).reduce( (acc, [_, trends]) => { - const validTrends = trends.filter( - (trend) => trend.timeToProduction !== undefined, + const latestTrend = trends.reduce( + (latest, current) => + new Date(latest.date) < new Date(current.date) + ? current + : latest, + trends[0], ); - const avgTimeToProduction = - validTrends.reduce( - (sum, item) => sum + (item.timeToProduction || 0), - 0, - ) / (validTrends.length || 1); - return acc + (validTrends.length > 0 ? avgTimeToProduction : 0); + // If there's no valid latest trend, this project won't contribute to the average + if (!validTrend(latestTrend)) { + totalProjects--; + return acc; + } + + const timeToProduction = latestTrend.timeToProduction || 0; + return acc + timeToProduction; }, 0, );