Skip to content

Commit

Permalink
Merge pull request #1266 from opentripplanner/sync-sort-departarrive
Browse files Browse the repository at this point in the history
Sync itinerary sort with depart arrive
  • Loading branch information
daniel-heppner-ibigroup committed Sep 26, 2024
2 parents 1f7e8b9 + 9e404f6 commit ca8995a
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 90 deletions.
7 changes: 7 additions & 0 deletions example-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ persistence:
# iconUrl: ''
# href: ''

### These settings are only used for the field trip features.
dateTime:
timeFormat: h:mm a
dateFormat: MM/dd/yyyy

map:
initLat: 45.52
initLon: -122.682
Expand Down Expand Up @@ -411,6 +416,8 @@ itinerary:
displayA11yError: false
# Whether to display itinerary info in the side of the preview or next to the departure times
showInlineItinerarySummary: false
# Whether to sync the sort type with the depart/arrive time in the date/time modal
syncSortWithDepartArrive: true
# The sort option to use by default
# Available sort options: 'BEST', 'DURATION', 'ARRIVALTIME', 'WALKTIME', 'COST', 'DEPARTURETIME'
# defaultSort: "BEST" # Default
Expand Down
76 changes: 0 additions & 76 deletions lib/components/form/date-time-modal.js

This file was deleted.

116 changes: 116 additions & 0 deletions lib/components/form/date-time-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { connect } from 'react-redux'
import coreUtils from '@opentripplanner/core-utils'
import React, { useCallback } from 'react'

import * as formActions from '../../actions/form'
import * as narrativeActions from '../../actions/narrative'
import { AppConfig } from '../../util/config-types'
import { AppReduxState, FilterType, SortType } from '../../util/state-types'

import { StyledDateTimeSelector } from './styled'

type Props = {
config: AppConfig
date: string
dateFormatLegacy?: string
departArrive: DepartArriveValue
setQueryParam: (params: any) => void
sort: SortType
time: string
timeFormatLegacy?: string
updateItineraryFilter: (payload: FilterType) => void
}

type DepartArriveValue = 'NOW' | 'DEPART' | 'ARRIVE'

const DepartArriveTypeMap: Record<
DepartArriveValue,
FilterType['sort']['type']
> = {
ARRIVE: 'ARRIVALTIME',
DEPART: 'DEPARTURETIME',
NOW: 'DURATION'
}

function DateTimeModal({
config,
date,
dateFormatLegacy,
departArrive,
setQueryParam,
sort,
time,
timeFormatLegacy,
updateItineraryFilter
}: Props) {
const { homeTimezone, isTouchScreenOnDesktop } = config
const touchClassName = isTouchScreenOnDesktop
? 'with-desktop-touchscreen'
: ''

const syncSortWithDepartArrive = config?.itinerary?.syncSortWithDepartArrive
// Note the side effect that this will resort the results of a previous query
// if the user changes the depart/arrive setting before the query is run.
const setQueryParamMiddleware = useCallback(
(params: any) => {
if (syncSortWithDepartArrive) {
updateItineraryFilter({
sort: {
...sort,
type: DepartArriveTypeMap[params.departArrive as DepartArriveValue]
}
})
}
setQueryParam(params)
},
[setQueryParam, updateItineraryFilter, sort, syncSortWithDepartArrive]
)
return (
<div className="date-time-modal">
<div className="main-panel">
<StyledDateTimeSelector
className={`date-time-selector ${touchClassName}`}
date={date}
dateFormatLegacy={dateFormatLegacy}
departArrive={departArrive}
onQueryParamChange={setQueryParamMiddleware}
time={time}
// These props below are for legacy browsers
// that don't support `<input type="time|date">`.
// These props are not relevant in modern browsers,
// where `<input type="time|date">` already
// formats the time|date according to the OS settings.
// eslint-disable-next-line react/jsx-sort-props
timeFormatLegacy={timeFormatLegacy}
timeZone={homeTimezone}
/>
</div>
</div>
)
}

const mapStateToProps = (state: AppReduxState) => {
const { date, departArrive, time } = state.otp.currentQuery
const config = state.otp.config
const { sort } = state.otp.filter
return {
config,
date,
// This prop is for legacy browsers (see render method above).
// @ts-expect-error Mismatched config types
dateFormatLegacy: coreUtils.time.getDateFormat(config),
departArrive,
sort,
time,
// This prop is for legacy browsers (see render method above).
// @ts-expect-error Mismatched config types
timeFormatLegacy: coreUtils.time.getTimeFormat(config)
}
}

const mapDispatchToProps = {
setQueryParam: formActions.setQueryParam,
updateItineraryFilter: narrativeActions.updateItineraryFilter
}

export default connect(mapStateToProps, mapDispatchToProps)(DateTimeModal)
10 changes: 1 addition & 9 deletions lib/components/narrative/narrative-itineraries-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export default function NarrativeItinerariesHeader({
enabledSortModes,
errors,
itineraries,
itinerary,
itineraryIsExpanded,
onSortChange,
onSortDirChange,
Expand Down Expand Up @@ -109,13 +108,6 @@ export default function NarrativeItinerariesHeader({
const sortOptionsArr = sortOptions(intl, enabledSortModes)
const sortText = sortOptionsArr.find((x) => x.value === sort.type)?.text

const handleSortClick = useCallback(
(value) => {
onSortChange(value)
},
[onSortChange]
)

return (
<div
className="options header"
Expand Down Expand Up @@ -222,7 +214,7 @@ export default function NarrativeItinerariesHeader({
<li className="sort-option" key={sortOption.value}>
<UnstyledButton
aria-selected={sortText === sortOption.text || undefined}
onClick={() => handleSortClick(sortOption.value)}
onClick={() => onSortChange(sortOption.value)}
role="option"
>
{sortOption.text}
Expand Down
7 changes: 7 additions & 0 deletions lib/util/config-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ export interface ItineraryConfig {
showPlanFirstLastButtons?: boolean
showRouteFares?: boolean
sortModes?: ItinerarySortOption[]
syncSortWithDepartArrive?: boolean
weights?: ItineraryCostWeights
}

Expand Down Expand Up @@ -362,6 +363,11 @@ export interface StopScheduleViewerConfig {
showBlockIds?: boolean
}

export interface DateTimeConfig {
dateFormat: string
timeFormat: string
}

/** The main application configuration object */
export interface AppConfig {
accessibilityScore?: AccessibilityScoreConfig
Expand All @@ -375,6 +381,7 @@ export interface AppConfig {
bugsnag?: BugsnagConfig
co2?: CO2Config
companies?: Company[]
dateTime?: DateTimeConfig
elevationProfile?: boolean
extraMenuItems?: AppMenuItemConfig[]
geocoder: GeocoderConfig
Expand Down
15 changes: 10 additions & 5 deletions lib/util/state-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ export interface OtpState {
activeSearchId?: string
config: AppConfig
currentQuery: any
filter: {
sort: {
type: string
}
}
filter: FilterType
location: any
modeSettingDefinitions: ModeSetting[]
overlay: any
Expand All @@ -31,6 +27,15 @@ export interface OtpState {
ui: any // TODO
}

export interface SortType {
direction: string
type: string
}

export interface FilterType {
sort: SortType
}

export interface UserState {
itineraryExistence?: ItineraryExistence
localUser?: any
Expand Down

0 comments on commit ca8995a

Please sign in to comment.