wip
This commit is contained in:
@ -0,0 +1,140 @@
|
||||
//
|
||||
// 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()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user