- 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>
5.1 KiB
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:
- Fetch game counts per sport for selected date range
- Use existing
AppDataProvider.shared.filterGames(sports:startDate:endDate:) - Cache results; re-fetch if dates change
- 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