Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(advanced-trip-form): Add autoPlan to advanced trip form #1291

Merged
merged 8 commits into from
Oct 31, 2024
24 changes: 22 additions & 2 deletions lib/components/app/batch-routing-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { CSSTransition, TransitionGroup } from 'react-transition-group'
import { FormattedMessage, injectIntl, IntlShape } from 'react-intl'
import React, { Component, FormEvent } from 'react'

import * as apiActions from '../../actions/api'
import {
advancedPanelClassName,
mainPanelClassName,
transitionDuration,
TransitionStyles
} from '../form/styled'
import { alertUserTripPlan } from '../form/util'
import { getActiveSearch, getShowUserSettings } from '../../util/state'
import { getPersistenceMode } from '../../util/user'
import AdvancedSettingsPanel from '../form/advanced-settings-panel'
Expand All @@ -22,9 +24,11 @@ import ViewerContainer from '../viewers/viewer-container'

interface Props {
activeSearch: any
currentQuery: any
intl: IntlShape
mainPanelContent: number
mobile?: boolean
routingQuery: () => void
showUserSettings: boolean
}

Expand Down Expand Up @@ -75,7 +79,13 @@ class BatchRoutingPanel extends Component<Props> {
handleSubmit = (e: FormEvent) => e.preventDefault()

handlePlanTripClick = () => {
this.setState({ planTripClicked: true })
const { currentQuery, intl, routingQuery } = this.props
alertUserTripPlan(
intl,
currentQuery,
() => this.setState({ planTripClicked: true }),
routingQuery
)
}

render() {
Expand Down Expand Up @@ -128,6 +138,7 @@ class BatchRoutingPanel extends Component<Props> {
>
<AdvancedSettingsPanel
closeAdvancedSettings={this.closeAdvancedSettings}
handlePlanTrip={this.handlePlanTripClick}
innerRef={this._advancedSettingRef}
setCloseAdvancedSettingsWithDelay={
this.setCloseAdvancedSettingsWithDelay
Expand Down Expand Up @@ -223,12 +234,21 @@ const mapStateToProps = (state: any) => {
(state.user.loggedInUser?.hasConsentedToTerms ||
getPersistenceMode(state.otp.config.persistence).isLocalStorage)
const { mainPanelContent } = state.otp.ui
const currentQuery = state.otp.currentQuery

return {
activeSearch: getActiveSearch(state),
currentQuery,
mainPanelContent,
showUserSettings
}
}

export default connect(mapStateToProps)(injectIntl(BatchRoutingPanel))
const mapDispatchToProps = {
routingQuery: apiActions.routingQuery
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(injectIntl(BatchRoutingPanel))
26 changes: 22 additions & 4 deletions lib/components/form/advanced-settings-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import {
onSettingsUpdate,
pipe,
populateSettingWithIcon,
setModeButton
setModeButton,
tripPlannerValidationErrors
} from './util'
import { setModeButtonEnabled } from './batch-settings'
import { styledCheckboxCss } from './styled'
Expand Down Expand Up @@ -111,8 +112,11 @@ const DtSelectorContainer = styled.div`
`

const AdvancedSettingsPanel = ({
autoPlan,
closeAdvancedSettings,
currentQuery,
enabledModeButtons,
handlePlanTrip,
innerRef,
modeButtonOptions,
modeSettingDefinitions,
Expand All @@ -121,8 +125,11 @@ const AdvancedSettingsPanel = ({
setCloseAdvancedSettingsWithDelay,
setQueryParam
}: {
autoPlan: boolean
closeAdvancedSettings: () => void
currentQuery: any
enabledModeButtons: string[]
handlePlanTrip: () => void
innerRef: RefObject<HTMLDivElement>
modeButtonOptions: ModeButtonDefinition[]
modeSettingDefinitions: ModeSetting[]
Expand Down Expand Up @@ -177,11 +184,19 @@ const AdvancedSettingsPanel = ({
)
)

const tripFormErrors = tripPlannerValidationErrors(currentQuery, intl)

const closePanel = useCallback(() => {
// Only autoplan if there are no validation errors
tripFormErrors.length === 0 && autoPlan && handlePlanTrip()
closeAdvancedSettings()
}, [autoPlan, closeAdvancedSettings, handlePlanTrip, tripFormErrors.length])

const onSaveAndReturnClick = useCallback(async () => {
await setCloseAdvancedSettingsWithDelay()
setClosingBySave(true)
closeAdvancedSettings()
}, [closeAdvancedSettings, setCloseAdvancedSettingsWithDelay])
closePanel()
}, [closePanel, setCloseAdvancedSettingsWithDelay])

return (
<PanelOverlay className="advanced-settings" ref={innerRef}>
Expand All @@ -190,7 +205,7 @@ const AdvancedSettingsPanel = ({
aria-label={closeButtonText}
id="close-advanced-settings-button"
onClick={() => {
closeAdvancedSettings()
closePanel()
}}
title={closeButtonText}
>
Expand Down Expand Up @@ -256,9 +271,12 @@ const mapStateToProps = (state: AppReduxState) => {
state.otp.modeSettingDefinitions || [],
modes?.initialState?.modeSettingValues || {}
)

const { autoPlan } = state.otp.config
const saveAndReturnButton =
state.otp.config?.advancedSettingsPanel?.saveAndReturnButton
return {
autoPlan: autoPlan !== false,
currentQuery: state.otp.currentQuery,
// TODO: Duplicated in apiv2.js
enabledModeButtons:
Expand Down
13 changes: 2 additions & 11 deletions lib/components/form/batch-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import { ModeButtonDefinition } from '@opentripplanner/types'
import { Search } from '@styled-icons/fa-solid/Search'
import { SyncAlt } from '@styled-icons/fa-solid/SyncAlt'
import { useIntl } from 'react-intl'
import React, { useCallback, useContext, useState } from 'react'
import React, { useContext, useState } from 'react'

import * as apiActions from '../../actions/api'
import * as formActions from '../../actions/form'
import { ComponentContext } from '../../util/contexts'
import { getActiveSearch, hasValidLocation } from '../../util/state'
Expand All @@ -16,7 +15,6 @@ import { StyledIconWrapper } from '../util/styledIcon'

import {
addModeButtonIcon,
alertUserTripPlan,
modesQueryParamConfig,
onSettingsUpdate,
pipe,
Expand All @@ -39,7 +37,6 @@ type Props = {
modeButtonOptions: ModeButtonDefinition[]
onPlanTripClick: () => void
openAdvancedSettings: () => void
routingQuery: any
setQueryParam: (evt: any) => void
spacedOutModeSelector?: boolean
}
Expand All @@ -64,7 +61,6 @@ function BatchSettings({
modeButtonOptions,
onPlanTripClick,
openAdvancedSettings,
routingQuery,
setQueryParam,
spacedOutModeSelector
}: Props) {
Expand All @@ -80,10 +76,6 @@ function BatchSettings({
pipe(addModeButtonIcon(ModeIcon), setModeButtonEnabled(enabledModeButtons))
)

const _planTrip = useCallback(() => {
alertUserTripPlan(intl, currentQuery, onPlanTripClick, routingQuery)
}, [currentQuery, intl, onPlanTripClick, routingQuery])

const baseColor = getBaseColor()

const accentColor = getDarkenedBaseColor()
Expand All @@ -109,7 +101,7 @@ function BatchSettings({
/>
<PlanTripButton
id="plan-trip"
onClick={_planTrip}
onClick={onPlanTripClick}
title={intl.formatMessage({
id: 'components.BatchSettings.planTripTooltip'
})}
Expand Down Expand Up @@ -151,7 +143,6 @@ const mapStateToProps = (state: any) => {
}

const mapDispatchToProps = {
routingQuery: apiActions.routingQuery,
setQueryParam: formActions.setQueryParam
}

Expand Down
20 changes: 14 additions & 6 deletions lib/components/form/util.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,10 @@ export const setModeButton =
)
}

export const alertUserTripPlan = (
intl: IntlShape,
export const tripPlannerValidationErrors = (
currentQuery: any,
onPlanTripClick: () => void,
routingQuery: () => any
): void => {
// Check for any validation issues in query.
intl: IntlShape
): string[] => {
const issues: string[] = []
if (!hasValidLocation(currentQuery, 'from')) {
issues.push(intl.formatMessage({ id: 'components.BatchSettings.origin' }))
Expand All @@ -88,6 +85,17 @@ export const alertUserTripPlan = (
intl.formatMessage({ id: 'components.BatchSettings.destination' })
)
}
return issues
}

export const alertUserTripPlan = (
intl: IntlShape,
currentQuery: any,
onPlanTripClick: () => void,
routingQuery: () => any
): void => {
// Check for any validation issues in query and alert user.
const issues = tripPlannerValidationErrors(currentQuery, intl)
onPlanTripClick()
if (issues.length > 0) {
// TODO: replace with less obtrusive validation.
Expand Down
23 changes: 21 additions & 2 deletions lib/components/mobile/batch-search-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { injectIntl, IntlShape } from 'react-intl'
import React, { Component } from 'react'
import styled from 'styled-components'

import * as apiActions from '../../actions/api'
import * as uiActions from '../../actions/ui'
import {
advancedPanelClassName,
mainPanelClassName,
transitionDuration,
TransitionStyles
} from '../form/styled'
import { alertUserTripPlan } from '../form/util'
import { MobileScreens } from '../../actions/ui-constants'
import AdvancedSettingsPanel from '../form/advanced-settings-panel'
import BatchSettings from '../form/batch-settings'
Expand Down Expand Up @@ -43,8 +45,10 @@ const MobileSearchSettings = styled.div<{
`

interface Props {
currentQuery: any
intl: IntlShape
map: React.ReactElement
routingQuery: any
setMobileScreen: (screen: number) => void
}

Expand All @@ -63,7 +67,10 @@ class BatchSearchScreen extends Component<Props> {
_advancedSettingRef = React.createRef<HTMLDivElement>()

handlePlanTripClick = () => {
this.setState({ planTripClicked: true })
const { currentQuery, intl, routingQuery } = this.props
alertUserTripPlan(intl, currentQuery, routingQuery, () =>
this.setState({ planTripClicked: true })
)
}

openAdvancedSettings = () => {
Expand Down Expand Up @@ -159,6 +166,7 @@ class BatchSearchScreen extends Component<Props> {
>
<AdvancedSettingsPanel
closeAdvancedSettings={this.closeAdvancedSettings}
handlePlanTrip={this.handlePlanTripClick}
innerRef={this._advancedSettingRef}
setCloseAdvancedSettingsWithDelay={
this.setCloseAdvancedSettingsWithDelay
Expand All @@ -180,8 +188,19 @@ class BatchSearchScreen extends Component<Props> {

// connect to the redux store

const mapStateToProps = (state: any) => {
const { currentQuery } = state.otp.currentQuery
return {
currentQuery
}
}

const mapDispatchToProps = {
routingQuery: apiActions.routingQuery,
setMobileScreen: uiActions.setMobileScreen
}

export default connect(null, mapDispatchToProps)(injectIntl(BatchSearchScreen))
export default connect(
mapStateToProps,
mapDispatchToProps
)(injectIntl(BatchSearchScreen))
Loading