import SwiftUI struct TrainingPlanDetailView: View { let plan: TrainingPlan @State private var expandedWeek: Int? = 1 var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { planHeader progressSection planDescription weeklyWorkoutsSection } .padding(.horizontal) .padding(.bottom, 32) } .navigationTitle(plan.title) .navigationBarTitleDisplayMode(.inline) } private var planHeader: some View { VStack(spacing: 8) { HStack { Image(systemName: plan.planType.icon) .font(.system(size: 36)) .foregroundColor(plan.difficulty.color) VStack(alignment: .leading, spacing: 4) { Text(plan.planType.displayName) .font(.title2) .fontWeight(.bold) Text(plan.difficulty.displayName) .font(.subheadline) .foregroundColor(plan.difficulty.color) } Spacer() Toggle("", isOn: Binding( get: { plan.isFollowing }, set: { _ in } )) } Divider() HStack(spacing: 24) { statLabel(value: "\(plan.durationWeeks)", label: "Weeks") statLabel(value: "\(plan.progress.totalSessions)", label: "Sessions") statLabel(value: "\(Int(plan.progress.percentage))%", label: "Progress") } } .padding() .background(Color.secondary.opacity(0.1)) .cornerRadius(12) } private func statLabel(value: String, label: String) -> some View { VStack(spacing: 4) { Text(value) .font(.title3) .fontWeight(.bold) Text(label) .font(.caption) .foregroundColor(.secondary) } } private var progressSection: some View { VStack(alignment: .leading, spacing: 8) { Text("Overall Progress") .font(.headline) ProgressView(value: plan.progress.percentage) .tint(.blue) HStack { Text("\(plan.progress.completedWeeks)/\(plan.progress.totalWeeks) weeks") Spacer() Text("\(plan.progress.completedSessions)/\(plan.progress.totalSessions) sessions") } .font(.caption) .foregroundColor(.secondary) } } private var planDescription: some View { VStack(alignment: .leading, spacing: 4) { Text("About This Plan") .font(.headline) Text(plan.description) .font(.subheadline) .foregroundColor(.secondary) } } private var weeklyWorkoutsSection: some View { VStack(alignment: .leading, spacing: 12) { Text("Weekly Schedule") .font(.headline) ForEach(plan.weeklyWorkouts, id: \.id) { week in WeekCard(week: week, isExpanded: expandedWeek == week.weekNumber) { expandedWeek = expandedWeek == week.weekNumber ? nil : week.weekNumber } } } } } struct WeekCard: View { let week: WeeklyWorkout let isExpanded: Bool let toggleAction: () -> Void var body: some View { VStack(alignment: .leading, spacing: 8) { HStack { Text("Week \(week.weekNumber)") .font(.headline) Spacer() Text("\(week.completedSessions)/\(week.totalSessions)") .font(.caption) .foregroundColor(.secondary) Image(systemName: isExpanded ? "chevron.up" : "chevron.down") .font(.caption) } .padding(.vertical, 8) .padding(.horizontal) .background(Color.secondary.opacity(0.1)) .cornerRadius(8) .onTapGesture { toggleAction() } if isExpanded { ForEach(week.dailySessions) { session in DailySessionRow(session: session) } } } } } struct DailySessionRow: View { let session: DailySession var body: some View { HStack(spacing: 12) { Image(systemName: session.workoutType.icon) .font(.system(size: 20)) .foregroundColor(session.workoutType.color) .frame(width: 32) VStack(alignment: .leading, spacing: 2) { Text("\(session.dayOfWeek.displayName): \(session.workoutType.displayName)") .font(.subheadline) .fontWeight(.medium) if session.status == .completed { Text("Completed") .font(.caption) .foregroundColor(.green) } else if let distance = session.targetDistanceKm { Text("\(distance) km") .font(.caption) .foregroundColor(.secondary) } } Spacer() switch session.status { case .completed: Image(systemName: "checkmark.circle.fill") .foregroundColor(.green) case .inProgress: Image(systemName: "pause.circle.fill") .foregroundColor(.orange) case .skipped: Image(systemName: "xmark.circle.fill") .foregroundColor(.red) case .pending: Image(systemName: "circle") .foregroundColor(.secondary) } } .padding(.vertical, 4) } } #Preview { NavigationView { TrainingPlanDetailView(plan: samplePlan) } } private var samplePlan: TrainingPlan { TrainingPlan( id: "1", title: "5K Beginner Plan", description: "A 8-week plan designed to help beginners complete their first 5K race.", planType: .fiveK, durationWeeks: 8, difficulty: .beginner, startDate: Date(), endDate: Date().addingTimeInterval(8 * 7 * 24 * 3600), weeklyWorkouts: [ WeeklyWorkout(id: "w1", weekNumber: 1, dailySessions: [ DailySession(id: "s1", dayOfWeek: .monday, workoutType: .easyRun, title: "Easy Run", description: "Start with a comfortable pace", targetDistanceKm: 2.0, targetDurationMinutes: 20, targetPaceMinPerKm: 10, intensity: .easy, status: .completed), DailySession(id: "s2", dayOfWeek: .wednesday, workoutType: .rest, title: "Rest Day", description: "Recovery", targetDistanceKm: nil, targetDurationMinutes: nil, targetPaceMinPerKm: nil, intensity: .veryEasy, status: .completed), DailySession(id: "s3", dayOfWeek: .friday, workoutType: .easyRun, title: "Easy Run", description: "Build endurance", targetDistanceKm: 2.5, targetDurationMinutes: 25, targetPaceMinPerKm: 10, intensity: .easy, status: .pending), DailySession(id: "s4", dayOfWeek: .saturday, workoutType: .longRun, title: "Long Run", description: "Gradually increase distance", targetDistanceKm: 3.0, targetDurationMinutes: 30, targetPaceMinPerKm: 10, intensity: .moderate, status: .pending) ]) ], progress: PlanProgress(completedWeeks: 0, totalWeeks: 8, completedSessions: 2, totalSessions: 32, currentWeekNumber: 1), isFollowing: true, createdAt: Date() ) }