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

Fix itinerary grouping #976

Merged
merged 13 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/components/narrative/metro/attribute-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const getFirstTransitLegStop = (
itinerary.legs?.find((leg: Leg) => leg?.from?.vertexType === 'TRANSIT')?.from
?.name

export const getFlexAttirbutes = (
export const getFlexAttributes = (
itinerary: Itinerary
): {
isCallAhead: boolean
Expand Down
18 changes: 6 additions & 12 deletions lib/components/narrative/metro/metro-itinerary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import ItineraryBody from '../line-itin/connected-itinerary-body'
import NarrativeItinerary from '../narrative-itinerary'
import SimpleRealtimeAnnotation from '../simple-realtime-annotation'

import { getFirstTransitLegStop, getFlexAttirbutes } from './attribute-utils'
import { getFlexAttributes } from './attribute-utils'
import DepartureTimesList, {
SetActiveItineraryHandler
} from './departure-times-list'
Expand Down Expand Up @@ -202,23 +202,17 @@ class MetroItinerary extends NarrativeItinerary {
static ModesAndRoutes = MetroItineraryRoutes

_onMouseEnter = () => {
const { active, index, setVisibleItinerary, visibleItinerary } = this.props
const { active, index, setVisibleItinerary, visible } = this.props
// Set this itinerary as visible if not already visible.
const visibleNotSet =
visibleItinerary === null || visibleItinerary === undefined
const isVisible =
visibleItinerary === index || (active === index && visibleNotSet)
const isVisible = visible || active
if (typeof setVisibleItinerary === 'function' && !isVisible) {
setVisibleItinerary({ index })
}
}

_onMouseLeave = () => {
const { index, setVisibleItinerary, visibleItinerary } = this.props
if (
typeof setVisibleItinerary === 'function' &&
visibleItinerary === index
) {
const { setVisibleItinerary, visible } = this.props
if (typeof setVisibleItinerary === 'function' && visible) {
setVisibleItinerary({ index: null })
}
}
Expand Down Expand Up @@ -266,7 +260,7 @@ class MetroItinerary extends NarrativeItinerary {
const { SvgIcon } = this.context

const { isCallAhead, isContinuousDropoff, isFlexItinerary, phone } =
getFlexAttirbutes(itinerary)
getFlexAttributes(itinerary)

const { fareCurrency, transitFare } = getFare(itinerary, defaultFareType)

Expand Down
52 changes: 33 additions & 19 deletions lib/components/narrative/narrative-itineraries.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ import Loading from './loading'
import NarrativeItinerariesErrors from './narrative-itineraries-errors'
import NarrativeItinerariesHeader from './narrative-itineraries-header'

/** Creates a start time object for the given itinerary. */
function makeStartTime(itinerary) {
return {
itinerary,
legs: itinerary.legs,
realtime: firstTransitLegIsRealtime(itinerary)
}
}

function doMergeItineraries(itineraries) {
const mergedItineraries = itineraries
.reduce((prev, cur, curIndex) => {
Expand All @@ -60,46 +69,51 @@ function doMergeItineraries(itineraries) {
// Only process itineraries less than 24 hours in the future
differenceInDays(updatedItinerary.startTime, Date.now()) < 1
) {
const duplicateItin = updatedItineraries[duplicateIndex]
const duplicateFoundItin = updatedItineraries[duplicateIndex]
// TODO: MERGE ROUTE NAMES

// Add only new start time to existing itinerary
// Add only new start time to existing itinerary.
// The existing itinerary is the earliest between
// this itinerary (updatedItinerary) and duplicateItin.
// This is because alternate routes are only added to the first non-duplicate itinerary,
// and we show alternate routes for the first (i.e. earliest) non-duplicate itinerary found.
let duplicateItin = duplicateFoundItin
let itinCopyToAdd = updatedItinerary
if (duplicateFoundItin.startTime > updatedItinerary.startTime) {
duplicateItin = updatedItinerary
duplicateItin.startTimes = duplicateFoundItin.allStartTimes
updatedItineraries[duplicateIndex] = updatedItinerary
itinCopyToAdd = duplicateFoundItin
}

if (!duplicateItin.allStartTimes) {
duplicateItin.allStartTimes = [
{
itinerary: duplicateItin,
legs: duplicateItin.legs,
realtime: firstTransitLegIsRealtime(duplicateItin)
}
]
duplicateItin.allStartTimes = [makeStartTime(duplicateItin)]
}
// Only add new time if it doesn't already exist. It would be better to use
// the uniqueness feature of Set, but unfortunately objects are never equal
if (
!duplicateItin.allStartTimes.find(
(time) => getFirstLegStartTime(time.legs) === cur.startTime
(time) =>
getFirstLegStartTime(time.legs) === itinCopyToAdd.startTime
)
) {
duplicateItin.allStartTimes.push({
itinerary: updatedItinerary,
legs: cur.legs,
realtime: firstTransitLegIsRealtime(cur)
})
duplicateItin.allStartTimes.push(makeStartTime(itinCopyToAdd))
}

// Some legs will be the same, but have a different route
// This map catches those and stores the alternate routes so they can be displayed
duplicateItin.legs = duplicateItin.legs.map((leg, index) => {
const newLeg = clone(leg)
if (leg?.routeId !== cur.legs[index]?.routeId) {
const curLeg = itinCopyToAdd.legs[index]
const curLegRouteId = curLeg?.routeId
if (curLegRouteId && leg?.routeId && leg?.routeId !== curLegRouteId) {
if (!newLeg.alternateRoutes) {
newLeg.alternateRoutes = {}
}
const { routeId } = cur.legs?.[index]
newLeg.alternateRoutes[routeId] = {
newLeg.alternateRoutes[curLegRouteId] = {
// We save the entire leg to the alternateRoutes object so in
// the future, we can draw the leg on the map as an alternate route
...cur.legs?.[index]
...curLeg
}
}
return newLeg
Expand Down
3 changes: 2 additions & 1 deletion lib/reducers/create-otp-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ function createOtpReducer(config) {
[state.activeSearchId]: {
activeItinerary: { $set: action.payload.index },
activeLeg: { $set: null },
activeStep: { $set: null }
activeStep: { $set: null },
visibleItinerary: { $set: null }
}
}
})
Expand Down
Loading