diff --git a/front/src/applications/stdcm/components/StdcmForm/StdcmInputVia.tsx b/front/src/applications/stdcm/components/StdcmForm/StdcmInputVia.tsx deleted file mode 100644 index 244dd723622..00000000000 --- a/front/src/applications/stdcm/components/StdcmForm/StdcmInputVia.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { useMemo, useEffect, useState } from 'react'; - -import { Input } from '@osrd-project/ui-core'; -import { debounce } from 'lodash'; -import { useTranslation } from 'react-i18next'; - -import { StdcmStopTypes } from '../../types'; - -type StdcmInputViaProps = { - stopType: StdcmStopTypes; - stopDuration?: number; - updatePathStepStopTime: (stopTime: string) => void; -}; - -const StdcmInputVia = ({ stopType, stopDuration, updatePathStepStopTime }: StdcmInputViaProps) => { - const { t } = useTranslation('stdcm'); - - const [pathStepStopTime, setPathStepStopTime] = useState(''); - - const stopWarning = stopType === StdcmStopTypes.DRIVER_SWITCH && stopDuration && stopDuration < 3; - - const debounceUpdatePathStepStopTime = useMemo( - () => debounce((value) => updatePathStepStopTime(value), 300), - [] - ); - - useEffect(() => { - setPathStepStopTime(stopDuration !== undefined ? `${stopDuration}` : ''); - }, [stopDuration]); - - return ( - stopType !== StdcmStopTypes.PASSAGE_TIME && ( -
- { - // TODO: Find a better way to prevent user from entering decimal values - const value = e.target.value.replace(/[\D.,]/g, ''); - setPathStepStopTime(value); - debounceUpdatePathStepStopTime(value); - }} - value={pathStepStopTime} - trailingContent="minutes" - statusWithMessage={ - stopWarning - ? { - status: 'warning', - message: t('trainPath.warningMinStopTime'), - } - : undefined - } - /> -
- ) - ); -}; - -export default StdcmInputVia; diff --git a/front/src/applications/stdcm/components/StdcmForm/StdcmVias.tsx b/front/src/applications/stdcm/components/StdcmForm/StdcmVias.tsx index e2cba5798b8..2094450d3e2 100644 --- a/front/src/applications/stdcm/components/StdcmForm/StdcmVias.tsx +++ b/front/src/applications/stdcm/components/StdcmForm/StdcmVias.tsx @@ -13,9 +13,9 @@ import { useAppDispatch } from 'store'; import StdcmCard from './StdcmCard'; import StdcmDefaultCard from './StdcmDefaultCard'; -import StdcmInputVia from './StdcmInputVia'; import StdcmOperationalPoint from './StdcmOperationalPoint'; import StdcmStopType from './StdcmStopType'; +import StopDurationInput from './StopDurationInput'; import { StdcmStopTypes } from '../../types'; import type { StdcmConfigCardProps } from '../../types'; @@ -84,16 +84,6 @@ const StdcmVias = ({ disabled = false }: StdcmConfigCardProps) => { }; }, [newIntermediateOpIndex]); - const updateStopDuration = (stopTime: string, pathStep: StdcmPathStep) => { - const stopFor = stopTime ? Number(stopTime) : undefined; - dispatch( - updateStdcmPathStep({ - id: pathStep.id, - updates: { stopFor }, - }) - ); - }; - const deleteViaOnClick = (pathStepId: string) => { dispatch(deleteStdcmVia(pathStepId)); }; @@ -147,11 +137,9 @@ const StdcmVias = ({ disabled = false }: StdcmConfigCardProps) => { stopTypes={pathStep.stopType} updatePathStepStopType={(newStopType) => updateStopType(newStopType, pathStep)} /> - updateStopDuration(e, pathStep)} - /> + {pathStep.stopType !== StdcmStopTypes.PASSAGE_TIME && ( + + )} ); diff --git a/front/src/applications/stdcm/components/StdcmForm/StopDurationInput.tsx b/front/src/applications/stdcm/components/StdcmForm/StopDurationInput.tsx new file mode 100644 index 00000000000..6986cf9d93e --- /dev/null +++ b/front/src/applications/stdcm/components/StdcmForm/StopDurationInput.tsx @@ -0,0 +1,78 @@ +import { useMemo, useEffect, useState } from 'react'; + +import { Input } from '@osrd-project/ui-core'; +import type { Status } from '@osrd-project/ui-core/dist/components/inputs/StatusMessage'; +import { useTranslation } from 'react-i18next'; + +import { useOsrdConfActions } from 'common/osrdContext'; +import type { StdcmConfSliceActions } from 'reducers/osrdconf/stdcmConf'; +import type { StdcmPathStep } from 'reducers/osrdconf/types'; +import { useAppDispatch } from 'store'; +import { useDebounce } from 'utils/helpers'; +import { parseNumber } from 'utils/strings'; + +import { StdcmStopTypes } from '../../types'; + +type StopDurationInputProps = { + pathStep: Extract; +}; + +const StopDurationInput = ({ pathStep }: StopDurationInputProps) => { + const dispatch = useAppDispatch(); + const { t } = useTranslation('stdcm'); + + const { updateStdcmPathStep } = useOsrdConfActions() as StdcmConfSliceActions; + + const [stopDuration, setStopDuration] = useState( + pathStep.stopFor !== undefined ? `${pathStep.stopFor}` : '' + ); + const debouncedStopDuration = useDebounce(stopDuration, 300); + + const stopWarning = useMemo( + () => + pathStep.stopType === StdcmStopTypes.DRIVER_SWITCH && + pathStep.stopFor !== undefined && + pathStep.stopFor < 3 + ? { + status: 'warning' as Status, + message: t('trainPath.warningMinStopTime'), + } + : undefined, + [pathStep.stopType, pathStep.stopFor] + ); + + useEffect(() => { + setStopDuration(pathStep.stopFor !== undefined ? `${pathStep.stopFor}` : ''); + }, [pathStep.stopFor]); + + useEffect(() => { + const parsedNumber = parseNumber(debouncedStopDuration); + const newStopDuration = parsedNumber !== undefined ? Math.round(parsedNumber) : undefined; + if (newStopDuration !== pathStep.stopFor) { + dispatch( + updateStdcmPathStep({ + id: pathStep.id, + updates: { stopFor: newStopDuration }, + }) + ); + } + }, [debouncedStopDuration]); + + return ( +
+ { + setStopDuration(e.target.value); + }} + value={stopDuration} + trailingContent="minutes" + statusWithMessage={stopWarning} + /> +
+ ); +}; + +export default StopDurationInput; diff --git a/front/src/utils/strings.ts b/front/src/utils/strings.ts index 9f4ebe6a08b..4aa0d2bf86d 100644 --- a/front/src/utils/strings.ts +++ b/front/src/utils/strings.ts @@ -49,8 +49,7 @@ export function geti18nKeyForNull(str: string | null): string { /** Given a string, return a number or undefined */ export function parseNumber(str: string) { - const number = Number(str); - return !Number.isNaN(number) ? number : undefined; + return str && !Number.isNaN(Number(str)) ? Number(str) : undefined; } /**