import { useEffect, useMemo } from 'react'; import { DatePicker, Select, TimePicker, TolerancePicker } from '@osrd-project/ui-core'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { useOsrdConfSelectors } from 'common/osrdContext'; import { formatDateString, isArrivalDateInSearchTimeWindow } from 'utils/date'; import { createStringSelectOptions } from 'utils/uiCoreHelpers'; import type { ArrivalTimeTypes, ScheduleConstraint } from '../../types'; type StdcmOpScheduleProps = { disabled: boolean; onArrivalChange: ({ date, hours, minutes }: ScheduleConstraint) => void; onArrivalTypeChange: (arrivalType: ArrivalTimeTypes) => void; onArrivalToleranceChange: ({ toleranceBefore, toleranceAfter, }: { toleranceBefore: number; toleranceAfter: number; }) => void; opScheduleTimeType: ArrivalTimeTypes; opTimingData?: { arrivalDate: string; arrivalTime: string; arrivalTimehours: number; arrivalTimeMinutes: number; }; opToleranceValues: { arrivalToleranceBefore: number; arrivalToleranceAfter: number; }; opId: string; isOrigin?: boolean; }; const defaultDate = (date?: Date) => { const newDate = date ? new Date(date) : new Date(); newDate.setHours(0, 0, 0); return newDate; }; const StdcmOpSchedule = ({ disabled, onArrivalChange, onArrivalTypeChange, onArrivalToleranceChange, opTimingData, opScheduleTimeType, opToleranceValues, opId, isOrigin = false, }: StdcmOpScheduleProps) => { const { t } = useTranslation('stdcm'); const { getSearchDatetimeWindow } = useOsrdConfSelectors(); const searchDatetimeWindow = useSelector(getSearchDatetimeWindow); const { arrivalDate, arrivalTime, arrivalTimeHours, arrivalTimeMinutes, arrivalToleranceValues } = useMemo(() => { const isArrivalDateValid = opTimingData?.arrivalDate && isArrivalDateInSearchTimeWindow(new Date(opTimingData.arrivalDate), searchDatetimeWindow); return { arrivalDate: opTimingData && isArrivalDateValid ? new Date(opTimingData.arrivalDate) : defaultDate(searchDatetimeWindow?.begin), arrivalTime: opTimingData?.arrivalTime, arrivalTimeHours: opTimingData?.arrivalTimehours, arrivalTimeMinutes: opTimingData?.arrivalTimeMinutes, arrivalToleranceValues: { minusTolerance: opToleranceValues.arrivalToleranceBefore, plusTolerance: opToleranceValues.arrivalToleranceAfter, }, }; }, [opTimingData, opToleranceValues, searchDatetimeWindow]); const selectableSlot = useMemo( () => searchDatetimeWindow ? { start: searchDatetimeWindow.begin, end: searchDatetimeWindow.end, } : undefined, [searchDatetimeWindow] ); const datePickerErrorMessages = useMemo( () => ({ invalidInput: t('form.datePickerErrors.invalidInput'), invalidDate: t('form.datePickerErrors.invalidDate', { startDate: formatDateString(searchDatetimeWindow?.begin), endDate: formatDateString(searchDatetimeWindow?.end), }), }), [t, searchDatetimeWindow] ); useEffect(() => { if ( (!isArrivalDateInSearchTimeWindow(arrivalDate, searchDatetimeWindow) || !opTimingData?.arrivalDate) && opScheduleTimeType === 'preciseTime' ) { onArrivalChange({ date: defaultDate(searchDatetimeWindow?.begin), hours: arrivalTimeHours || 0, minutes: arrivalTimeMinutes || 0, }); } }, [searchDatetimeWindow, opScheduleTimeType]); return ( <> <div className="arrival-type-select"> <Select id={`select-${opId}`} value={opScheduleTimeType} onChange={(e) => { if (e) { onArrivalTypeChange(e as ArrivalTimeTypes); } }} {...createStringSelectOptions( isOrigin ? ['preciseTime', 'respectDestinationSchedule'] : ['preciseTime', 'asSoonAsPossible'] )} getOptionLabel={(option) => t(`trainPath.${option}`)} disabled={disabled} /> </div> {opScheduleTimeType === 'preciseTime' && ( <div className="schedule"> <DatePicker inputProps={{ id: `date-${opId}`, label: t('trainPath.date'), name: 'op-date', disabled, }} selectableSlot={selectableSlot} value={arrivalDate} onDateChange={(e) => { onArrivalChange({ date: e, hours: arrivalTimeHours || 0, minutes: arrivalTimeMinutes || 0, }); }} errorMessages={datePickerErrorMessages} /> <TimePicker id={`time-${opId}`} label={t('trainPath.time')} hours={arrivalTimeHours} minutes={arrivalTimeMinutes} onTimeChange={({ hours, minutes }) => { onArrivalChange({ date: arrivalDate, hours, minutes }); }} disabled={disabled} value={arrivalTime} readOnly={false} /> <div className="mr-n2 pr-1"> <TolerancePicker id={`stdcm-tolerance-${opId}`} label={t('trainPath.tolerance')} toleranceValues={arrivalToleranceValues} onChange={() => {}} onToleranceChange={({ minusTolerance, plusTolerance }) => { onArrivalToleranceChange({ toleranceBefore: minusTolerance, toleranceAfter: plusTolerance, }); }} disabled={disabled} /> </div> </div> )} </> ); }; export default StdcmOpSchedule;