Skip to content

feat: Google Places credentials, trip groups, Railway build fixes & Doppler sync#7

Merged
Systemsaholic merged 27 commits intomainfrom
feature/google-places-autocomplete
Jan 30, 2026
Merged

feat: Google Places credentials, trip groups, Railway build fixes & Doppler sync#7
Systemsaholic merged 27 commits intomainfrom
feature/google-places-autocomplete

Conversation

@Systemsaholic
Copy link
Copy Markdown
Owner

@Systemsaholic Systemsaholic commented Jan 30, 2026

Summary

  • Google Places: Switched hotel autocomplete to use Doppler env vars via CredentialResolverService instead of database-stored credentials
  • Trip Groups: Added schema, API filters, activity logging, and move-to-group dialog for organizing trips into collections
  • Railway Build Fixes: Resolved TypeScript strict-mode errors in trip duplication (unused Logger, nullable .returning() results, missing agencyId in inserts)
  • Doppler-Railway Sync: Set up native integration for both prdapi-prod/production and stgapi-dev/preview
  • Cascade Fixes: Added ON DELETE CASCADE to package_details/activity_travelers FKs, fixed package delete trigger timing
  • Multi-day Spanning Activities: New visual layer for activities that span multiple itinerary days
  • Cruise Enhancements: Color coordination, date validation, auto-extend itinerary dates, FTP retry logic
  • Flight UX: Auto-collapse segments and pre-populate dates when adding new segments

Test plan

  • Verify hotel search autocomplete works on preview (Google Places API)
  • Verify trip group filter appears on /trips page (Kanban + Table views)
  • Verify trip duplication works without errors
  • Verify Railway preview deployment succeeds via Doppler sync
  • Verify cruise activities display correct color coordination
  • Verify multi-day spanning activities render correctly in itinerary views

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Trip sharing with public links
    • Organize trips into groups
    • Publish/unpublish trips for visibility control
    • Duplicate existing trips with all details
    • Multi-day activity visualization in itinerary view
    • Auto-extend itinerary dates when adding incompatible cruises
  • Bug Fixes

    • Fixed numeric handling for cruise durations
    • Fixed cascade deletion of trip-related data
    • Corrected spanning activity filtering logic
  • Documentation

    • Added itinerary troubleshooting guide
    • Updated cruise and database architecture documentation

✏️ Tip: You can customize this high-level summary in your review settings.

Systemsaholic and others added 27 commits January 22, 2026 11:20
- Document R2 storage buckets (documents, media)
- Add key files for storage system
- Document module initialization order issue and fix
- Add Unsplash integration notes
- Add dev/preview environment URLs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed cover photo aspect ratio from 16:9 to 3:1 with max-height of 192px
for a more compact, banner-style appearance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add getPublicUrl() method to StorageProvider interface so each provider
  generates URLs appropriate for its storage backend
- Fix bug where files uploaded to Supabase Storage had R2 URLs stored
- Wire Edit button in Trip Summary to open EditItineraryDialog instead
  of navigating to non-existent /trips/[id]/edit route
- Update CLAUDE.md with multi-provider storage documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: Traveltek FTP JSON was storing 'nights' as a string (e.g., "7").
JavaScript string concatenation caused: getDate() + "7" = "257" (not 32).
setDate(257) set the date to day 257 of the year (September 14) instead
of 7 days after departure.

Changes:
- Backend (sailing-import.service.ts): Coerce nights to number before
  date calculation with explicit Number() cast
- Frontend (use-cruise-library.ts): Compute arrivalDate from
  sailDate + nights instead of using potentially corrupted catalog
  endDate field

This fixes the issue where adding a 7-night cruise was creating 233
port_info activities instead of 8.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When creating an itinerary with both start and end dates, automatically
generate the corresponding itinerary days. This eliminates the need for
users to manually click "Generate Days" after creating an itinerary.

