diff --git a/front/src/applications/operationalStudies/views/v2/ScenarioV2.tsx b/front/src/applications/operationalStudies/views/v2/ScenarioV2.tsx index ee67f8c054e..e60c061bf9f 100644 --- a/front/src/applications/operationalStudies/views/v2/ScenarioV2.tsx +++ b/front/src/applications/operationalStudies/views/v2/ScenarioV2.tsx @@ -146,11 +146,10 @@ const ScenarioV2 = () => { } ); - // const { refetch: refetchConflicts } = - // osrdEditoastApi.endpoints.getV2TimetableByIdConflicts.useQuery( - // { id: timetable!.id, infraId: infraId! }, - // { skip: !timetable || !infraId } - // ); + const { data: conflicts } = osrdEditoastApi.endpoints.getV2TimetableByIdConflicts.useQuery( + { id: timetable?.id as number, infraId: infraId! }, + { skip: !timetable || !infraId } + ); useEffect(() => { if (timetable && infra?.state === 'CACHED' && timetable.train_ids.length > 0) { @@ -287,7 +286,6 @@ const ScenarioV2 = () => { setDisplayTrainScheduleManagement={setDisplayTrainScheduleManagement} setTrainResultsToFetch={setTrainResultsToFetch} infraState={infra.state} - // refetchConflicts={() => {}} /> )} {infra && ( @@ -297,7 +295,7 @@ const ScenarioV2 = () => { infraState={infra.state} trainIds={timetable.train_ids} selectedTrainId={selectedTrainId} - conflicts={[]} + conflicts={conflicts} setTrainResultsToFetch={setTrainResultsToFetch} /> )} diff --git a/front/src/modules/conflict/components/ConflictsListV2.tsx b/front/src/modules/conflict/components/ConflictsListV2.tsx new file mode 100644 index 00000000000..57f209ac47e --- /dev/null +++ b/front/src/modules/conflict/components/ConflictsListV2.tsx @@ -0,0 +1,113 @@ +import React from 'react'; + +import cx from 'classnames'; +import { useTranslation } from 'react-i18next'; +import { BsLightningFill } from 'react-icons/bs'; + +import type { ConflictV2 } from 'common/api/osrdEditoastApi'; +import type { TrainScheduleWithDetails } from 'modules/trainschedule/components/TimetableV2/types'; + +type ConflictTableProps = { + conflicts: ConflictV2[]; + expanded: boolean; + trainSchedulesDetails: TrainScheduleWithDetails[]; + toggleConflictsList: () => void; + onClick: (conflict: ConflictWithTrainNames) => void; +}; + +type ConflictWithTrainNames = ConflictV2 & { + train_names: string[]; +}; + +function addTrainNamesToConflicts( + conflicts: ConflictV2[], + trainSchedulesDetails: TrainScheduleWithDetails[] +): ConflictWithTrainNames[] { + const trainNameMap: { [id: number]: string } = {}; + + trainSchedulesDetails.forEach(({ id, trainName }) => { + trainNameMap[id] = trainName; + }); + + return conflicts.map((conflict) => ({ + ...conflict, + train_names: conflict.train_ids.map((id) => trainNameMap[id] || ''), + })); +} + +function string2time(sec: string) { + const secNum = parseInt(sec, 10); + return new Date(secNum * 1000).toISOString().substr(11, 8); +} + +function ConflictCard({ + conflict, + onClick, +}: { + conflict: ConflictWithTrainNames; + onClick: (conflict: ConflictWithTrainNames) => void; +}) { + const { t } = useTranslation(['operationalStudies/scenario']); + + return ( +
onClick(conflict)} role="button" tabIndex={0}> + +
+ {conflict.train_names.map((train_name, idx) => ( +
+ {train_name} +
+ ))} +
+
+

{t(`${conflict.conflict_type}`)}

