// // ExerciseProgressControlView 2.swift // Workouts // // Created by rzen on 7/23/25 at 9:15 AM. // // Copyright 2025 Rouslan Zenetl. All Rights Reserved. // import SwiftUI struct ExerciseProgressControlView: View { let log: WorkoutLog @Environment(\.dismiss) private var dismiss @Environment(\.modelContext) private var modelContext @State private var exerciseStates: [ExerciseState] = [] @State private var currentStateIndex: Int = 0 @State private var elapsedSeconds: Int = 0 @State private var timer: Timer? = nil @State private var previousStateIndex: Int = 0 var body: some View { TabView(selection: $currentStateIndex) { ForEach(Array(exerciseStates.enumerated()), id: \.element.id) { index, state in if state.isIntro { ExerciseIntroCard(log: log) .tag(index) } else if state.isSet { ExerciseSetCard(set: state.setNumber ?? 0, elapsedSeconds: elapsedSeconds) .tag(index) } else if state.isRest { ExerciseRestCard(elapsedSeconds: elapsedSeconds) .tag(index) } else if state.isDone { ExerciseDoneCard(elapsedSeconds: elapsedSeconds, onComplete: completeExercise) .tag(index) } } } .tabViewStyle(.page(indexDisplayMode: .never)) .onChange(of: currentStateIndex) { oldValue, newValue in if oldValue != newValue { elapsedSeconds = 0 moveToNextState() } } .onAppear { setupExerciseStates() currentStateIndex = log.currentStateIndex ?? 0 startTimer() } .onDisappear { stopTimer() } } private func setupExerciseStates() { var states: [ExerciseState] = [] states.append(.intro) for i in 1...log.sets { states.append(.set(number: i)) if i < log.sets { states.append(.rest(afterSet: i)) } } states.append(.done) exerciseStates = states } private func startTimer() { timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in elapsedSeconds += 1 // Check if we need to provide haptic feedback during rest periods if currentStateIndex >= 0 && currentStateIndex < exerciseStates.count { let currentState = exerciseStates[currentStateIndex] if currentState.isRest { provideRestHapticFeedback() } else if currentState.isDone && elapsedSeconds >= 10 { // Auto-complete after 10 seconds on the DONE state completeExercise() } } } } private func stopTimer() { timer?.invalidate() timer = nil } private func moveToNextState() { if currentStateIndex < exerciseStates.count - 1 { elapsedSeconds = 0 withAnimation { currentStateIndex += 1 log.currentStateIndex = currentStateIndex log.elapsedSeconds = elapsedSeconds log.status = .inProgress try? modelContext.save() } } else { // We've reached the end (DONE state) completeExercise() } } private func provideRestHapticFeedback() { // Provide haptic feedback based on elapsed time if elapsedSeconds % 60 == 0 && elapsedSeconds > 0 { // Triple tap every 60 seconds HapticFeedback.tripleTap() } else if elapsedSeconds % 30 == 0 && elapsedSeconds > 0 { // Double tap every 30 seconds HapticFeedback.doubleTap() } else if elapsedSeconds % 10 == 0 && elapsedSeconds > 0 { // Single tap every 10 seconds HapticFeedback.success() } } private func completeExercise() { // Update the workout log status to completed log.status = .completed // reset index in case we wish to re-run the exercise log.currentStateIndex = 0 // Provide "tada" haptic feedback HapticFeedback.tripleTap() // Dismiss this view to return to WorkoutDetailView dismiss() } }