Files
Sportstime/docs/plans/2026-01-12-trip-planning-enhancements-design.md
Trey t 3530b31cca docs: add 3 feature enhancement design plans
- Trip Planning Enhancements: progressive reveal single-screen wizard
- Progress Tracking Enhancements: multiple visits, games history, zoomable map
- Polish Enhancements: grouped sorting, 100+ planning tips

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 19:07:46 -06:00

5.1 KiB

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

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