Skip to content

feat: Transportation refactor — subtype-conditional form, Google Places, Amadeus alignment#51

Merged
Systemsaholic merged 14 commits intomainfrom
feature/issue-23-26-transportation
Mar 20, 2026
Merged

feat: Transportation refactor — subtype-conditional form, Google Places, Amadeus alignment#51
Systemsaholic merged 14 commits intomainfrom
feature/issue-23-26-transportation

Conversation

@Systemsaholic
Copy link
Copy Markdown
Owner

@Systemsaholic Systemsaholic commented Mar 20, 2026

Summary

Complete transportation activity refactor addressing issues #23 and #26:

  • 14 new DB columns on transportation_details for structured location data (pickup/dropoff lat/lng/placeId/name), enhanced car rental fields (company, booking ref, class, fuel policy), and station fields (departure/arrival)
  • Subtype-conditional form — sections show/hide based on transportation type (transfer, taxi, train, car rental, etc.)
  • Google Places Autocomplete in pickup/dropoff address fields with trip location suggestions (hotels, airports, ports)
  • Amadeus Transfer API alignment — structured data maps directly to Transfer Search API requests
  • Currency conversion — transfer search results display in trip currency (CAD) with approximate FX conversion via exchange-rates API
  • Station/terminal labels adapt for train/ferry/bus subtypes (Departure Station / Arrival Station)

Files changed (13 files, ~1100 lines added)

Database:

  • New migration: 14 columns on transportation_details
  • Drizzle schema + shared types updated

API:

  • GET /trips/:id/locations endpoint for trip location suggestions
  • Transportation service explicit field maps (create/update/format) + snapshot builder
  • SharedTransportDetailDto type updated

Admin:

  • TransportationAddressInput component (Google Places v1 + trip suggestions)
  • useTripLocations hook
  • Form refactor with showSection() visibility map
  • Validation schema, defaults, payload mapper
  • FX conversion in transfer search results + on select
  • Stale field clearing on subtype change

Codex validated

  • All 14 fields consistent across migration → schema → types → validation → service → snapshot
  • Manual address edit propagation fixed (onBlur handler)
  • Lat/lng numeric coercion fixed (toNullableStrict for create, toNumber for format)

Test plan

  • Select each subtype and verify correct sections show/hide
  • Test Google Places autocomplete in pickup/dropoff fields
  • Search transfers (CUN → Hotel) and verify CAD conversion in results
  • Select a transfer and verify form fields populate
  • Test train/ferry/bus shows Departure/Arrival Station labels
  • Test car rental shows company, booking ref, class, fuel policy fields
  • Verify auto-save works with new fields

fixes #23, fixes #26

Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added address autocomplete for pickup/dropoff locations with trip history and Google Places integration.
    • Implemented automatic currency conversion for transfer pricing from provider currency to trip currency.
    • Enhanced car rental booking with company, reference, car class, and fuel policy fields.
    • Added station/terminal fields for trains, ferries, and buses.
  • Improvements

    • Automatic field clearing when changing transportation type to prevent stale data.
    • Visual enhancements for transit modes with improved section labeling.

Systemsaholic and others added 14 commits March 19, 2026 19:32
Add structured location data (pickup/dropoff name, lat, lng, placeId),
enhanced car rental fields (company, booking ref, car class, fuel policy),
and station/terminal fields for train/ferry/bus.

Supports Google Places integration and Amadeus Transfer API compatibility.

fixes #23, fixes #26

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Returns hotels, airports, ports, and day locations from trip activities
for use as autocomplete suggestions in the transportation form.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds structured location, car rental, and station fields to validation,
defaults, field list, and API payload mapper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… snapshot builder

Explicitly maps pickup/dropoff location, car rental, and station fields
in create/update/format field maps and proposal snapshot builder.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Combines Google Places Autocomplete with trip location suggestions.
Trip locations (hotels, airports, ports) appear above search results.
Uses Google Places API v1 with NEXT_PUBLIC_GOOGLE_MAPS_API_KEY.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ndering

