diff --git a/epictrack-api/src/api/schemas/response/work_response.py b/epictrack-api/src/api/schemas/response/work_response.py index 50356fd9c..b1db669ac 100644 --- a/epictrack-api/src/api/schemas/response/work_response.py +++ b/epictrack-api/src/api/schemas/response/work_response.py @@ -133,6 +133,7 @@ class WorkPhaseAdditionalInfoResponseSchema(Schema): total_number_of_days = fields.Number( metadata={"description": "Total number of days in the phase"}, required=True ) + current_milestone = fields.Str(metadata={"description": "Current milestone in the phase"}) next_milestone = fields.Str(metadata={"description": "Next milestone in the phase"}) milestone_progress = fields.Number(metadata={"description": "Milestone progress"}) is_last_phase = fields.Number(metadata={"description": "Indicate if this the last phase of the work"}) diff --git a/epictrack-api/src/api/services/work_phase.py b/epictrack-api/src/api/services/work_phase.py index 8ca7cb773..611e9409a 100644 --- a/epictrack-api/src/api/services/work_phase.py +++ b/epictrack-api/src/api/services/work_phase.py @@ -169,19 +169,29 @@ def _find_work_phase_status(cls, work_id, work_phase_id, work_phases): ), ) result_item["total_number_of_days"] = total_days - suspended_days - next_milestone_event = next( - (x for x in work_phase_events if x.actual_date is None), None - ) - if next_milestone_event: - result_item["next_milestone"] = next_milestone_event.name - result_item["milestone_progress"] = cls._calculate_milestone_progress( - work_phase_events - ) + + milestone_info = cls._get_milestone_information(work_phase_events) + result_item = {**result_item, **milestone_info} + days_left = cls._get_days_left(suspended_days, total_days, work_phase) result_item["days_left"] = days_left result.append(result_item) return result + @classmethod + def _get_milestone_information(cls, work_phase_events): + result = {} + + completed_milestone_events = [event for event in work_phase_events if event.actual_date] + result["current_milestone"] = completed_milestone_events[-1].name if completed_milestone_events else None + + remaining_milestone_events = [event for event in work_phase_events if event.actual_date is None] + result["next_milestone"] = remaining_milestone_events[0].name if remaining_milestone_events else None + + result["milestone_progress"] = cls._calculate_milestone_progress(work_phase_events) + + return result + @classmethod def _calculate_milestone_progress(cls, work_phase_events): total_number_of_milestones = len(work_phase_events) diff --git a/epictrack-web/src/components/workPlan/about/AboutContext.tsx b/epictrack-web/src/components/workPlan/about/AboutContext.tsx index 9d26d8d02..491675f34 100644 --- a/epictrack-web/src/components/workPlan/about/AboutContext.tsx +++ b/epictrack-web/src/components/workPlan/about/AboutContext.tsx @@ -1,14 +1,9 @@ -import { createContext } from "react"; import React from "react"; -import { useSearchParams } from "../../../hooks/SearchParams"; +import { createContext } from "react"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface AboutContextProps {} -interface StatusContainerRouteParams extends URLSearchParams { - work_id: string; -} - export const AboutContext = createContext({}); export const AboutProvider = ({ @@ -16,8 +11,5 @@ export const AboutProvider = ({ }: { children: JSX.Element | JSX.Element[]; }) => { - const query = useSearchParams(); - const workId = React.useMemo(() => query.get("work_id"), [query]); - return {children}; }; diff --git a/epictrack-web/src/components/workPlan/about/aboutDetails/WorkDetails.tsx b/epictrack-web/src/components/workPlan/about/aboutDetails/WorkDetails.tsx index f90714d82..205864025 100644 --- a/epictrack-web/src/components/workPlan/about/aboutDetails/WorkDetails.tsx +++ b/epictrack-web/src/components/workPlan/about/aboutDetails/WorkDetails.tsx @@ -1,5 +1,5 @@ -import { Box, Divider, Grid } from "@mui/material"; -import { useContext, useEffect, useState } from "react"; +import { Divider, Grid } from "@mui/material"; +import { useContext } from "react"; import { WorkplanContext } from "../../WorkPlanContext"; import { ETCaption1, ETCaption2, GrayBox } from "../../../shared"; import { Palette } from "../../../../styles/theme"; @@ -7,20 +7,11 @@ import dayjs from "dayjs"; import { MONTH_DAY_YEAR } from "../../../../constants/application-constant"; const WorkDetails = () => { - const [phaseInfo, setPhaseInfo] = useState({}); const { work, workPhases } = useContext(WorkplanContext); - const getNextPhaseInfo = () => { - workPhases.map((phase) => { - if (phase?.work_phase?.id === work?.current_work_phase_id) { - setPhaseInfo(phase); - } - }); - }; - - useEffect(() => { - getNextPhaseInfo(); - }, []); + const currentWorkPhase = workPhases?.find( + (phase) => phase.work_phase.id === work?.current_work_phase_id + ); return ( @@ -54,7 +45,7 @@ const WorkDetails = () => { - {work?.anticipated_decision_date || "-"} + {work?.anticipated_decision_date ?? "-"} @@ -67,12 +58,16 @@ const WorkDetails = () => { NEXT MILESTONE + - - + + {currentWorkPhase?.current_milestone ?? "-"} + + - {phaseInfo?.next_milestone} + {currentWorkPhase?.next_milestone ?? "-"} diff --git a/epictrack-web/src/models/work.ts b/epictrack-web/src/models/work.ts index 90d54ed14..c197e91bc 100644 --- a/epictrack-web/src/models/work.ts +++ b/epictrack-web/src/models/work.ts @@ -79,6 +79,7 @@ export interface WorkPhaseAdditionalInfo { work_phase: WorkPhase; total_number_of_days: number; next_milestone: string; + current_milestone: string; milestone_progress: number; days_left: number; is_last_phase: boolean;