- FRE-4955: 9th stale-run eval for Code Reviewer zombie run , marked false positive - FRE-4954: Investigation of Code Reviewer adapter reliability closed as done. Root cause: no heartbeat/adapter config. Fix tracked in FRE-4956 (CEO) - Broader CTO oversight: Senior Engineer bottleneck (19 in_review), Code Reviewer ghost runs awaiting FRE-4956 Co-Authored-By: Paperclip <noreply@paperclip.ing>
265 lines
10 KiB
Markdown
265 lines
10 KiB
Markdown
# 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.
|