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 && (
-
)}