FRE-4665: Implement Phase 3 AI training plans and premium features
- Models: TrainingPlan, Race, FamilyPlan, BeginnerMode, CommunityEvent - Services: 5 service layers with protocol-based architecture - ViewModels: 5 view models with @MainActor ObservableObject pattern - Views: 10 SwiftUI views for all Phase 3 features - Updated README with full Phase 3 documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
201
Lendair/Models/BeginnerMode.swift
Normal file
201
Lendair/Models/BeginnerMode.swift
Normal file
@@ -0,0 +1,201 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Beginner Configuration
|
||||
|
||||
struct BeginnerConfig: Codable {
|
||||
var isEnabled: Bool
|
||||
var currentLevel: BeginnerLevel
|
||||
var completedOnboardingSteps: [OnboardingStep]
|
||||
var milestones: [Milestone]
|
||||
var shownTips: Set<String>
|
||||
var preferredMetric: MetricType
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case isEnabled, currentLevel, completedOnboardingSteps, milestones, shownTips, preferredMetric
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Beginner Level
|
||||
|
||||
enum BeginnerLevel: String, CaseIterable, Codable {
|
||||
case justStarted
|
||||
case gettingComfortable
|
||||
case buildingConsistency
|
||||
case progressing
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .justStarted: return "Just Started"
|
||||
case .gettingComfortable: return "Getting Comfortable"
|
||||
case .buildingConsistency: return "Building Consistency"
|
||||
case .progressing: return "Progressing"
|
||||
}
|
||||
}
|
||||
|
||||
var requiredWorkouts: Int {
|
||||
switch self {
|
||||
case .justStarted: return 0
|
||||
case .gettingComfortable: return 5
|
||||
case .buildingConsistency: return 15
|
||||
case .progressing: return 30
|
||||
}
|
||||
}
|
||||
|
||||
var icon: String {
|
||||
switch self {
|
||||
case .justStarted: return "sparkles"
|
||||
case .gettingComfortable: return "leaf.fill"
|
||||
case .buildingConsistency: return "chart.bar.fill"
|
||||
case .progressing: return "bolt.fill"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Onboarding Step
|
||||
|
||||
enum OnboardingStep: String, CaseIterable, Codable {
|
||||
case profileSetup
|
||||
case goalSelection
|
||||
case firstActivity
|
||||
case inviteFriends
|
||||
case enableNotifications
|
||||
case choosePlan
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .profileSetup: return "Profile Setup"
|
||||
case .goalSelection: return "Set Goals"
|
||||
case .firstActivity: return "First Activity"
|
||||
case .inviteFriends: return "Invite Friends"
|
||||
case .enableNotifications: return "Enable Notifications"
|
||||
case .choosePlan: return "Choose a Plan"
|
||||
}
|
||||
}
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .profileSetup: return "Complete your profile with your name and photo"
|
||||
case .goalSelection: return "Tell us what you want to achieve"
|
||||
case .firstActivity: return "Record your first workout"
|
||||
case .inviteFriends: return "Invite friends to join Nessa"
|
||||
case .enableNotifications: return "Get reminders and updates"
|
||||
case .choosePlan: return "Pick a training plan to follow"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Milestone
|
||||
|
||||
struct Milestone: Identifiable, Codable {
|
||||
let id: String
|
||||
let title: String
|
||||
let description: String
|
||||
let icon: String
|
||||
let requirement: MilestoneRequirement
|
||||
var isCompleted: Bool
|
||||
var completedAt: Date?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, title, description, icon, requirement, isCompleted, completedAt
|
||||
}
|
||||
|
||||
init(
|
||||
id: String,
|
||||
title: String,
|
||||
description: String,
|
||||
icon: String,
|
||||
requirement: MilestoneRequirement,
|
||||
isCompleted: Bool,
|
||||
completedAt: Date?
|
||||
) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.description = description
|
||||
self.icon = icon
|
||||
self.requirement = requirement
|
||||
self.isCompleted = isCompleted
|
||||
self.completedAt = completedAt
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Milestone Requirement
|
||||
|
||||
struct MilestoneRequirement: Codable {
|
||||
let type: RequirementType
|
||||
let targetValue: Double
|
||||
}
|
||||
|
||||
enum RequirementType: String, CaseIterable, Codable {
|
||||
case totalDistanceKm
|
||||
case totalWorkouts
|
||||
case consecutiveDays
|
||||
case weeklyConsistency
|
||||
case firstWorkout
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .totalDistanceKm: return "Total Distance"
|
||||
case .totalWorkouts: return "Total Workouts"
|
||||
case .consecutiveDays: return "Streak"
|
||||
case .weeklyConsistency: return "Weekly Consistency"
|
||||
case .firstWorkout: return "First Workout"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Tip
|
||||
|
||||
struct BeginnerTip: Identifiable, Codable {
|
||||
let id: String
|
||||
let context: TipContext
|
||||
let title: String
|
||||
let message: String
|
||||
var isShown: Bool
|
||||
}
|
||||
|
||||
enum TipContext: String, CaseIterable, Codable {
|
||||
case beforeWorkout
|
||||
case afterWorkout
|
||||
case dailyReminder
|
||||
case progressUpdate
|
||||
case restDay
|
||||
}
|
||||
|
||||
// MARK: - Metric Type
|
||||
|
||||
enum MetricType: String, CaseIterable, Codable {
|
||||
case distance
|
||||
case duration
|
||||
case pace
|
||||
|
||||
var displayName: String {
|
||||
switch self {
|
||||
case .distance: return "Distance"
|
||||
case .duration: return "Duration"
|
||||
case .pace: return "Pace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - API Response Types
|
||||
|
||||
struct BeginnerConfigResponse: Decodable {
|
||||
let config: BeginnerConfig
|
||||
}
|
||||
|
||||
struct UpdateBeginnerConfigRequest: Encodable {
|
||||
var isEnabled: Bool?
|
||||
var completedOnboardingSteps: [OnboardingStep]?
|
||||
var preferredMetric: MetricType?
|
||||
}
|
||||
|
||||
struct UpdateBeginnerConfigResponse: Decodable {
|
||||
let success: Bool
|
||||
let config: BeginnerConfig
|
||||
}
|
||||
|
||||
struct MilestoneProgressResponse: Decodable {
|
||||
let milestones: [Milestone]
|
||||
let currentLevel: BeginnerLevel
|
||||
}
|
||||
Reference in New Issue
Block a user