feat: filter by a single instance of a flight and add a flight details pane#649
feat: filter by a single instance of a flight and add a flight details pane#649mhlas7 wants to merge 5 commits into
Conversation
|
Label error. Requires exactly 1 of: changelog:.*. Found: Web |
…te only gives filter options that pertain to flights along that route
…ting the flightId
… flight from the list or route details page
|
| })(); | ||
| if (!arcRoute) return; | ||
|
|
||
| const arc = allFlightArcs.find((item) => routeMatches(item, arcRoute)); |
There was a problem hiding this comment.
🟡 Medium map/Map.svelte:493
The flight-focus path can fail to move the map for flights whose origin/destination share names with another airport pair. prepareFlightArcData() deduplicates arcs by sorted airport names, but the lookup at allFlightArcs.find((item) => routeMatches(item, arcRoute)) matches by airport IDs. When two distinct airport pairs share the same name, the arc stored in allFlightArcs has the first pair's IDs, so routeMatches returns false and the effect exits at if (!arc) return; — opening that flight's details leaves the map unfocused. Consider looking up the arc by matching names instead of IDs, or deriving the camera target directly from the flight's coordinates rather than via the deduplicated arc list.
🤖 Copy this AI Prompt to have your agent fix this:
In file @src/lib/components/map/Map.svelte around line 493:
The flight-focus path can fail to move the map for flights whose origin/destination share names with another airport pair. `prepareFlightArcData()` deduplicates arcs by sorted airport **names**, but the lookup at `allFlightArcs.find((item) => routeMatches(item, arcRoute))` matches by airport **IDs**. When two distinct airport pairs share the same name, the arc stored in `allFlightArcs` has the first pair's IDs, so `routeMatches` returns false and the effect exits at `if (!arc) return;` — opening that flight's details leaves the map unfocused. Consider looking up the arc by matching names instead of IDs, or deriving the camera target directly from the flight's coordinates rather than via the deduplicated arc list.
| const flightNumber = $derived( | ||
| flight.flightNumber?.replace(/([a-zA-Z]{2})(\d+)/, '$1 $2') ?? null, | ||
| ); |
There was a problem hiding this comment.
🟡 Medium map-details/FlightDetailsHeader.svelte:20
When flight.flightNumber is an empty string, the ?? null operator at line 21 keeps it as '' instead of treating it as missing, so the header title at line 46 renders an empty string rather than falling back to flight.airline?.name or 'Flight'. Consider coercing empty strings to null (e.g., flight.flightNumber?.trim() || null) so the fallback chain works.
| const flightNumber = $derived( | |
| flight.flightNumber?.replace(/([a-zA-Z]{2})(\d+)/, '$1 $2') ?? null, | |
| ); | |
| const flightNumber = $derived( | |
| flight.flightNumber?.trim() || null, | |
| ); |
🤖 Copy this AI Prompt to have your agent fix this:
In file @src/lib/components/map-details/FlightDetailsHeader.svelte around lines 20-22:
When `flight.flightNumber` is an empty string, the `?? null` operator at line 21 keeps it as `''` instead of treating it as missing, so the header title at line 46 renders an empty string rather than falling back to `flight.airline?.name` or `'Flight'`. Consider coercing empty strings to `null` (e.g., `flight.flightNumber?.trim() || null`) so the fallback chain works.
| const flight = useFlightDetails( | ||
| () => flights, | ||
| () => filters, | ||
| ); |
There was a problem hiding this comment.
🟠 High map-details/MapDetailsPane.svelte:51
useFlightDetails is created with only flights and filters, so toggleFlightFilter has no access to tempFilters and cannot clear them when isolating a flight. When a list-drilldown tempFilters is active, +page.svelte applies tempFilters before filters.flightIds, so tapping "Isolate flight on map" sets filters.flightIds but the page still filters by the active tempFilters first — the selected flight stays hidden or the map keeps showing the drilldown subset instead of the single isolated flight. Consider passing () => tempFilters into useFlightDetails (matching useAirportDetails and useRouteDetails) so the toggle can clear tempFilters when isolating.
const flight = useFlightDetails(
() => flights,
() => filters,
+ () => tempFilters,
);🤖 Copy this AI Prompt to have your agent fix this:
In file @src/lib/components/map-details/MapDetailsPane.svelte around lines 51-54:
`useFlightDetails` is created with only `flights` and `filters`, so `toggleFlightFilter` has no access to `tempFilters` and cannot clear them when isolating a flight. When a list-drilldown `tempFilters` is active, `+page.svelte` applies `tempFilters` before `filters.flightIds`, so tapping "Isolate flight on map" sets `filters.flightIds` but the page still filters by the active `tempFilters` first — the selected flight stays hidden or the map keeps showing the drilldown subset instead of the single isolated flight. Consider passing `() => tempFilters` into `useFlightDetails` (matching `useAirportDetails` and `useRouteDetails`) so the toggle can clear `tempFilters` when isolating.
| if ( | ||
| filters.flightIds.length && | ||
| !filters.flightIds.includes(f.id.toString()) | ||
| ) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
🟠 High routes/+page.svelte:204
When filters.flightIds is set, matchesNonLocationFilters still applies the existing date, passenger, airline, aircraft, and registration filters alongside it. If a flight is selected via "show this flight on the map" and doesn't match the currently active non-location filters, filteredFlights returns empty, so the map draws nothing even though the details pane opens for that flight. Consider making a non-empty flightIds filter short-circuit and bypass the other non-location checks, so the selected flight is always visible.
if (
- filters.flightIds.length &&
- !filters.flightIds.includes(f.id.toString())
- ) {
- return false;
+ filters.flightIds.length
+ ) {
+ return filters.flightIds.includes(f.id.toString());
}Also found in 2 other location(s)
src/lib/components/map-details/useFlightDetails.svelte.ts:50
toggleFlightFilteronly clears the location-based filters before settingf.flightIds = [flight.id.toString()]. Any existing non-location filter such asfromDate,toDate,passengers,airline,aircraft, oraircraftRegsstill applies, andmatchesNonLocationFiltersonsrc/routes/+page.svelteintersects those withflightIds. If the selected flight does not satisfy one of those filters, clicking “Isolate flight on map” leaves the map empty instead of isolating that flight.
src/lib/components/map-details/useRouteDetails.svelte.ts:143
showFlightis supposed to isolate the clicked route entry on the map, but it only clearsdepartureAirports,arrivalAirports,airportsEither, androutesbefore settingf.flightIds. Existing non-location filters like date, passenger, airline, aircraft, or registration still remain active inmatchesNonLocationFilters, so clicking a flight from route details can open the flight pane while the map shows no flight at all.
🤖 Copy this AI Prompt to have your agent fix this:
In file @src/routes/+page.svelte around lines 204-209:
When `filters.flightIds` is set, `matchesNonLocationFilters` still applies the existing date, passenger, airline, aircraft, and registration filters alongside it. If a flight is selected via "show this flight on the map" and doesn't match the currently active non-location filters, `filteredFlights` returns empty, so the map draws nothing even though the details pane opens for that flight. Consider making a non-empty `flightIds` filter short-circuit and bypass the other non-location checks, so the selected flight is always visible.
Also found in 2 other location(s):
- src/lib/components/map-details/useFlightDetails.svelte.ts:50 -- `toggleFlightFilter` only clears the location-based filters before setting `f.flightIds = [flight.id.toString()]`. Any existing non-location filter such as `fromDate`, `toDate`, `passengers`, `airline`, `aircraft`, or `aircraftRegs` still applies, and `matchesNonLocationFilters` on `src/routes/+page.svelte` intersects those with `flightIds`. If the selected flight does not satisfy one of those filters, clicking “Isolate flight on map” leaves the map empty instead of isolating that flight.
- src/lib/components/map-details/useRouteDetails.svelte.ts:143 -- `showFlight` is supposed to isolate the clicked route entry on the map, but it only clears `departureAirports`, `arrivalAirports`, `airportsEither`, and `routes` before setting `f.flightIds`. Existing non-location filters like date, passenger, airline, aircraft, or registration still remain active in `matchesNonLocationFilters`, so clicking a flight from route details can open the flight pane while the map shows no flight at all.
There was a problem hiding this comment.
🟡 Medium
showFlightOnMap is only wired into the desktop actions snippet (line 647). The MobileFlightList component (line 418) only receives onEdit and onDelete callbacks, so on small screens the "show on map" action is completely inaccessible. Pass an onShowOnMap callback to MobileFlightList and expose it in its swipe/action UI so mobile users can also trigger it.
🤖 Copy this AI Prompt to have your agent fix this:
In file @src/lib/components/modals/list-flights/ListFlightsModal.svelte around line 423:
`showFlightOnMap` is only wired into the desktop `actions` snippet (line 647). The `MobileFlightList` component (line 418) only receives `onEdit` and `onDelete` callbacks, so on small screens the "show on map" action is completely inaccessible. Pass an `onShowOnMap` callback to `MobileFlightList` and expose it in its swipe/action UI so mobile users can also trigger it.



Description
Closes: #647. Users can now filter by a single instance of a flight. I also added a flight details pane similar to the airport details and route details pane.
This turned out to be a much larger change than I anticipated once I added the new details page so appologies in advance!
The filter can be applied in three ways:
In addition, I added a "Show on map" button to the list flights page.
Testing
Note
Add single-flight filter and flight details pane to the map
flightIdsfilter toFlightFiltersthat restricts the map and dataset to a single flight; the filter is honored in the main page predicate and all derived option lists.FlightDetailsContent,FlightDetailsHeader,FlightDetailsBody,FlightDetailsActions) showing airline, aircraft, route, passengers, and seat data.scopedFlightsderived, preventing empty-result filter combinations.flightIdsand opens the details pane.flightIdsisolation filter instead of focusing the list modal.Macroscope summarized c1c6a1e.