feat: initial project scaffold with Watch companion app

This commit is contained in:
2026-08-04 17:28:06 +02:00
parent adbb4f01c5
commit 43b6467efb
65 changed files with 6361 additions and 166 deletions
+109
View File
@@ -0,0 +1,109 @@
import SwiftUI
struct ActiveWorkoutView: View {
@ObservedObject var workoutManager: WorkoutManager
var body: some View {
VStack(spacing: 8) {
if workoutManager.isResting {
RestView(workoutManager: workoutManager)
} else {
SwimView(workoutManager: workoutManager)
}
}
.padding()
}
}
struct SwimView: View {
@ObservedObject var workoutManager: WorkoutManager
var body: some View {
VStack(spacing: 6) {
if let workout = workoutManager.selectedWorkout,
workoutManager.currentSetIndex < workout.sets.count {
let currentSet = workout.sets[workoutManager.currentSetIndex]
Text("Set \(workoutManager.currentSetIndex + 1)/\(workout.sets.count)")
.font(.caption2)
.foregroundColor(.secondary)
Text(currentSet.stroke)
.font(.headline)
.foregroundColor(.cyan)
Text("Rep \(workoutManager.currentRep + 1)/\(currentSet.repCount)")
.font(.subheadline)
Text("\(currentSet.distancePerRep)m")
.font(.system(size: 36, weight: .bold, design: .rounded))
.foregroundColor(.cyan)
}
Text(formatTime(workoutManager.elapsedSeconds))
.font(.system(.title, design: .monospaced))
if workoutManager.heartRate > 0 {
HStack(spacing: 4) {
Image(systemName: "heart.fill")
.foregroundColor(.red)
.font(.caption)
Text("\(Int(workoutManager.heartRate))")
.font(.caption)
}
}
Button {
workoutManager.completeLap()
} label: {
Text("Complete Lap")
.font(.headline)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.tint(.cyan)
Button("End") {
workoutManager.endWorkout()
}
.font(.caption)
.foregroundColor(.red)
}
}
private func formatTime(_ seconds: TimeInterval) -> String {
let mins = Int(seconds) / 60
let secs = Int(seconds) % 60
return String(format: "%d:%02d", mins, secs)
}
}
struct RestView: View {
@ObservedObject var workoutManager: WorkoutManager
var body: some View {
VStack(spacing: 12) {
Text("Rest")
.font(.headline)
.foregroundColor(.secondary)
Text(formatTime(workoutManager.restTimeRemaining))
.font(.system(size: 44, weight: .bold, design: .monospaced))
.foregroundColor(.cyan)
if let workout = workoutManager.selectedWorkout,
workoutManager.currentSetIndex + 1 < workout.sets.count {
let nextSet = workout.sets[workoutManager.currentSetIndex + 1]
Text("Next: \(nextSet.stroke) \(nextSet.distancePerRep)m")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
private func formatTime(_ seconds: TimeInterval) -> String {
let mins = Int(seconds) / 60
let secs = Int(seconds) % 60
return String(format: "%d:%02d", mins, secs)
}
}