- Inject ItineraryDaysService into ItinerariesService using forwardRef
- Call autoGenerate() after successful itinerary creation
- Gracefully handle day generation failures (log warning but don't fail creation)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Add date validation in component-orchestration.service.ts
- Throw BadRequestException if cruise dates don't fit within itinerary dates
- Include helpful error message with specific date conflicts

Frontend - Cruise Library Page:
- Auto-apply date filters when navigating from trip itinerary
- Show itinerary dates in page description when filtering
- Show specific "no cruises available" message with guidance for itinerary context

Frontend - Add to Trip Dialog:
- Add checkDatesCompatible helper function
- Show cruise dates in dialog header when selecting itinerary
- Display itinerary dates for each existing itinerary option
- Disable incompatible itineraries with warning message
- Show that "Create new" option will use cruise dates
- Prevent submission when selected itinerary is date-incompatible

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement Gantt-style visualization for activities that span multiple days
(e.g., 7-night cruises).

Board View:
- New DayHeadersRow component (extracted from DayColumn)
- SpanningActivitiesLayer with CSS Grid for Gantt bars
- SpanningActivityBar with sticky image/name/badges on scroll
- Day columns now filter out spanning parent activities

Table View:
- Left edge connector lines for spanning activities
- Duration badges showing nights count
- Subtle background highlight for spanning rows

Trip Summary:
- Spanning activities shown once at start day
- Vertical continuation lines through spanned days

Also fixes navigation UX: users now return to Itinerary tab
(not Overview) after adding cruises/packages/activities.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two bugs fixed:

1. Date auto-population on drag-and-drop:
   - CASE 4 in trip-itinerary.tsx was missing itineraryId in URL params
   - Caused page.tsx to use wrong itinerary's days, making dayId lookup fail
   - Added itineraryId to URLSearchParams

2. Cruise port info/sea days not visible:
   - spanning-activity-utils.ts had backwards filter condition
   - Changed from checking parentActivityId to checking activity.id

Also added useEffect pattern to all activity forms to handle async
dayDate loading (matches existing pattern in flight-form.tsx).

Added troubleshooting documentation for future reference.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add exponential backoff retry (3 attempts: 5min, 10min delays) to
  scheduled sync for handling temporary FTP outages
- Reduce FTP connection pool from 4 to 2 connections
- Add 30s timeout protection for directory listings
- Add 100ms throttle delay between FTP directory operations
- Prevent sync from hanging indefinitely on unresponsive FTP server

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…g detection

Cruises were not appearing as spanning activities (Gantt-style bars)
because toCustomCruiseApiPayload() did not include startDatetime and
endDatetime at the activity level. These fields are required for
isSpanningActivity() to detect multi-day activities.

Now derives startDatetime from departureDate and endDatetime from
arrivalDate in the cruise details, ensuring cruises properly render
as spanning activities in the itinerary board view.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When adding a cruise from the library that extends beyond the itinerary
dates, instead of throwing an error, we now automatically extend the
itinerary's start/end dates to accommodate the cruise.

Changes:
- Add `autoExtendItinerary` parameter to generate-port-schedule endpoint
- When enabled, updates itinerary dates before creating port activities
- Frontend passes `autoExtendItinerary: true` when adding from library

This provides a much better UX - users no longer need to manually adjust
itinerary dates before adding a cruise.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of automatically extending itinerary dates when adding a cruise
from the library, show a confirmation dialog asking the user first. Also
allow selecting date-incompatible itineraries with a visual warning.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…mation dialog

Remove unused selectedItineraryDateCheck variable that caused build failure.
Skip error toast in onError when date mismatch is being handled by the
extend confirmation dialog.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…date

- Auto-collapse current segment and expand new one when clicking "+ Add Segment"
- Pre-populate new segment's departure date from previous segment's arrival date

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Assign deterministic colors to cruise bookings and their port-info
children so they are visually grouped in table, board, spanning bar,
and summary views. Parent-child activities are grouped together within
each day, with children from earlier parents appearing before later
parent rows.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ripts

Rename deploy-dev.yml to deploy-preview.yml to match environment naming.
Update CRUISE_ARCHITECTURE.md, DATABASE_ARCHITECTURE.md, and cruise-booking
README. Add AGENTS.md, cruise migration script, and migration tracking reset.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
# Conflicts:
#	CLAUDE.md
#	apps/admin/src/app/trips/[id]/_components/trip-summary-column.tsx
Add tripGroupId filter across the full stack so users can filter trips
by group in both Kanban and Table views on the /trips page.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…vity_travelers

Fixes 500 error when deleting trips that have package_details or
activity_travelers rows referencing them.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…e conflicts

The BEFORE DELETE trigger on itinerary_activities was updating child rows
that CASCADE deletes were simultaneously trying to delete, causing
"tuple already modified" errors when deleting trips.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These migrations were registered in the journal but the SQL files
were not committed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Switch hotels controller from DB-based ApiCredentialsService to
env-based CredentialResolverService for Google Places and Amadeus
credentials. This fixes hotel search on preview/prod where the
api_credentials DB table had no Google Places row.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds Drizzle schema for trip_groups table and tripGroupId column on trips,
fixing Railway build failures caused by missing schema definitions.
Also includes activity feed improvements and audit logging for group operations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…uild

- Remove unused Logger import and declaration
- Add non-null assertions for .returning() results
- Add required agencyId to itinerary days and activities inserts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 30, 2026

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

Project Deployment Actions Updated (UTC)
tailfire Error Error Jan 30, 2026 11:08pm
tailfire-admin Ready Ready Preview, Comment Jan 30, 2026 11:08pm
tailfire-client Ready Ready Preview, Comment Jan 30, 2026 11:08pm
tailfire-ota Ready Ready Preview, Comment Jan 30, 2026 11:08pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 30, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This PR introduces trip grouping and sharing, multi-day spanning activities visualization with Gantt-style bars, auto-extending itinerary dates when adding incompatible cruises, deterministic color theming for cruise activities, and publish/unpublish functionality for trips, alongside numerous form enhancements for date auto-population.

Changes

Cohort / File(s) Summary
Deployment & Configuration
.github/workflows/deploy-preview.yml, apps/admin/tailwind.config.ts
Updated Doppler token reference from DEV to PREVIEW; extended Tailwind content scanning to lib utilities.
Documentation & Guidelines
AGENTS.md, CLAUDE.md, apps/admin/docs/itinerary-troubleshooting.md, apps/api/src/cruise-booking/README.md, docs/CRUISE_ARCHITECTURE.md, docs/DATABASE_ARCHITECTURE.md
Added agent guidance docs, expanded operational procedures for environment/secret management, documented itinerary troubleshooting cases, updated cruise booking API contracts and architecture, and extended database documentation for new cruise booking sessions and trip group tables.
Trip Grouping & Sharing Core
apps/admin/src/components/trips/MoveToGroupDialog.tsx, apps/admin/src/components/tern/trips/trips-filter-panel.tsx
Introduced comprehensive group management dialog with create, rename, delete, and trip removal flows; added group filtering UI to trips filter panel.
Trip Activity Tracking
apps/admin/src/components/trips/ActivityFeed.tsx, apps/admin/src/hooks/use-trip-activity.ts, apps/api/src/activity-logs/activity-logs.service.ts, apps/api/src/activity-logs/audit-sanitizer.ts, apps/api/src/activity-logs/events/audit.event.ts
Extended activity feed icons and audit logging to track trip group move/remove actions; updated audit enums and descriptions for trip group operations.
Spanning Activities (Multi-day Rendering)
apps/admin/src/app/trips/[id]/_components/spanning-activities-layer.tsx, apps/admin/src/app/trips/[id]/_components/spanning-activity-bar.tsx, apps/admin/src/hooks/use-spanning-activities.ts, apps/admin/src/lib/spanning-activity-utils.ts
Added Gantt-style spanning activity layer and bar components; created comprehensive spanning activity hook and utility library with date validation, span calculation, and parent/child activity processing.
Itinerary & Activity List Views
apps/admin/src/app/trips/[id]/_components/itinerary-days-list.tsx, apps/admin/src/app/trips/[id]/_components/itinerary-table-view.tsx, apps/admin/src/app/trips/[id]/_components/trip-summary-column.tsx, apps/admin/src/app/trips/[id]/_components/day-headers-row.tsx, apps/admin/src/app/trips/[id]/_components/day-column.tsx, apps/admin/src/app/trips/[id]/_components/day-section.tsx
Integrated spanning activities and cruise color theming into itinerary layouts; added day headers row component; refactored day column to support filtered activities, optional headers, and color mapping; restructured list/table/summary views to handle multi-day activities.
Activity Component Styling
apps/admin/src/app/trips/[id]/_components/activity-list-item.tsx, apps/admin/src/app/trips/[id]/_components/activity-summary-item.tsx
Added optional cruiseColor prop for left-border theming on activity items.
Cruise Auto-Extension & Library
apps/admin/src/app/library/cruises/_components/add-to-trip-dialog.tsx, apps/admin/src/app/library/cruises/_components/cruise-detail-modal.tsx, apps/admin/src/app/library/cruises/page.tsx, apps/admin/src/hooks/use-cruise-library.ts, apps/admin/src/lib/cruise-color-utils.ts, apps/admin/src/lib/validation/cruise-validation.ts
Introduced date compatibility checking and confirmation flow for extending itinerary dates when adding incompatible cruises; added itinerary-aware cruise filtering; created deterministic cruise color palette and assignment utilities; updated validation to derive dates from cruise details.
Activity Forms with Date Auto-Population
apps/admin/src/app/trips/[id]/_components/custom-cruise-form.tsx, apps/admin/src/app/trips/[id]/_components/dining-form.tsx, apps/admin/src/app/trips/[id]/_components/flight-form.tsx, apps/admin/src/app/trips/[id]/_components/lodging-form.tsx, apps/admin/src/app/trips/[id]/_components/options-form.tsx, apps/admin/src/app/trips/[id]/_components/port-info-form.tsx, apps/admin/src/app/trips/[id]/_components/tour-form.tsx, apps/admin/src/app/trips/[id]/_components/transportation-form.tsx
Added effectiveDayDate derivation and auto-population of date fields (departureDate, checkInDate, tourDate, reservationDate, etc.) for new activities using refs to prevent duplicate application on navigation.
Trip Navigation & Context
apps/admin/src/app/trips/[id]/_components/trip-itinerary.tsx, apps/admin/src/hooks/use-activity-navigation.ts
Preserved itinerary tab state in navigation URLs by appending ?tab=itinerary; injected itineraryId into query parameters for activity creation flows.
Trip Management Page
apps/admin/src/app/trips/[id]/page.tsx
Added publish/unpublish/duplicate trip actions and move-to-group dialog integration to trip header; wired new hooks for mutation operations.
Trip Hooks & Queries
apps/admin/src/hooks/use-trips.ts
Introduced publish/unpublish/duplicate trip mutations; added trip group CRUD hooks (create, read, update, delete, list); extended trip filtering to support tripGroupId.
API Routes & Controllers
apps/api/src/trips/trips.controller.ts, apps/api/src/trips/activities.controller.ts
Added new trip endpoints for grouping, sharing, publish/unpublish, and duplicate; introduced public share endpoint; extended generateCruisePortSchedule to accept autoExtendItinerary flag.
Trip Business Logic
apps/api/src/trips/trips.service.ts, apps/api/src/trips/component-orchestration.service.ts, apps/api/src/trips/itineraries.service.ts
Implemented publish/unpublish with share token generation, trip duplication with activity copy, trip group CRUD, and auto-generation of itinerary days on creation; added cruise date validation with auto-extension logic and dynamic filter option building.
Data Transfer Objects
apps/api/src/trips/dto/trip-filter.dto.ts, apps/api/src/trips/dto/update-trip.dto.ts, packages/shared-types/src/api/trips.types.ts, packages/shared-types/src/api/activity-logs.types.ts
Extended DTOs with tripGroupId, shareToken fields; added TripShareDto, TripGroupDto, and filter options for groups; introduced ActivityLogDto interface.
External Services Integration
apps/api/src/external-apis/providers/hotels/hotels.controller.ts, apps/api/src/cruise-import/services/sailing-import.service.ts
Replaced direct credential retrieval with CredentialResolverService; added numeric coercion for nights and seaDays in cruise import.
Client Middleware
apps/client/src/middleware.ts
Added /shared route to public routes list for unauthenticated access to shared trips.
Database Migrations & Schema
packages/database/src/migrations/20260129000000_add_trip_share_token.sql, packages/database/src/migrations/20260129000100_add_trip_groups.sql, packages/database/src/migrations/20260129190539_add_trip_group_audit_enums.sql, packages/database/src/migrations/20260130132456_fix_trip_cascade_deletes.sql, packages/database/src/migrations/20260130143000_fix_package_delete_trigger_timing.sql, packages/database/src/migrations/meta/_journal.json, packages/database/src/schema/trips.schema.ts, packages/database/src/schema/activity-travelers.schema.ts, packages/database/src/schema/package-details.schema.ts, packages/database/scripts/migrate_cruise_to_prod.sh, packages/database/scripts/reset_migration_tracking.sql
Added share_token column to trips; created trip_groups table with RLS policy; added trip_group_id FK to trips; extended audit enums; added cascade deletes for package_details and activity_travelers; adjusted trigger timing; added migration scripts for cruise data and migration tracking reset.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Dialog as Add-to-Trip Dialog
    participant API as Mutation Handler
    participant Service as Component Orchestration
    
    User->>Dialog: Select cruise & incompatible itinerary
    Dialog->>Dialog: Check date compatibility
    alt Dates incompatible
        Dialog->>Dialog: Store pending extension details
        Dialog->>Dialog: Open confirmation dialog
        User->>Dialog: Confirm extend dates
        Dialog->>Dialog: Set loading state
        Dialog->>API: Retry with autoExtendItinerary: true
        API->>Service: validateAndExtendItinerary
        Service->>Service: Extend itinerary start/end dates
        Service->>API: Return updated itinerary
        API->>Dialog: Success
        Dialog->>User: Show cruise added
    else Dates compatible
        Dialog->>API: Add cruise (normal flow)
        API->>Service: Generate port schedule
        Service->>API: Return schedule
        API->>Dialog: Success
        Dialog->>User: Show cruise added
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Whiskers twitching with delight,
Groups of trips now nested tight,
Spanning bars paint days so wide,
Colors code each cruise-filled ride,
Sharing tokens set trips free—
What a grand itinerary!

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/google-places-autocomplete

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 ebca809 into main Jan 30, 2026
4 of 6 checks passed
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.

1 participant