Skip to content

fix(nearby): filter stop sheet routes to the tapped mode (shared stop_id) - #176

Closed
ai-tiro wants to merge 1 commit into
masterfrom
fix/175-sheet-cross-mode-routes
Closed

fix(nearby): filter stop sheet routes to the tapped mode (shared stop_id)#176
ai-tiro wants to merge 1 commit into
masterfrom
fix/175-sheet-cross-mode-routes

Conversation

@ai-tiro

@ai-tiro ai-tiro commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator

What

Filter StopDetail.servingRoutes to the requested route_type so the Nearby map's stop bottom-sheet only shows Routes chips for the mode of the tapped pin.

What I discovered

At co-located stops, the metro platforms and the V/Line platform share one stop_id (Richmond = stop_id 1162). PTV's /stops/{id}/route_type/{type} endpoint ignores the route_type path param for the routes array and returns every route serving that physical stop. Confirmed against the live proxy:

curl -s 'https://ptv.jfx.ac/api/v3/stops/1162/route_type/3' | ...
0 Alamein
0 Belgrave
0 Cranbourne ...
3 Bairnsdale - Melbourne via Sale & Traralgon
3 Traralgon - Melbourne via Morwell & Moe & Pakenham ...

So even though we requested route_type/3 (V/Line), metro (route_type 0) routes come back mixed in. The Nearby sheet rendered them as the Routes chips (NearbyViewModel.startSheetFetchesroutes = result.data.servingRoutes). Departures are fetched per (stopId, routeType) and were already correct, which is exactly why only the Routes chips were wrong.

The fix

Added a requestedRouteType parameter to StopResponseDto.toDomain() (:core:network mapper) and filtered servingRoutes to it. RetrofitStopDetailDataSource already knows the requested routeType and now passes it through.

I fixed it at the mapper/data boundary rather than locally in NearbyViewModel so every getStopDetail consumer gets a routes list consistent with the mode it asked for. I grepped all servingRoutes usages:

  • Nearby sheet — wants the mode-consistent list (this bug).
  • stop-detail toGroupedList — uses servingRoutes only as a routeId -> Route lookup map against departures (which are already mode-specific) and synthesises a placeholder Route for any id the map misses, so a mode-filtered list is strictly correct for it too. (The stop-detail screen's own per-stop serving-routes section was already removed in cffc08e, so nothing renders the raw cross-mode list.)

No surface intentionally wants the cross-mode list, so the shared-layer fix is safe and is the cleaner SSOT choice. RouteType.Unknown disables the filter (we never put Unknown on the wire; this only guards an unexpected upstream value, where passing the raw list through beats dropping every route).

Alternative rejected

A localised filter inside NearbyViewModel.startSheetFetches. Rejected because it leaves the same latent bug for any future getStopDetail consumer and pushes a data-correctness concern up into the UI layer.

Overlap with open PRs

None. Changed files are all in :core:network; neither #173 (fix/171-route-name-overflow) nor #174 (fix/172-colocated-marker-offset) touch them. Base is master.

Testing

  • New regression tests in StopDetailDtoMapperTest (:core:network):
    • serving routes are filtered to the requested route type at a shared stop_id — Richmond-shaped mixed-mode response, request V/Line, assert only the two V/Line routes remain.
    • requesting metro at a shared stop_id keeps only metro routes — the mirror case.
    • Updated the existing mapper tests to pass requestedRouteType (matching their route data, so behaviour is unchanged).
  • ./gradlew :core:network:testDebugUnitTest :core:data:testDebugUnitTest :feature:nearby:testDebugUnitTest — all green.
  • ./gradlew :app:assembleDebug — green.
  • Manual / emulator QA pending (left to the human per request).

Fixes #175

…_id)

PTV's /stops/{id}/route_type/{type} endpoint ignores the route_type path
param for the `routes` array and returns every route serving the physical
stop_id. At co-located stops sharing a stop_id (Richmond, stop_id 1162: the
metro platforms and the V/Line platform are one stop) this mixed modes, so
the Nearby sheet's Routes chips on the V/Line pin showed metro train lines
(Alamein, Belgrave, ...). Departures are fetched per (stopId, routeType) and
were already correct, which is why only the Routes chips were wrong.

Filter servingRoutes to the requested route_type in StopResponseDto.toDomain
so every getStopDetail consumer gets routes consistent with the mode it asked
for. Both current consumers (Nearby sheet, stop-detail departure-grouping
lookup) want the mode-consistent list.

Co-Authored-By: ai-tiro <ai-tiro@jfx.ac>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Debug APK: app-debug-07a088bf62233f058bbc5cda1d00cb43e736131c.apk (built from 07a088b at 2026-06-20 06:45 UTC)

Requires GitHub login. Artifact expires after 3 days.

itsjfx added a commit that referenced this pull request Jun 21, 2026
chore(mobile): combine stop-detail + nearby fixes for QA (#165 #166 #174 #176)
@ai-tiro

ai-tiro commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #179, which combined these commits and has merged to master. Closing as superseded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nearby stop sheet shows another mode's routes for stops sharing a stop_id (Richmond V/Line shows metro lines)

2 participants