- Add section visibility map for all 9 subtypes
- Replace pickup/dropoff address Input with TransportationAddressInput
- Add Station/Terminal card for train/ferry/bus
- Enhance car rental section with company, booking ref, class, fuel policy
- Add stale field clearing on subtype change
- Wrap Vehicle, Driver, Features, Flight sections with showSection() checks
- Wire useTripLocations for address autocomplete suggestions
- Add 14 new fields to AUTO_SAVE_FIELDS

fixes #23, fixes #26

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds 14 new transportation fields to the snapshot DTO type used by
buildProposalItinerary() to fix TypeScript compilation error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. TransportationAddressInput: propagate manual text on blur and clear
   form state when input is emptied (Codex issue #1)
2. detail-mapper: add coerce.toNumber for parsing numeric DB strings
3. transportation-details.service: use toNullableStrict for lat/lng
   on create (preserves 0), toNumber on format (string→number)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove separate Station/Terminal card — for train/ferry/bus subtypes,
pickup/dropoff labels change to Departure/Arrival Station with
appropriate icons and placeholders. Less redundancy, cleaner UX.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Form now shows only the type selector and a hint prompt until the user
picks a transportation type. Sections then appear based on the
subtype visibility matrix — cleaner, more adaptive UX.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a transfer is selected from Amadeus results and its currency
differs from the trip currency (e.g., EUR vs CAD), automatically
convert using the existing exchange-rates API. Shows the conversion
in notes: "Approx. conversion: EUR 72.72 → CAD 109.50 (rate: 1.5062).
Provider quotes in EUR."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Transfer results now display prices in trip currency (e.g., ~CAD 109.50)
with original provider currency below (EUR 72.72). Fetches FX rates
via existing exchange-rates API when results load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tailfire-client Ready Ready Preview, Comment Mar 20, 2026 0:54am
tailfire-ota Ready Ready Preview, Comment Mar 20, 2026 0:54am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 20, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This pull request extends the transportation activity management system with trip-scoped location autocomplete (hotels, airports, ports), subtype-driven UI visibility for different transport modes, and structured field storage for pickup/dropoff coordinates, car rental details, and station information. Address inputs now integrate Google Places API with trip location suggestions, and transfer pricing includes automatic currency conversion to the trip currency via exchange rate lookups.

Changes

Cohort / File(s) Summary
Transportation Form UI
apps/admin/src/app/trips/[id]/_components/transportation-form.tsx, apps/admin/src/components/transfer-search-panel.tsx
Enhanced form with subtype-driven section visibility, replaced address inputs with TransportationAddressInput component, added car rental fields (rental company, booking ref, car class, fuel policy), implemented async transfer selection with currency conversion to trip currency via exchange rate API, expanded auto-save watched fields.
Address Autocomplete Component
apps/admin/src/components/transportation/transportation-address-input.tsx
New client component combining trip location suggestions with Google Places autocomplete, featuring debounced requests, keyboard navigation (ArrowUp/Down/Enter/Escape), blur-to-persist logic, and fallback handling for failed Details API calls.
Frontend Hooks & Validation
apps/admin/src/hooks/use-trip-locations.ts, apps/admin/src/lib/validation/transportation-validation.ts
New hook fetching trip locations (hotels, airports, ports, day locations) via useQuery with 60-second stale time; schema extended with pickup/dropoff metadata (name, lat/lng, placeId), car rental fields, and station fields with corresponding payload/default mappers.
Backend API Layer
apps/api/src/trips/trips.service.ts, apps/api/src/trips/trips.controller.ts, apps/api/src/trips/transportation-details.service.ts, apps/api/src/trips/detail-mapper.ts
Added GET /trips/:id/locations endpoint and getTripLocations() service method aggregating locations from trip itineraries (lodging, flights, ports, day activities); extended transportation detail field mappings from 28 to 42 fields; added numeric coercion helper for lat/lng conversion.
Database Schema & Migrations
packages/database/src/migrations/20260319233106_transportation_location_fields.sql, packages/database/src/migrations/meta/_journal.json, packages/database/src/schema/transportation-details.schema.ts
Added 14 new optional columns to transportation_details table for structured pickup/dropoff data, rental metadata, and station names; updated Drizzle schema with numeric/varchar definitions.
Shared Type Definitions
packages/shared-types/src/api/trips.types.ts, packages/shared-types/src/schemas/transportation.schema.ts
Extended SharedTransportDetailDto and corresponding Zod schema with new optional fields for pickup/dropoff coordinates/names, car rental details, and station information.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Form as Transportation Form
    participant AddressInput as TransportationAddressInput
    participant TripLocations as useTripLocations<br/>(React Query)
    participant GooglePlaces as Google Places API
    participant API as Backend API

    User->>Form: Open transportation form
    Form->>TripLocations: Request trip locations
    TripLocations->>API: GET /trips/{id}/locations
    API-->>TripLocations: [hotels, airports, ports, day_locations]
    TripLocations-->>Form: locations loaded
    
    User->>AddressInput: Focus pickup address field
    AddressInput->>AddressInput: Display trip locations in dropdown
    
    User->>AddressInput: Type address query
    AddressInput->>AddressInput: Debounce & check trip locations
    AddressInput->>GooglePlaces: Autocomplete request (if no trip match)
    GooglePlaces-->>AddressInput: Prediction suggestions
    AddressInput->>AddressInput: Display combined results
    
    User->>AddressInput: Select suggestion
    alt Trip Location Selected
        AddressInput->>AddressInput: Use location coords directly
    else Google Prediction Selected
        AddressInput->>GooglePlaces: Fetch Place Details
        GooglePlaces-->>AddressInput: Formatted address, coords
    end
    
    AddressInput->>Form: onChange({address, name, lat, lng, placeId})
    Form->>Form: Store in form state
Loading
sequenceDiagram
    actor User
    participant Form as Transportation Form
    participant TransferPanel as TransferSearchPanel
    participant SearchAPI as Search/Transfer API
    participant ExchangeAPI as Exchange Rates API
    participant Backend as Backend Service
    participant DB as Database

    User->>TransferPanel: Search transfers
    TransferPanel->>SearchAPI: Request transfers
    SearchAPI-->>TransferPanel: Results (provider currency)
    TransferPanel->>TransferPanel: Extract provider currencies
    TransferPanel->>ExchangeAPI: Fetch missing FX rates
    ExchangeAPI-->>TransferPanel: Rate conversions
    TransferPanel->>TransferPanel: Display prices in trip currency with subtext
    
    User->>Form: Select transfer option
    Form->>Form: Convert price to trip currency (async)
    Form->>ExchangeAPI: POST /exchange-rates/convert
    ExchangeAPI-->>Form: Converted amount
    Form->>Form: Update totalPriceCents, currency, notes
    Form->>Form: Show "Transfer Details Applied" toast
    
    User->>Form: Submit transportation form
    Form->>Backend: POST /trips/{id}/transportation
    Backend->>DB: INSERT transportation_details
    DB-->>Backend: Stored with converted pricing
    Backend-->>Form: Success
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A burrow of addresses, a warren of places,
Google's suggestions now greet friendly faces,
Currencies convert with a hop and a bound,
Trip locations remembered, all safe and sound,
With subtypes and stations, the form comes alive,
This transportation refactor helps travelers thrive!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main changes: subtype-conditional form UI, Google Places integration, and Amadeus API alignment for transportation activities.
Linked Issues check ✅ Passed All coding requirements from issues #23 and #26 are met: subtype-conditional form visibility, Amadeus field alignment, Google Places autocomplete integration, and trip location suggestions.
Out of Scope Changes check ✅ Passed All changes directly support the linked issue objectives. No unrelated modifications detected; additions to database schema, validation, services, and UI components are all aligned with transportation refactoring and address autocomplete requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/issue-23-26-transportation
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Systemsaholic Systemsaholic merged commit 9644529 into main Mar 20, 2026
3 of 4 checks passed
@Systemsaholic Systemsaholic deleted the feature/issue-23-26-transportation branch March 23, 2026 19:07
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.

Transportation Activity - Address Transportation - Refactor

1 participant