Skip to content

Commit

Permalink
front: integrate api call and refacto component
Browse files Browse the repository at this point in the history
Signed-off-by: Achraf Mohyeddine <[email protected]>
  • Loading branch information
achrafmohye committed Oct 30, 2024
1 parent 7bb6d4f commit 2894828
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 130 deletions.
140 changes: 27 additions & 113 deletions front/src/applications/stdcm/components/StdcmResults/StdcmResults.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo, useState, useEffect } from 'react';
import { useMemo, useState } from 'react';

import { Button } from '@osrd-project/ui-core';
import { PDFDownloadLink } from '@react-pdf/renderer';
Expand All @@ -7,15 +7,14 @@ import { useSelector } from 'react-redux';

import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types';
import { STDCM_TRAIN_ID } from 'applications/stdcm/consts';
import useConflictsMessages from 'applications/stdcm/hooks/useConflicts';
import useProjectedTrainsForStdcm from 'applications/stdcm/hooks/useProjectedTrainsForStdcm';
import type { StdcmSimulation } from 'applications/stdcm/types';
import { processConflicts } from 'applications/stdcm/utils/fomatConflicts';
import {
generateCodeNumber,
getOperationalPointsWithTimes,
} from 'applications/stdcm/utils/formatSimulationReportSheet';
import conflictData from 'applications/stdcmV2/components/StdcmResults/conflicts.json';
import { osrdEditoastApi, type Conflict, type TrackRange } from 'common/api/osrdEditoastApi';
import { osrdEditoastApi, type TrackRange } from 'common/api/osrdEditoastApi';
import { useOsrdConfSelectors } from 'common/osrdContext';
import i18n from 'i18n';
import ManchetteWithSpaceTimeChartWrapper from 'modules/simulationResult/components/ManchetteWithSpaceTimeChart/ManchetteWithSpaceTimeChart';
Expand Down Expand Up @@ -74,19 +73,27 @@ const StcdmResults = ({
const [mapCanvas, setMapCanvas] = useState<string>();
const [speedSpaceChartContainerHeight, setSpeedSpaceChartContainerHeight] =
useState(SPEED_SPACE_CHART_HEIGHT);
const [trackConflicts, setTrackConflicts] = useState<string[]>([]);
const [workConflicts, setWorkConflicts] = useState<string[]>([]);

const selectedSimulation = simulationsList[selectedSimulationIndex];
const spaceTimeData = useProjectedTrainsForStdcm(selectedSimulation.outputs?.results);
const hasConflicts = (selectedSimulation?.conflicts?.length ?? 0) > 0;
const { trackConflicts, workConflicts } = useConflictsMessages(
t,
selectedSimulation?.conflicts,
pathProperties
);

const spaceTimeData = useProjectedTrainsForStdcm(selectedSimulation?.outputs?.results);
const speedSpaceChartData = selectedSimulation?.outputs?.speedSpaceChartData;

const simulationReportSheetNumber = generateCodeNumber();

const isSelectedSimulationRetained = selectedSimulationIndex === retainedSimulationIndex;

const speedChartStyle = {
height: `${speedSpaceChartContainerHeight + HANDLE_TAB_RESIZE_HEIGHT}px`,
};

const operationalPointsList = useMemo(() => {
if (!selectedSimulation || !selectedSimulation.outputs) {
if (!selectedSimulation?.outputs) {
return [];
}

Expand All @@ -97,97 +104,6 @@ const StcdmResults = ({
);
}, [selectedSimulation]);

useEffect(() => {
if (!pathProperties) return;
const generateConflictMessages = () => {
const processedConflictsData = processConflicts(
conflictData?.conflicts as Conflict[],
pathProperties
);

// condition to be reconsider before merging
const trackConflictsData = processedConflictsData.filter(
(conflict) => conflict.conflictType === 'Spacing'
);
// condition to be reconsider before merging
const workConflictsData = processedConflictsData.filter(
(conflict) => conflict.conflictType !== 'Spacing'
);

const trackMessages = [];
trackConflictsData.slice(0, 2).forEach((conflict) => {
const { waypointBefore, waypointAfter, startDate, endDate, startTime, endTime } = conflict;

if (startDate === endDate) {
trackMessages.push(
t('trackConflictSameDay', {
waypointBefore,
waypointAfter,
startTime,
endTime,
startDate,
})
);
} else {
trackMessages.push(
t('trackConflict', {
waypointBefore,
waypointAfter,
startDate,
endDate,
startTime,
endTime,
})
);
}
});

const remainingTrackConflicts = trackConflictsData.length - 2;
if (remainingTrackConflicts > 0) {
trackMessages.push(t('remainingTrackConflicts', { remainingTrackConflicts }));
}

const workMessages = [];
workConflictsData.slice(0, 2).forEach((conflict) => {
const { waypointBefore, waypointAfter, startDate, endDate, startTime, endTime } = conflict;

if (startDate === endDate) {
workMessages.push(
t('workConflictSameDay', {
waypointBefore,
waypointAfter,
startDate,
startTime,
endTime,
})
);
} else {
workMessages.push(
t('workConflict', {
waypointBefore,
waypointAfter,
startDate,
startTime,
endDate,
endTime,
})
);
}
});

const remainingWorkConflicts = workConflictsData.length - 2;
if (remainingWorkConflicts > 0) {
workMessages.push(t('remainingWorkConflicts', { remainingWorkConflicts }));
}

// Update the state with generated messages
setTrackConflicts(trackMessages);
setWorkConflicts(workMessages);
};

generateConflictMessages();
}, [t, pathProperties]);

return (
<>
<StdcmSimulationNavigator
Expand All @@ -199,7 +115,7 @@ const StcdmResults = ({
retainedSimulationIndex={retainedSimulationIndex}
/>
<div className="simulation-results">
{selectedSimulation.outputs ? (
{selectedSimulation?.outputs && !hasConflicts ? (
<div className="results-and-sheet">
<StcdmResultsTable
stdcmData={selectedSimulation.outputs.results}
Expand Down Expand Up @@ -272,15 +188,18 @@ const StcdmResults = ({
isReadOnly
hideAttribution
showStdcmAssets
isFeasible={conflictData.status !== 'conflicts'}
isFeasible={!hasConflicts}
setMapCanvas={setMapCanvas}
pathGeometry={selectedSimulation.outputs?.pathProperties.geometry}
simulationPathSteps={selectedSimulation.outputs?.results.simulationPathSteps}
pathGeometry={
hasConflicts
? pathProperties?.geometry
: selectedSimulation?.outputs?.pathProperties?.geometry
}
simulationPathSteps={selectedSimulation?.outputs?.results?.simulationPathSteps}
/>
</div>
</div>
{/* TODO: Replace this part with the spaceTimeChartWithManchette component once it's merged (ui-manchette #504) */}
{isDebugMode && (
{isDebugMode && selectedSimulation?.outputs && !hasConflicts && (
<>
{spaceTimeData &&
spaceTimeData.length > 0 &&
Expand All @@ -304,13 +223,8 @@ const StcdmResults = ({
)}

<div className="osrd-simulation-container my-2 speedspacechart-container">
<div
className="chart-container"
style={{
height: `${speedSpaceChartContainerHeight + HANDLE_TAB_RESIZE_HEIGHT}px`,
}}
>
{selectedSimulation.outputs && speedSpaceChartData && (
<div className="chart-container" style={speedChartStyle}>
{speedSpaceChartData && (
<SpeedSpaceChartContainer
trainSimulation={selectedSimulation.outputs.results.simulation}
selectedTrainPowerRestrictions={speedSpaceChartData.formattedPowerRestrictions}
Expand Down
108 changes: 108 additions & 0 deletions front/src/applications/stdcm/hooks/useConflicts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { useEffect, useState } from 'react';

import type { TFunction } from 'i18next';

import type { ManageTrainSchedulePathProperties } from 'applications/operationalStudies/types';
import { processConflicts } from 'applications/stdcm/utils/fomatConflicts';
import type { Conflict } from 'common/api/osrdEditoastApi';

const useConflictsMessages = (
t: TFunction,
conflictData?: Conflict[],
pathProperties?: ManageTrainSchedulePathProperties
) => {
const [trackConflicts, setTrackConflicts] = useState<string[]>([]);
const [workConflicts, setWorkConflicts] = useState<string[]>([]);

useEffect(() => {
if (!pathProperties || !conflictData) return;

const generateConflictMessages = () => {
const processedConflictsData = processConflicts(conflictData, pathProperties);

const trackConflictsData = processedConflictsData.filter(
(conflict) => conflict.conflictType === 'Spacing'
);

const workConflictsData = processedConflictsData.filter(
(conflict) => conflict.conflictType !== 'Spacing'
);

const trackMessages: string[] = [];
trackConflictsData.slice(0, 2).forEach((conflict) => {
const { waypointBefore, waypointAfter, startDate, endDate, startTime, endTime } = conflict;

if (startDate === endDate) {
trackMessages.push(
t('trackConflictSameDay', {
waypointBefore,
waypointAfter,
startTime,
endTime,
startDate,
})
);
} else {
trackMessages.push(
t('trackConflict', {
waypointBefore,
waypointAfter,
startDate,
endDate,
startTime,
endTime,
})
);
}
});

const remainingTrackConflicts = trackConflictsData.length - 2;
if (remainingTrackConflicts > 0) {
trackMessages.push(t('remainingTrackConflicts', { remainingTrackConflicts }));
}

const workMessages: string[] = [];
workConflictsData.slice(0, 2).forEach((conflict) => {
const { waypointBefore, waypointAfter, startDate, endDate, startTime, endTime } = conflict;

if (startDate === endDate) {
workMessages.push(
t('workConflictSameDay', {
waypointBefore,
waypointAfter,
startDate,
startTime,
endTime,
})
);
} else {
workMessages.push(
t('workConflict', {
waypointBefore,
waypointAfter,
startDate,
startTime,
endDate,
endTime,
})
);
}
});

const remainingWorkConflicts = workConflictsData.length - 2;
if (remainingWorkConflicts > 0) {
workMessages.push(t('remainingWorkConflicts', { remainingWorkConflicts }));
}

// Update the state with generated messages
setTrackConflicts(trackMessages);
setWorkConflicts(workMessages);
};

generateConflictMessages();
}, [t, pathProperties, conflictData]);

return { trackConflicts, workConflicts };
};

export default useConflictsMessages;
19 changes: 12 additions & 7 deletions front/src/applications/stdcm/hooks/useStdcm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { ManageTrainSchedulePathProperties } from 'applications/operational
import { STDCM_REQUEST_STATUS, STDCM_TRAIN_ID } from 'applications/stdcm/consts';
import type { StdcmRequestStatus, StdcmSuccessResponse } from 'applications/stdcm/types';
import { osrdEditoastApi } from 'common/api/osrdEditoastApi';
import type { TrainScheduleResult } from 'common/api/osrdEditoastApi';
import type { Conflict, TrainScheduleResult } from 'common/api/osrdEditoastApi';
import { useOsrdConfSelectors } from 'common/osrdContext';
import { useStoreDataForSpeedLimitByTagSelector } from 'common/SpeedLimitByTagSelector/useStoreDataForSpeedLimitByTagSelector';
import { setFailure } from 'reducers/main';
Expand All @@ -32,12 +32,12 @@ const useStdcm = ({
showFailureNotification = true,
}: { showFailureNotification?: boolean } = {}) => {
const [stdcmTrainResult, setStdcmTrainResult] = useState<TrainScheduleResult>();
const [stdcmTrainConflicts, setStdcmTrainConflicts] = useState<Conflict[]>();
const [stdcmResponse, setStdcmResponse] = useState<StdcmSuccessResponse>();
const [currentStdcmRequestStatus, setCurrentStdcmRequestStatus] = useState<StdcmRequestStatus>(
STDCM_REQUEST_STATUS.idle
);
const [pathProperties, setPathProperties] = useState<ManageTrainSchedulePathProperties>();
const [isStdcmResultsEmpty, setIsStdcmResultsEmpty] = useState(false);

const dispatch = useAppDispatch();
const { t } = useTranslation(['translation', 'stdcm']);
Expand Down Expand Up @@ -70,14 +70,15 @@ const useStdcm = ({

const launchStdcmRequest = async () => {
setCurrentStdcmRequestStatus(STDCM_REQUEST_STATUS.pending);
setIsStdcmResultsEmpty(false);
setStdcmResponse(undefined);
setStdcmTrainConflicts(undefined);

const validConfig = checkStdcmConf(dispatch, t, osrdconf as OsrdStdcmConfState);
if (validConfig) {
const payload = formatStdcmPayload(validConfig);
try {
const response = await postTimetableByIdStdcm(payload).unwrap();

if (
response.status === 'success' &&
response.simulation.status === 'success' &&
Expand All @@ -104,9 +105,10 @@ const useStdcm = ({
};
setStdcmTrainResult(stdcmTrain);
dispatch(updateSelectedTrainId(STDCM_TRAIN_ID));
} else if (response.status === 'conflicts') {
setStdcmTrainConflicts(response.conflicts); // Set conflicts
setCurrentStdcmRequestStatus(STDCM_REQUEST_STATUS.success); // Conflicts but still success in this case
} else {
// When the back-end send back result with status 'path_not_found' we consider that the result is empty
setIsStdcmResultsEmpty(response.status === 'path_not_found');
setCurrentStdcmRequestStatus(STDCM_REQUEST_STATUS.rejected);
triggerShowFailureNotification({
name: t('stdcm:stdcmErrors.requestFailed'),
Expand All @@ -116,7 +118,10 @@ const useStdcm = ({
} catch (e) {
setCurrentStdcmRequestStatus(STDCM_REQUEST_STATUS.rejected);
triggerShowFailureNotification(
castErrorToFailure(e, { name: t('stdcm:stdcmErrors.requestFailed') })
castErrorToFailure(e, {
name: t('stdcm:stdcmErrors.requestFailed'),
message: t('translation:common.error'),
})
);
}
} else {
Expand Down Expand Up @@ -145,7 +150,7 @@ const useStdcm = ({
isPending,
isSuccessful,
isRejected,
isStdcmResultsEmpty,
stdcmTrainConflicts,
};
};

Expand Down
Loading

0 comments on commit 2894828

Please sign in to comment.