+
+
+
{string2time(conflict.start_time)}
+
{string2time(conflict.end_time)}
+
+
+ ); +} + +export default function ConflictsList({ + conflicts, + expanded, + trainSchedulesDetails, + toggleConflictsList, + onClick, +}: ConflictTableProps) { + const { t } = useTranslation(['operationalStudies/scenario']); + const enrichedConflicts = addTrainNamesToConflicts(conflicts, trainSchedulesDetails); + + if (conflicts.length === 0) { + return null; + } + return ( +
+
+

+ {t('conflictsCount', { + count: conflicts.length, + })} +

+ +
+ +
+ {enrichedConflicts.map((conflict, index) => ( + + ))} +
+
+ ); +} diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/AddTrainScheduleV2Button.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/AddTrainScheduleV2Button.tsx index fb5c433b2c8..551ca9461c8 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/AddTrainScheduleV2Button.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/AddTrainScheduleV2Button.tsx @@ -21,7 +21,6 @@ import formatTrainSchedulePayload from './helpers/formatTrainSchedulePayload'; type SubmitConfAddTrainScheduleProps = { infraState?: InfraState; // refetchTimetable: () => void; - // refetchConflicts: () => void; setIsWorking: (isWorking: boolean) => void; // setTrainResultsToFetch: (trainScheduleIds?: number[]) => void; }; @@ -29,7 +28,6 @@ type SubmitConfAddTrainScheduleProps = { const AddTrainScheduleV2Button = ({ infraState, // refetchTimetable, - // refetchConflicts, setIsWorking, // setTrainResultsToFetch, }: SubmitConfAddTrainScheduleProps) => { @@ -87,7 +85,6 @@ const AddTrainScheduleV2Button = ({ setIsWorking(false); // setTrainResultsToFetch(newTrainIds); // refetchTimetable(); - // refetchConflicts(); } catch (e) { setIsWorking(false); dispatch(setFailure(castErrorToFailure(e))); diff --git a/front/src/modules/trainschedule/components/ManageTrainSchedule/TimetableManageTrainScheduleV2.tsx b/front/src/modules/trainschedule/components/ManageTrainSchedule/TimetableManageTrainScheduleV2.tsx index b88d0e852fc..6d3ce52526f 100644 --- a/front/src/modules/trainschedule/components/ManageTrainSchedule/TimetableManageTrainScheduleV2.tsx +++ b/front/src/modules/trainschedule/components/ManageTrainSchedule/TimetableManageTrainScheduleV2.tsx @@ -19,7 +19,6 @@ type TimetableManageTrainScheduleProps = { setTrainResultsToFetch: (trainScheduleIds?: number[]) => void; infraState?: InfraState; // refetchTimetable: () => void; - // refetchConflicts: () => void; }; const TimetableManageTrainScheduleV2 = ({ @@ -28,7 +27,6 @@ const TimetableManageTrainScheduleV2 = ({ setTrainResultsToFetch, infraState, // refetchTimetable, - // refetchConflicts, }: TimetableManageTrainScheduleProps) => { const { t } = useTranslation('operationalStudies/manageTrainSchedule'); const dispatch = useDispatch(); @@ -67,7 +65,6 @@ const TimetableManageTrainScheduleV2 = ({ infraState={infraState} // refetchTimetable={refetchTimetable} setIsWorking={setIsWorking} - // refetchConflicts={refetchConflicts} // setTrainResultsToFetch={setTrainResultsToFetch} /> )} diff --git a/front/src/modules/trainschedule/components/TimetableV2/TimetableV2.tsx b/front/src/modules/trainschedule/components/TimetableV2/TimetableV2.tsx index 55178a03487..56909dc63b7 100644 --- a/front/src/modules/trainschedule/components/TimetableV2/TimetableV2.tsx +++ b/front/src/modules/trainschedule/components/TimetableV2/TimetableV2.tsx @@ -7,9 +7,9 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { MANAGE_TRAIN_SCHEDULE_TYPES } from 'applications/operationalStudies/consts'; -import type { Conflict, InfraState } from 'common/api/osrdEditoastApi'; +import type { ConflictV2, InfraState } from 'common/api/osrdEditoastApi'; import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext'; -import ConflictsList from 'modules/conflict/components/ConflictsList'; +import ConflictsListV2 from 'modules/conflict/components/ConflictsListV2'; import { updateSelectedTrainId } from 'reducers/osrdsimulation/actions'; import { getTrainIdUsedForProjection } from 'reducers/osrdsimulation/selectors'; import { useAppDispatch } from 'store'; @@ -26,7 +26,7 @@ type TimetableV2Props = { infraState: InfraState; trainIds: number[]; selectedTrainId?: number; - conflicts?: Conflict[]; + conflicts?: ConflictV2[]; setTrainResultsToFetch: (trainScheduleIds?: number[]) => void; }; @@ -86,7 +86,7 @@ const TimetableV2 = ({ setSelectedTrainIds(currentSelectedTrainIds); }; - const handleConflictClick = (conflict: Conflict) => { + const handleConflictClick = (conflict: ConflictV2) => { if (conflict.train_ids.length > 0) { const firstTrainId = conflict.train_ids[0]; dispatch(updateSelectedTrainId(firstTrainId)); @@ -176,10 +176,11 @@ const TimetableV2 = ({ )} {conflicts && ( - )}