diff --git a/front/public/locales/en/stdcm.json b/front/public/locales/en/stdcm.json index 31172b49e02..b119387dd58 100644 --- a/front/public/locales/en/stdcm.json +++ b/front/public/locales/en/stdcm.json @@ -23,6 +23,7 @@ "invalidDate": "Select a date between {{startDate}} and {{endDate}}" }, "incompleteForm": "Incomplete form", + "missingValue": "Missing value", "viaNotDefined": "Au moins une localisation n'est pas renseignée" }, "leaveAt": "Leave at {{ time }}", diff --git a/front/public/locales/fr/stdcm.json b/front/public/locales/fr/stdcm.json index 30a085dd736..e3840dbfa0d 100644 --- a/front/public/locales/fr/stdcm.json +++ b/front/public/locales/fr/stdcm.json @@ -23,6 +23,7 @@ "invalidDate": "Renseignez une date entre le {{startDate}} et le {{endDate}}" }, "incompleteForm": "Formulaire incomplet", + "missingValue": "Valeur manquante", "viaNotDefined": "Au moins une localisation n'est pas renseignée" }, "leaveAt": "Partir à {{ time }}", diff --git a/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx b/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx index b330b391b03..5e80e094428 100644 --- a/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx +++ b/front/src/applications/stdcm/components/StdcmForm/StdcmConfig.tsx @@ -73,12 +73,15 @@ const StdcmConfig = ({ const formRef = useRef(null); const [formErrors, setFormErrors] = useState(); + const [showErrors, setShowErrors] = useState(false); const disabled = isPending || retainedSimulationIndex > -1; const markersInfo = useMemo(() => extractMarkersInfo(pathSteps), [pathSteps]); const startSimulation = () => { + setShowErrors(true); + const isPathfindingFailed = !!pathfinding && pathfinding.status !== 'success'; const formErrorsStatus = checkStdcmConfigErrors(isPathfindingFailed, pathSteps, t); if (pathfinding?.status === 'success' && !formErrorsStatus) { @@ -146,13 +149,13 @@ const StdcmConfig = ({ />
- +
- + - + { +const StdcmConsist = ({ disabled = false, showErrors }: StdcmConfigCardProps) => { const { t } = useTranslation('stdcm'); const { speedLimitByTag, speedLimitsByTags, dispatchUpdateSpeedLimitByTag } = useStoreDataForSpeedLimitByTagSelector({ isStdcm: true }); @@ -65,6 +65,12 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => { filters: towedRsFilters, } = useFilterTowedRollingStock(); + const isTractionEngineEmpty = !filters.text.trim(); + const isTowedRollingStockEmpty = !towedRsFilters.text.trim(); + const isTotalMassEmpty = totalMass === undefined || totalMass === null; + const isTotalLengthEmpty = totalLength === undefined || totalLength === null; + const isMaxSpeedEmpty = maxSpeed === undefined || maxSpeed === null; + useEffect(() => { if (towedRollingStock) { searchTowedRollingStock(towedRollingStock.name); @@ -128,6 +134,11 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => { suggestions={filteredRollingStockList} getSuggestionLabel={(suggestion: LightRollingStockWithLiveries) => getLabel(suggestion)} onSelectSuggestion={onSelectSuggestion} + statusWithMessage={ + showErrors && isTractionEngineEmpty + ? { tooltip: 'left', status: 'error', message: t('form.missingValue') } + : undefined + } />
@@ -154,6 +165,11 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => { prefillConsist(rollingStock, towed, speedLimitByTag); dispatch(updateTowedRollingStockID(towed?.id)); }} + statusWithMessage={ + showErrors && isTowedRollingStockEmpty + ? { tooltip: 'left', status: 'error', message: t('form.missingValue') } + : undefined + } />
@@ -166,6 +182,11 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => { value={totalMass ?? ''} onChange={onTotalMassChange} disabled={disabled} + statusWithMessage={ + showErrors && isTotalMassEmpty + ? { tooltip: 'left', status: 'error', message: t('form.missingValue') } + : undefined + } /> { value={totalLength ?? ''} onChange={onTotalLengthChange} disabled={disabled} + statusWithMessage={ + showErrors && isTotalLengthEmpty + ? { tooltip: 'left', status: 'error', message: t('form.missingValue') } + : undefined + } />
@@ -194,6 +220,11 @@ const StdcmConsist = ({ disabled = false }: StdcmConfigCardProps) => { value={maxSpeed ?? ''} onChange={onMaxSpeedChange} disabled={disabled} + statusWithMessage={ + showErrors && isMaxSpeedEmpty + ? { tooltip: 'left', status: 'error', message: t('form.missingValue') } + : undefined + } />
diff --git a/front/src/applications/stdcm/components/StdcmForm/StdcmDestination.tsx b/front/src/applications/stdcm/components/StdcmForm/StdcmDestination.tsx index 31e0a185904..6bd8f8e52d1 100644 --- a/front/src/applications/stdcm/components/StdcmForm/StdcmDestination.tsx +++ b/front/src/applications/stdcm/components/StdcmForm/StdcmDestination.tsx @@ -15,7 +15,7 @@ import StdcmOperationalPoint from './StdcmOperationalPoint'; import StdcmOpSchedule from './StdcmOpSchedule'; import type { ArrivalTimeTypes, ScheduleConstraint, StdcmConfigCardProps } from '../../types'; -const StdcmDestination = ({ disabled = false }: StdcmConfigCardProps) => { +const StdcmDestination = ({ disabled = false, showErrors }: StdcmConfigCardProps) => { const { t } = useTranslation('stdcm'); const dispatch = useAppDispatch(); @@ -77,6 +77,7 @@ const StdcmDestination = ({ disabled = false }: StdcmConfigCardProps) => { location={destination.location} pathStepId={destination.id} disabled={disabled} + showErrors={showErrors} /> { +const StdcmOperationalPoint = ({ + location, + pathStepId, + disabled, + showErrors, +}: StdcmOperationalPointProps) => { const { t } = useTranslation('stdcm'); const dispatch = useAppDispatch(); @@ -36,6 +42,8 @@ const StdcmOperationalPoint = ({ location, pathStepId, disabled }: StdcmOperatio const { updateStdcmPathStep } = useOsrdConfActions() as StdcmConfSliceActions; + const isFieldEmpty = !searchTerm.trim(); + const operationalPointsSuggestions = useMemo( () => // Temporary filter added to show a more restrictive list of suggestions inside the stdcm app. @@ -149,6 +157,11 @@ const StdcmOperationalPoint = ({ location, pathStepId, disabled }: StdcmOperatio getSuggestionLabel={(option: Option) => option?.label} onSelectSuggestion={onSelectSuggestion} disableDefaultFilter + statusWithMessage={ + showErrors && isFieldEmpty + ? { tooltip: 'left', status: 'error', message: t('form.missingValue') } + : undefined + } />
diff --git a/front/src/applications/stdcm/components/StdcmForm/StdcmOrigin.tsx b/front/src/applications/stdcm/components/StdcmForm/StdcmOrigin.tsx index bc934810e45..e6edaad15e1 100644 --- a/front/src/applications/stdcm/components/StdcmForm/StdcmOrigin.tsx +++ b/front/src/applications/stdcm/components/StdcmForm/StdcmOrigin.tsx @@ -15,7 +15,7 @@ import StdcmOperationalPoint from './StdcmOperationalPoint'; import StdcmOpSchedule from './StdcmOpSchedule'; import type { ArrivalTimeTypes, ScheduleConstraint, StdcmConfigCardProps } from '../../types'; -const StdcmOrigin = ({ disabled = false }: StdcmConfigCardProps) => { +const StdcmOrigin = ({ disabled = false, showErrors }: StdcmConfigCardProps) => { const { t } = useTranslation('stdcm'); const dispatch = useAppDispatch(); @@ -81,6 +81,7 @@ const StdcmOrigin = ({ disabled = false }: StdcmConfigCardProps) => { location={origin.location} pathStepId={origin.id} disabled={disabled} + showErrors={showErrors} />