Add 22 new UI tests across 8 test files covering Home, Schedule, Progress,
Settings, TabNavigation, TripSaving, and TripOptions. Add accessibility
identifiers to 11 view files for test element discovery. Fix sport chip
assertion logic (all sports start selected, tap deselects), scroll container
issues on iOS 26 nested ScrollViews, toggle interaction, and delete trip flow.
Update QA coverage map from 32 to 54 automated test cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive UI test infrastructure with Page Object pattern,
accessibility identifiers, UI test mode (--ui-testing, --reset-state,
--disable-animations), and 10 passing tests covering app launch, tab
navigation, trip wizard, trip saving, settings, schedule, and
accessibility at XXXL Dynamic Type. Also adds a 229-case QA test plan
Excel workbook for manual QA handoff.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add debug-only Marketing Video Mode toggle that enables hands-free
screen recording across the app: auto-scrolling Featured Trips carousel,
auto-filling trip wizard, smooth trip detail scrolling via CADisplayLink,
and trip options auto-sort with scroll.
Add Remotion marketing video project with 6 scene compositions using
image sequences extracted from screen recordings, varied phone entrance
animations, and deduped frames for smooth playback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all system colors (.secondary, Color(.secondarySystemBackground),
etc.) with Theme.textPrimary/textSecondary/textMuted/cardBackground/
surfaceGlow across 13 views. Remove PostHog debug logging. Add debug
settings for sample trips and hardcoded group poll preview.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add VoiceOver labels, hints, and element grouping across all 60+ views
- Add Reduce Motion support (Theme.Animation.prefersReducedMotion) to all animations
- Replace fixed font sizes with semantic Dynamic Type styles
- Hide decorative elements from VoiceOver with .accessibilityHidden(true)
- Add .minimumHitTarget() modifier ensuring 44pt touch targets
- Add AccessibilityAnnouncer utility for VoiceOver announcements
- Improve color contrast values in Theme.swift for WCAG AA compliance
- Extract CloudKitContainerConfig for explicit container identity
- Remove PostHog debug console log from AnalyticsManager
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use contentMargins on horizontal ScrollView so cards start inset but
scroll to screen edges. Pad headers and error states individually.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract AnimatedSportsBackground components to shared file and update
ThemedBackground modifier to conditionally show animations when enabled
in settings. All views using .themedBackground() now get animated background.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create shared TipsSection component for displaying planning tips
- Add TipsSection to all 22 home content variants
- Fix displayedTips population with onAppear in HomeView
- Add map buttons to GameRowCompact (opens stadium in Apple Maps)
- Add map buttons to TravelRowView (opens driving directions)
- Add map buttons to CustomItemRowView (opens location when GPS available)
- Add AppleMapsLauncher.openLocation() and openDirections() methods
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Only load polls once on initial view appearance, not every tab switch
- Only show spinner when there's no existing data (first load)
- Subsequent refreshes update content in place without showing spinner
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CustomItineraryItem domain model with sortOrder for ordering
- Add CKCustomItineraryItem CloudKit wrapper for persistence
- Create CustomItemService for CRUD operations
- Create CustomItemSubscriptionService for real-time sync
- Add AppDelegate for push notification handling
- Add AddItemSheet for creating/editing items
- Add CustomItemRow with drag handle
- Update TripDetailView with continuous vertical timeline
- Enable drag-to-reorder using .draggable/.dropDestination
- Add inline "Add" buttons after games and travel segments
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Increase card height from 160 to 175 and add extra bottom padding
to prevent date text from being cut off.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New design style combines the Classic layout with subtle animated
backgrounds featuring floating sports icons and route lines.
Animations are slow and unobtrusive to avoid distracting from content.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add `displayName` computed property to Trip model that always
generates city list with " → " separator for consistent display
- Replace all `trip.name` usages with `trip.displayName` in UI files
- Update SuggestedTripsGenerator to use " → " separator
- Update PDFGenerator to use displayName for PDF titles
This ensures all trip names display consistently regardless of when
the trip was created or how the name was originally stored.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Refactor TripDetailView to fetch games from AppDataProvider when not
provided, adding loading state indicator for better UX
- Update all callers (25+ HomeContent variants, TripOptionsView, HomeView)
to use simpler TripDetailView(trip:) initializer
- Fix PollDetailView sheet issue by using sheet(item:) instead of
sheet(isPresented:) to prevent blank screen on first tap
- Improve PollDetailView UI with Theme styling, icons, and better
visual hierarchy for share code, voting status, and results sections
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix suggested trips showing wrong sports for cross-country trips
- Remove quick start sections from home variants (Classic, Spotify)
- Remove dead quickActions code from HomeView
- Fix pace capsule animation in TripCreationView
- Add text wrapping to achievement descriptions
- Improve poll parsing with better error handling
- Various sharing system improvements
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add complete group trip polling feature allowing users to share trips
with friends for voting using Borda count scoring.
New components:
- TripPoll and PollVote domain models with share codes and rankings
- LocalTripPoll and LocalPollVote SwiftData models for persistence
- CKTripPoll and CKPollVote CloudKit record wrappers
- PollService actor for CloudKit CRUD operations and subscriptions
- PollCreation/Detail/Voting views and view models
- Deep link handling for sportstime://poll/{code} URLs
- Debug Pro status override toggle in Settings
Integration:
- HomeView shows polls section in My Trips
- SportsTimeApp registers SwiftData models and handles deep links
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add design style system with 23 unique home screen aesthetics:
- Classic (original SportsTime design, now default)
- 12 experimental styles (Brutalist, Luxury Editorial, etc.)
- 10 polished app-inspired styles (Flighty, SeatGeek, Apple Maps,
Things 3, Airbnb, Spotify, Nike Run Club, Fantastical, Strava,
Carrot Weather)
Includes settings picker to switch between styles and persists
selection via UserDefaults.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement freemium model with StoreKit 2:
- StoreManager singleton for purchase/restore/entitlements
- ProFeature enum defining gated features
- PaywallView and OnboardingPaywallView for upsell UI
- ProGate view modifier and ProBadge component
Feature gating:
- Trip saving: 1 free trip, then requires Pro
- PDF export: Pro only with badge indicator
- Progress tab: Shows ProLockedView for free users
- Settings: Subscription management section
Also fixes pre-existing test issues with StadiumVisit
and ItineraryOption model signature changes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add LoadingSpinner component with small/medium/large sizes using system gray color
- Add LoadingPlaceholder for skeleton loading states
- Add LoadingSheet for full-screen blocking overlays
- Replace ThemedSpinner/ThemedSpinnerCompact across all views
- Remove deprecated loading components from AnimatedComponents.swift
- Delete LoadingTextGenerator.swift
- Fix PhotoImportView layout to fill full width
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PlanningTips data model with 105 tips across 7 categories
- Wire random tips into HomeView (3 tips per session)
- Add TripOptionsGrouper for grouping by city/game count and mileage
- Update TripOptionsView with sectioned display when sorting
- Recommended and Best Efficiency remain flat lists
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Lock all maps to North America (no pan/zoom) in ProgressMapView and TripDetailView
- Sort saved trips by most cities (stops count)
- Filter cross-country trips to top 2 by stops on home screen
- Use LocationSearchSheet for Follow Team home location (consistent with must-stop)
- Initialize DateRangePicker to show selected dates on appear
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create unified sport selector grid used across Home (Quick Start),
Trip Creation, and Progress views. Removes duplicate button implementations
and ensures consistent grid layout with centered bottom row.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use GeometryReader to calculate button width as 1/4 of available space,
ensuring all buttons have the same size. Bottom row (MLS, WNBA, NWSL)
is now centered with WNBA in the middle.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace all custom Theme.FontSize values and hardcoded font sizes with
Apple's built-in text styles (.largeTitle, .title2, .headline, .body,
.subheadline, .caption, .caption2) to support accessibility scaling.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix same-day different-city validation in C2C routes (no more impossible
games like Detroit 7:30pm AND Milwaukee 8pm on the same day)
- Cap C2C trips at 14 days max with 3 middle stops, prefer shortest routes
- Add sport icon and name to game rows in trip itinerary
- Add horizontal scroll to route dots in suggested trip cards
- Allow swipe-to-dismiss on home sheet (trip planner still blocks)
- Generate travel segments for suggested trips
- Increase DAG route lookahead to 5 days for multi-day drives
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add local canonicalization pipeline (stadiums, teams, games) that generates
deterministic canonical IDs before CloudKit upload
- Fix CanonicalSyncService to use deterministic UUIDs from canonical IDs
instead of random UUIDs from CloudKit records
- Add SyncStadium/SyncTeam/SyncGame types to CloudKitService that preserve
canonical ID relationships during sync
- Add canonical ID field keys to CKModels for reading from CloudKit records
- Bundle canonical JSON files (stadiums_canonical, teams_canonical,
games_canonical, stadium_aliases) for consistent bootstrap data
- Update BootstrapService to prefer canonical format files over legacy format
This ensures all entities use consistent deterministic UUIDs derived from
their canonical IDs, preventing duplicate records when syncing CloudKit
data with bootstrapped local data.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Stadium Progress & Achievements:
- Add StadiumVisit and Achievement SwiftData models
- Create Progress tab with interactive map view
- Implement photo-based visit import with GPS/date matching
- Add achievement badges (count-based, regional, journey)
- Create shareable progress cards for social media
- Add canonical data infrastructure (stadium identities, team aliases)
- Implement score resolution from free APIs (MLB, NBA, NHL stats)
UI Improvements:
- Add ThemedSpinner and ThemedSpinnerCompact components
- Replace all ProgressView() with themed spinners throughout app
- Fix sport selection state not persisting when navigating away
Bug Fixes:
- Fix Coast to Coast trips showing only 1 city (validation issue)
- Fix stadium progress showing 0/0 (filtering issue)
- Remove "Stadium Quest" title from progress view
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add themed background to all tab views (Schedule, Settings, My Trips)
- Remove navigation titles from all screens (tab bar provides context)
- Add empty state to My Trips view
- Remove max driving hours slider from trip planner (available in Settings)
- Replace save menu with heart button overlay on trip detail map
- Add ability to unsave trips by tapping heart again
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Generate 8 suggested trips on app launch (2 per region: East, Central, West, Cross-Country)
- Each region has single-sport and multi-sport trip options
- Region classification based on stadium longitude
- Animated loading state with shimmer placeholders
- Loading messages use Foundation Models when available, fallback otherwise
- Tap card to view trip details in sheet
- Refresh button to regenerate trips
- Fixed-height cards with aligned top/bottom layout
New files:
- Region.swift: Geographic region enum with longitude classification
- LoadingTextGenerator.swift: On-device AI loading messages
- SuggestedTripsGenerator.swift: Trip generation service
- SuggestedTripCard.swift: Carousel card component
- LoadingTripsView.swift: Animated loading state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add initialSport parameter to TripCreationView
- Set selected sport when quick start button is tapped
- Auto-select that sport in trip planning view on appear
- Clear selection when sheet is dismissed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Theme:
- New teal/cyan/mint/pink/gold color palette replacing orange/cream
- Added Theme.swift, ViewModifiers.swift, AnimatedComponents.swift
Trip Creation:
- Removed Drive/Fly toggle (drive-only for now)
- Removed Lodging Type picker
- Renamed "Number of Stops" to "Number of Cities" with explanation
- Added explanation for "Find Other Sports Along Route"
- Removed staggered animation from trip options list
Bug Fix:
- Disabled AI route description generation (Foundation Models crashes
in iOS 26.2 Simulator due to NLLanguageRecognizer assertion failure)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Three-scenario planning engine (A: date range, B: selected games, C: directional routes)
- GeographicRouteExplorer with anchor game support for route exploration
- Shared ItineraryBuilder for travel segment calculation
- TravelEstimator for driving time/distance estimation
- SwiftUI views for trip creation and detail display
- CloudKit integration for schedule data
- Python scraping scripts for sports schedules
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>