diff --git a/lib/editor/components/timetable/TripSeriesModal.js b/lib/editor/components/timetable/TripSeriesModal.js index e94b71969..ad9570406 100644 --- a/lib/editor/components/timetable/TripSeriesModal.js +++ b/lib/editor/components/timetable/TripSeriesModal.js @@ -8,6 +8,34 @@ import {getComponentMessages} from '../../../common/util/config' import HourMinuteInput from '../HourMinuteInput' import type {Trip} from '../../../types' +type State = { + autoBlockIdIncrement: number, + autoBlockIdPrefix: string, + autoBlockIdStart: number, + autoTripIdIncrement: number, + autoTripIdPrefix: string, + autoTripIdStart: number, + endTime: ?number, + headway: ?number, + startTime: ?number, + useAutoBlockIds: boolean, + useAutoTripIds: boolean, +} + +const initialState: State = { + startTime: null, + headway: null, + endTime: null, + useAutoTripIds: false, + useAutoBlockIds: false, + autoTripIdStart: 0, + autoBlockIdStart: 1, + autoTripIdIncrement: 1, + autoBlockIdIncrement: 1, + autoTripIdPrefix: '', + autoBlockIdPrefix: '' +} + type Props = { addNewTrip: typeof tripActions.addNewTrip, constructNewRow: (trip: ?Trip, tripSeriesStartTime: ?number, autoTripId: ?string, autoBlockId: ?string) => ?Trip, @@ -17,78 +45,48 @@ type Props = { } const TripSeriesModal = (props: Props) => { - // Trip series timing state variables - const [startTime, setStartTime] = useState(null) - const [headway, setHeadway] = useState(null) - const [endTime, setEndTime] = useState(null) - - // Automatic block and trip ID state variables - const [useAutoTripIds, setUseAutoTripIds] = useState(false) - const [useAutoBlockIds, setUseAutoBlockIds] = useState(false) - - const [autoTripIdStart, setAutoTripIdStart] = useState(0) - const [autoBlockIdStart, setAutoBlockIdStart] = useState(1) - - const [autoTripIdIncrement, setAutoTripIdIncrement] = useState(1) - const [autoBlockIdIncrement, setAutoBlockIdIncrement] = useState(1) - - const [autoTripIdPrefix, setAutoTripIdPrefix] = useState('') - const [autoBlockIdPrefix, setAutoBlockIdPrefix] = useState('') + const [state, setState] = useState(initialState) const messages = getComponentMessages('TripSeriesModal') - const handleIncrementStartUpdate = (evt: SyntheticInputEvent) => setAutoTripIdStart(+evt.target.value) + const handleIncrementStartUpdate = (evt: SyntheticInputEvent) => setState((prevState) => ({ ...prevState, autoTripIdStart: +evt.target.value })) const handleBlockIdStartUpdate = (evt: SyntheticInputEvent) => { // Check the input to make sure it's within the valid range. let input = +evt.target.value if (isNaN(input)) return null if (input > autoBlockIdIncrement) input = autoBlockIdIncrement else if (input < 1) input = 1 - setAutoBlockIdStart(input) + setState((prevState) => ({ ...prevState, autoBlockIdStart: input })) } - const handleTripPrefixUpdate = (evt: SyntheticInputEvent) => setAutoTripIdPrefix(evt.target.value) - const handleBlockPrefixUpdate = (evt: SyntheticInputEvent) => setAutoBlockIdPrefix(evt.target.value) - - const handleTripIncrementUpdate = (evt: SyntheticInputEvent) => setAutoTripIdIncrement(+evt.target.value) - const handleBlockIncrementUpdate = (evt: SyntheticInputEvent) => setAutoBlockIdIncrement(+evt.target.value) - - const handleAutoTripIDCheckBox = () => setUseAutoTripIds(!useAutoTripIds) - const handleAutoBlockIDCheckBox = () => setUseAutoBlockIds(!useAutoBlockIds) - - const clearState = () => { - setStartTime(null) - setEndTime(null) - setHeadway(null) - setAutoTripIdPrefix('') - setAutoTripIdStart(0) - setAutoTripIdIncrement(1) - setAutoBlockIdStart(1) - setAutoBlockIdIncrement(1) - setAutoBlockIdPrefix('') - setUseAutoBlockIds(false) - setUseAutoTripIds(false) - } + const handleTripPrefixUpdate = (evt: SyntheticInputEvent) => setState((prevState) => ({ ...prevState, autoTripIdPrefix: evt.target.value })) + const handleBlockPrefixUpdate = (evt: SyntheticInputEvent) => setState((prevState) => ({ ...prevState, autoBlockIdPrefix: evt.target.value })) + + const handleTripIncrementUpdate = (evt: SyntheticInputEvent) => setState((prevState) => ({ ...prevState, autoTripIdIncrement: +evt.target.value })) + const handleBlockIncrementUpdate = (evt: SyntheticInputEvent) => setState((prevState) => ({ ...prevState, autoBlockIdIncrement: +evt.target.value })) + + const handleAutoTripIDCheckBox = () => setState((prevState) => ({ ...prevState, useAutoTripIds: !prevState.useAutoTripIds })) + const handleAutoBlockIDCheckBox = () => setState((prevState) => ({ ...prevState, useAutoBlockIds: !prevState.useAutoBlockIds })) const _onClose = () => { const { onClose } = props - clearState() + setState(initialState) onClose() } const onClickGenerate = useCallback(() => { - const {addNewTrip, constructNewRow, onClose} = props + const {addNewTrip, constructNewRow} = props // Check state variables to make flow happy - if (startTime === null || endTime === null || headway === null) return - const adjustedEndTime = startTime < endTime ? endTime : endTime + 24 * 60 * 60 - - let tripId = autoTripIdStart - let currentBlockIdSuffix = autoBlockIdStart - for (let time = startTime; time <= adjustedEndTime; time += headway) { - const autoTripId = useAutoTripIds ? `${autoTripIdPrefix}-${tripId}` : null - const autoBlockId = useAutoBlockIds ? `${autoBlockIdPrefix}-${currentBlockIdSuffix}` : null + if (state.startTime === null || state.endTime === null || state.headway === null) return + const adjustedEndTime = state.startTime < state.endTime ? state.endTime : state.endTime + 24 * 60 * 60 + + let tripId = state.autoTripIdStart + let currentBlockIdSuffix = state.autoBlockIdStart + for (let time = state.startTime; time <= adjustedEndTime; time += state.headway) { + const autoTripId = state.useAutoTripIds ? `${state.autoTripIdPrefix}-${tripId}` : null + const autoBlockId = state.useAutoBlockIds ? `${state.autoBlockIdPrefix}-${currentBlockIdSuffix}` : null addNewTrip(constructNewRow(null, time, autoTripId, autoBlockId)) - // If we're upating the trip IDs automatically, increment the trip ID: + // If we're updating the trip IDs automatically, increment the trip ID: if (useAutoTripIds) tripId += autoTripIdIncrement // If we're updating the Block IDs automatically, alternate according to input number if (useAutoBlockIds) { @@ -97,12 +95,23 @@ const TripSeriesModal = (props: Props) => { if (currentBlockIdSuffix > autoBlockIdIncrement) currentBlockIdSuffix = currentBlockIdSuffix % autoBlockIdIncrement } } - clearState() - onClose() - }, [endTime, startTime, headway, autoTripIdStart, autoTripIdIncrement, autoTripIdPrefix, autoBlockIdPrefix, autoBlockIdIncrement, autoBlockIdStart]) + _onClose() + }, [state.startTime, state.endTime, state.headway, state.autoTripIdStart, state.autoTripIdIncrement, state.autoTripIdPrefix, state.autoBlockIdPrefix, state.autoBlockIdIncrement, state.autoBlockIdStart, state.useAutoTripIds, state.useAutoBlockIds]) const {Body, Footer, Header, Title} = Modal const {onClose, show, useSecondsInOffset} = props + const { + startTime, + endTime, + headway, + useAutoTripIds, + autoTripIdPrefix, + autoTripIdIncrement, + useAutoBlockIds, + autoBlockIdPrefix, + autoBlockIdIncrement, + autoBlockIdStart + } = state const generateTripsDisabled = startTime === null || endTime === null || !headway return ( @@ -114,22 +123,39 @@ const TripSeriesModal = (props: Props) => { flexDirection: 'row' }}>
- {messages('startTime') - } + {messages('startTime')} + setState((prevState) => ({ ...prevState, startTime: value }))} + seconds={startTime} + showSeconds={useSecondsInOffset} + standaloneInput + />
{messages('headway')} - + setState((prevState) => ({ ...prevState, headway: value }))} + seconds={headway} + showSeconds={useSecondsInOffset} + standaloneInput + />
{messages('endTime')} - + setState((prevState) => ({ ...prevState, endTime: value }))} + seconds={endTime} + showSeconds={useSecondsInOffset} + standaloneInput + />

- {messages('automaticallyUpdateTripIds')} - {useAutoTripIds && + + {messages('automaticallyUpdateTripIds')} + + {useAutoTripIds && ( <>
<> @@ -140,7 +166,7 @@ const TripSeriesModal = (props: Props) => { type='text' value={autoTripIdPrefix} /> - - + - {

- } + )}
- {messages('automaticallyUpdateBlockIds')} - {useAutoBlockIds && + {messages('automaticallyUpdateBlockIds')} + {useAutoBlockIds && ( <>
{
{messages('formatExplanation')} - } + )}