# Trip Planning Enhancements Design **Date:** 2026-01-12 **Status:** Draft **Scope:** High-level overview for scoping/prioritization ## Goal Transform trip creation from a dense single-form into a guided, progressive-reveal flow that walks users through planning one decision at a time—while keeping everything on a single scrolling screen. ## Current State - Single `TripCreationView` (~2500 lines) with all options visible at once - Planning mode selector controls which sections appear - 4 planning modes: Date Range, Game First, Locations, Follow Team - Sports without games in date range are not indicated ## Target State - Progressive disclosure: sections reveal as user makes selections - Conversational headers guide the user ("Great! When would you like to travel?") - Each section is a small, focused view component (~100-150 lines) - Sports with no games in selected date range are grayed out - Current form remains accessible via Settings toggle for power users ## Approach: Progressive Single-Screen Flow ### Container Architecture ```swift struct TripWizardView: View { @State var viewModel = TripWizardViewModel() var body: some View { ScrollView { VStack(spacing: Theme.Spacing.lg) { // Always visible PlanningModeStep(selection: $viewModel.planningMode) // Reveals after planning mode selected if viewModel.planningMode != nil { SportsStep(...) .transition(.move(edge: .bottom).combined(with: .opacity)) } // Reveals after at least one sport selected if !viewModel.selectedSports.isEmpty { DatesStep(...) .transition(.move(edge: .bottom).combined(with: .opacity)) } // Continues for each step... } .animation(.easeInOut(duration: 0.3), value: viewModel.revealState) } } } ``` ### Step Sequence | Step | Question | Reveals When | |------|----------|--------------| | 1 | "How do you want to plan?" | Always visible | | 2 | "Which sports interest you?" | After planning mode selected | | 3 | "When would you like to travel?" | After sport(s) selected | | 4 | "Where do you want to go?" | After dates set | | 5 | "What's your route preference?" | After region(s) selected | | 6 | "Visit cities more than once?" | After route preference | | 7 | "Any must-stop locations?" | After repeat cities choice | | 8 | Review & Plan button | After all required steps complete | Note: Step order varies by planning mode (e.g., "Game First" skips dates, shows game picker). ### Behavior - Steps slide in from bottom with fade animation - Auto-scroll to newly revealed section (300ms after animation starts) - User can scroll back up and change earlier answers - Changing an answer resets/updates downstream sections as needed - Conversational headers: "Nice! Now pick your travel dates" ### Sport Availability (Graying) After date selection: 1. Fetch game counts per sport for selected date range 2. Use existing `AppDataProvider.shared.filterGames(sports:startDate:endDate:)` 3. Cache results; re-fetch if dates change 4. Display: grayed card + disabled + subtitle "No games in this period" ## File Structure ``` Features/Trip/Views/Wizard/ ├── TripWizardView.swift # Container with progressive reveal logic ├── TripWizardViewModel.swift # Shared state across all steps ├── Steps/ │ ├── PlanningModeStep.swift # "How do you want to plan?" │ ├── SportsStep.swift # Sport grid with availability graying │ ├── DatesStep.swift # Date range picker │ ├── RegionsStep.swift # Region map │ ├── RoutePreferenceStep.swift # Efficient/Scenic/Flexible │ ├── RepeatCitiesStep.swift # Yes/No toggle │ ├── MustStopsStep.swift # Optional locations │ └── ReviewStep.swift # Summary + Plan button ``` ## Key Decisions | Decision | Choice | Rationale | |----------|--------|-----------| | Keep old `TripCreationView`? | Yes | Power users, accessible via Settings toggle | | Reset downstream on change? | Yes | Changing sports resets dates, changing dates refetches sport availability | | Sport graying | Grayed + disabled + subtitle | Clear feedback why sport unavailable | | Auto-scroll | 300ms delay after reveal | Let animation start before scrolling | | Step headers | Conversational tone | Guides user, feels less like a form | ## Not Included (YAGNI) - Progress indicator (single screen doesn't need it) - Save draft functionality (overkill for single-session flow) - Undo/redo beyond scrolling back up - Swipe gestures between steps (intentional friction for decisions) ## Dependencies - None - uses existing data providers and models - `AppDataProvider.shared.filterGames()` for sport availability ## Testing Considerations - Test progressive reveal with all 4 planning modes - Test sport availability graying with various date ranges - Test downstream reset when changing earlier selections - Test auto-scroll behavior on different screen sizes