# Lendair iOS App ## Overview SwiftUI iOS app with modular feature architecture following MVVM pattern. ## Architecture ### MVVM Pattern - **View**: `Views/` - SwiftUI views for all feature screens - **ViewModel**: `ViewModels/` - State management and business logic - **Service**: `Services/` - Data layer with API communication - **Model**: `Models/` - Data structures and type definitions ### File Structure ``` Lendair/ ├── Models/ │ ├── Notification.swift # NotificationItem, NotificationType, API response types │ ├── TrainingPlan.swift # TrainingPlan, PlanType, WorkoutSession, PlanProgress │ ├── Race.swift # Race, RaceType, RaceFilter, API response types │ ├── FamilyPlan.swift # FamilyPlan, FamilyMember, LeaderboardMetric │ ├── BeginnerMode.swift # BeginnerConfig, Milestone, OnboardingStep │ ├── CommunityEvent.swift # CommunityEvent, EventType, RSVPStatus │ ├── Club.swift # Club, ClubType, ClubPrivacy, MembershipStatus, ClubMember │ └── Challenge.swift # Challenge, ChallengeType, ChallengeStatus, LeaderboardEntry ├── Services/ │ ├── NotificationService.swift # NotificationsServiceProtocol + implementation │ ├── TrainingPlanService.swift # TrainingPlanServiceProtocol + implementation │ ├── RaceService.swift # RaceServiceProtocol + implementation │ ├── FamilyPlanService.swift # FamilyPlanServiceProtocol + implementation │ ├── BeginnerModeService.swift # BeginnerModeServiceProtocol + implementation │ ├── CommunityEventService.swift # CommunityEventServiceProtocol + implementation │ ├── ClubService.swift # ClubServiceProtocol + implementation │ └── ChallengeService.swift # ChallengeServiceProtocol + implementation ├── ViewModels/ │ ├── NotificationsViewModel.swift │ ├── TrainingPlanViewModel.swift │ ├── RaceDiscoveryViewModel.swift │ ├── FamilyPlanViewModel.swift │ ├── BeginnerModeViewModel.swift │ ├── CommunityEventViewModel.swift │ ├── ClubViewModel.swift │ └── ChallengeViewModel.swift ├── Views/ │ ├── NotificationsView.swift │ ├── NotificationRowView.swift │ ├── TrainingPlanView.swift │ ├── TrainingPlanDetailView.swift │ ├── WorkoutSessionView.swift │ ├── RaceDiscoveryView.swift │ ├── RaceDetailView.swift │ ├── FamilyPlanView.swift │ ├── FamilyMemberView.swift │ ├── BeginnerModeView.swift │ ├── CommunityEventsView.swift │ ├── CommunityEventDetailView.swift │ ├── ClubsView.swift │ ├── ClubDetailView.swift │ ├── ChallengesView.swift │ ├── ChallengeDetailView.swift │ ├── MainTabView.swift │ └── SettingsView.swift ├── Models/ │ ├── Notification.swift │ ├── TrainingPlan.swift │ ├── Race.swift │ ├── FamilyPlan.swift │ ├── BeginnerMode.swift │ ├── CommunityEvent.swift │ ├── Club.swift │ ├── Challenge.swift │ └── AppSettings.swift └── README.md ``` ## Features ### Notifications - Notification list with pull-to-refresh - Mark-as-read (individual and bulk) - Type-specific icons and color coding - Empty state handling ### AI Training Plans (Phase 3 - Premium) - Personalized training plan generation (5K, 10K, Half/Full Marathon, Custom) - Difficulty levels: Beginner, Intermediate, Advanced, Elite - Weekly/daily workout scheduling with progressive overload - Plan progress tracking with session completion - Workout session execution with metrics display - Plan following/unfollowing ### Race Discovery (Phase 3 - Premium) - Browse upcoming races by location, distance, type, terrain - Race detail pages with registration links - Save/bookmark races - Filter by race type (Road, Trail, Track, Virtual) - Calendar integration ready ### Family Plans (Phase 3 - Premium) - Multi-member household management (up to 6 members) - Invite members via email - Individual progress tracking per member - Family leaderboard (distance, workouts, streak) - Subscription status management ### Beginner Mode (Phase 3 - Premium) - Guided onboarding with step tracking - Progressive levels: Just Started → Getting Comfortable → Building Consistency → Progressing - Milestone achievements and tracking - Contextual tips and educational content - Simplified metric display ### Community Events (Phase 3 - Premium) - Event discovery and creation - RSVP system (Going, Maybe, Not Going) - Event types: Group Run, Race, Workshop, Social, Charity, Training Camp - Participant tracking - Upcoming/ongoing/past event categorization ### Clubs (Phase 2 - Community) - Persistent community groups for runners and fitness enthusiasts - Club types: Running, Walking, Cycling, Triathlon, CrossFit, General Fitness - Privacy levels: Public, Private, Invitation Only - Member management with roles (Owner, Admin, Member) - Invite members via email - Club rules and capacity limits - Discover clubs by type, location, and privacy ### Challenges (Phase 2 - Community) - Time-bound competitive goals with progress tracking - Challenge types: Distance, Time, Frequency, Elevation, Calories, Streak - Real-time leaderboard with rankings - Progress submission and percentage tracking - Join/leave challenges - Create custom challenges with rules and targets - Active/upcoming/completed challenge categorization ### Settings/About (Phase 2 - Core) - App version and build number display - Links to Terms of Service and Privacy Policy documents - User logout functionality - Account deletion option - Profile information display ## Service Pattern All services follow the same architecture: - **Protocol**: `Sendable` protocol for testability - **Implementation**: Configurable `baseURL`, `URLSession`, `authToken` - **Error Handling**: Typed error enums with `LocalizedError` conformance - **HTTP Methods**: GET, POST, PATCH, DELETE via shared helpers ## API Endpoints ### Notifications | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/notifications?limit=&offset=` | List notifications | | PATCH | `/api/notifications/:id/read` | Mark single as read | | PATCH | `/api/notifications/read-all` | Mark all as read | ### Training Plans | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/training-plans?type=&difficulty=` | List plans | | GET | `/api/training-plans/:id` | Get plan detail | | POST | `/api/training-plans/generate` | Generate AI plan | | POST | `/api/training-plans/:id/follow` | Follow plan | | DELETE | `/api/training-plans/:id/follow` | Unfollow plan | | PATCH | `/api/training-plans/sessions/:id/status` | Update session status | ### Races | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/races?type=&terrain=&...` | List races with filters | | GET | `/api/races/:id` | Get race detail | | POST/DELETE | `/api/races/:id/save` | Save/unsave race | | POST | `/api/races/:id/register` | Register for race | ### Family Plans | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/family-plan` | Get family plan | | POST | `/api/family-plan/invite` | Invite member | | DELETE | `/api/family-plan/members/:id` | Remove member | | GET | `/api/family-plan/leaderboard?metric=` | Get leaderboard | ### Beginner Mode | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/beginner-mode/config` | Get config | | PATCH | `/api/beginner-mode/config` | Update config | | GET | `/api/beginner-mode/milestones` | Get milestone progress | ### Community Events | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/events?type=&rsvp=&...` | List events with filters | | GET | `/api/events/:id` | Get event detail | | POST | `/api/events` | Create event | | PATCH | `/api/events/:id` | Update event | | POST | `/api/events/:id/rsvp` | RSVP to event | ### Clubs | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/clubs?type=&privacy=&...` | List clubs with filters | | GET | `/api/clubs/:id` | Get club detail with members | | POST | `/api/clubs` | Create club | | PATCH | `/api/clubs/:id` | Update club | | POST | `/api/clubs/:id/join` | Join club | | POST | `/api/clubs/:id/leave` | Leave club | | POST | `/api/clubs/:id/invite` | Invite member by email | | DELETE | `/api/clubs/:id/members/:memberId` | Remove member | ### Challenges | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/challenges?type=&status=&...` | List challenges with filters | | GET | `/api/challenges/:id` | Get challenge detail with participants | | POST | `/api/challenges` | Create challenge | | PATCH | `/api/challenges/:id` | Update challenge | | POST | `/api/challenges/:id/join` | Join challenge | | POST | `/api/challenges/:id/leave` | Leave challenge | | GET | `/api/challenges/:id/leaderboard` | Get challenge leaderboard | | POST | `/api/challenges/:id/progress` | Submit progress | ### Settings/About | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/settings/version` | Get app version and build number | | GET | `/api/settings/legal/terms` | Get Terms of Service document | | GET | `/api/settings/legal/privacy` | Get Privacy Policy document | | POST | `/api/settings/logout` | User logout | | DELETE | `/api/settings/account` | Delete user account | ## Testing Tests are in `LendairTests/`: - Uses mock services conforming to feature protocols - ViewModel tests cover fetch, update, error handling, and computed properties - Model tests cover enum cases, display values, equality, and computed properties - Available test files: `NotificationServiceTests.swift`, `ClubServiceTests.swift`, `ChallengeServiceTests.swift` ## Usage ```swift // Feature views can be integrated into your navigation stack NavigationStack { ClubsView() } NavigationStack { ChallengesView() } NavigationStack { CommunityEventsView() } ``` ## Premium Features All Phase 3 features (Training Plans, Race Discovery, Family Plans, Beginner Mode, Community Events) require a Pro subscription ($9.99/mo). Subscription status should be verified via the existing SubscriptionService before feature access.