Skip to content

feat: filter by a single instance of a flight and add a flight details pane#649

Draft
mhlas7 wants to merge 5 commits into
johanohly:mainfrom
mhlas7:filter-instance
Draft

feat: filter by a single instance of a flight and add a flight details pane#649
mhlas7 wants to merge 5 commits into
johanohly:mainfrom
mhlas7:filter-instance

Conversation

@mhlas7

@mhlas7 mhlas7 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

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:

  1. On the filters tab on the right side of the map
  2. Selecting an individual flight from the map details pane. Previously, this would open the "List Flights" modal and show all flights between the two airports. The "Open list" button still retains this behavior.
  3. Flight filter in the "List flights" modal
Screenshot_20260704_234108

In addition, I added a "Show on map" button to the list flights page.

Screenshot_20260704_222417

Testing

  • Tested all three filters locally with my personal flight database

Note

Add single-flight filter and flight details pane to the map

  • Adds a flightIds filter to FlightFilters that restricts the map and dataset to a single flight; the filter is honored in the main page predicate and all derived option lists.
  • Introduces a new flight details pane (FlightDetailsContent, FlightDetailsHeader, FlightDetailsBody, FlightDetailsActions) showing airline, aircraft, route, passengers, and seat data.
  • Scopes airport, airline, aircraft, passenger, and year filter options to flights matching currently active temp filters via a new scopedFlights derived, preventing empty-result filter combinations.
  • From the flight list modal, a new "Show on map" button isolates the flight via flightIds and opens the details pane.
  • From the route details pane, clicking a flight now opens its dedicated details pane and applies the flightIds isolation filter instead of focusing the list modal.

Macroscope summarized c1c6a1e.

@github-actions github-actions Bot added the Web label Jul 5, 2026
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Label error. Requires exactly 1 of: changelog:.*. Found: Web

Comment thread src/lib/components/flight-filters/Filters.svelte
Comment thread src/lib/components/modals/list-flights/ListFlightsModal.svelte Outdated
@sonarqubecloud

sonarqubecloud Bot commented Jul 5, 2026

Copy link
Copy Markdown

})();
if (!arcRoute) return;

const arc = allFlightArcs.find((item) => routeMatches(item, arcRoute));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Comment on lines +20 to +22
const flightNumber = $derived(
flight.flightNumber?.replace(/([a-zA-Z]{2})(\d+)/, '$1 $2') ?? null,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Suggested change
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.

Comment on lines +51 to +54
const flight = useFlightDetails(
() => flights,
() => filters,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 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.

Comment thread src/routes/+page.svelte
Comment on lines +204 to +209
if (
filters.flightIds.length &&
!filters.flightIds.includes(f.id.toString())
) {
return false;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 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

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.

🤖 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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium

onEdit={readonly ? undefined : handleMobileEdit}

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.

@mhlas7 mhlas7 marked this pull request as draft July 5, 2026 06:46
@mhlas7 mhlas7 changed the title feat: filter by a single instance of a flight feat: filter by a single instance of a flight and add a flight details pane Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant