change folders to the "feature" mindset
This commit is contained in:
@@ -49,19 +49,19 @@ struct SetListItem: View {
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
@Previewable @State var set = WorkoutItem(set: [
|
||||
WorkoutItem(Exercise("Squat")),
|
||||
WorkoutItem(Exercise("Squat")),
|
||||
WorkoutItem(Exercise("Squat"))])
|
||||
List {
|
||||
SetListItem(workout: Workout(name: "RR"), set: $set)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview("Empty Database") {
|
||||
@Previewable @State var set = WorkoutItem(set: [])
|
||||
List {
|
||||
SetListItem(workout: Workout(name: "RR"), set: $set)
|
||||
}
|
||||
}
|
||||
//#Preview {
|
||||
// @Previewable @State var set = WorkoutItem(set: [
|
||||
// WorkoutItem(Exercise("Squat")),
|
||||
// WorkoutItem(Exercise("Squat")),
|
||||
// WorkoutItem(Exercise("Squat"))])
|
||||
// List {
|
||||
// SetListItem(workout: Workout(name: "RR"), set: $set)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//#Preview("Empty Database") {
|
||||
// @Previewable @State var set = WorkoutItem(set: [])
|
||||
// List {
|
||||
// SetListItem(workout: Workout(name: "RR"), set: $set)
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -49,8 +49,7 @@ struct ContentView: View {
|
||||
Section {
|
||||
NavigationLink(
|
||||
destination: ActiveWorkoutSession(
|
||||
activeWorkoutSession: $activeWorkoutSession,
|
||||
activeWorkout: activeWorkoutSession.workout)
|
||||
activeWorkoutSession: $activeWorkoutSession)
|
||||
) {
|
||||
HStack {
|
||||
Label("Back to Session", systemImage: "memories")
|
||||
|
||||
@@ -75,7 +75,7 @@ struct WorkoutLog: View {
|
||||
ForEach(workoutSessions) { session in
|
||||
VStack(alignment: .leading) {
|
||||
Text(session.startDate.ISO8601Format())
|
||||
Text(session.workout.name)
|
||||
Text(session.name)
|
||||
.font(.subheadline)
|
||||
}
|
||||
}.onDelete(perform: deleteWorkoutSession)
|
||||
@@ -37,14 +37,14 @@ final class WorkoutItem: Nameable, Positionable {
|
||||
var id = UUID()
|
||||
var name: String
|
||||
var workout: Workout?
|
||||
// TODO: Make WorkoutItem a protocol so the type can be distinguished by the class type
|
||||
var workoutItemType: WorkoutItemType // Differentiates between exercise/rest/set
|
||||
var position: Int = 0
|
||||
var set: [WorkoutItem] = []
|
||||
|
||||
// Exercise has to be optional to allow Rest and Set to be a WorkoutItem (without being an Exercise).
|
||||
var exerciseData: Exercise? // Do Push-up | Run Marathon
|
||||
var plannedReps: Int // 8 times | 1 time
|
||||
var plannedValue: Double // With 10 | 42,187
|
||||
var exercise: Exercise // Do Push-up | Run Marathon
|
||||
var plannedReps: Int // 8 times | 1 time
|
||||
var plannedValue: Double // With 10 | 42,187
|
||||
var metric: ExerciseMetric? // kg (weight) | km (distance)
|
||||
|
||||
enum WorkoutItemType: Codable {
|
||||
@@ -54,7 +54,7 @@ final class WorkoutItem: Nameable, Positionable {
|
||||
}
|
||||
|
||||
init(_ exercise: Exercise) {
|
||||
self.exerciseData = exercise
|
||||
self.exercise = exercise
|
||||
self.workoutItemType = .exercise
|
||||
|
||||
// Push-up
|
||||
@@ -67,27 +67,25 @@ final class WorkoutItem: Nameable, Positionable {
|
||||
self.metric = exercise.metric
|
||||
}
|
||||
|
||||
init(set: [WorkoutItem] = []) {
|
||||
self.workoutItemType = .set
|
||||
self.name = "Set"
|
||||
self.plannedReps = 3
|
||||
self.plannedValue = 0
|
||||
set.forEach(addChild)
|
||||
}
|
||||
|
||||
// init(set: [WorkoutItem] = []) {
|
||||
// self.workoutItemType = .set
|
||||
// self.name = "Set"
|
||||
// self.plannedReps = 3
|
||||
// self.plannedValue = 0
|
||||
// set.forEach(addChild)
|
||||
// }
|
||||
// init(rest: Double) {
|
||||
// self.workoutItemType = .rest
|
||||
// self.name = "Rest"
|
||||
// self.plannedReps = 1
|
||||
// self.plannedValue = rest
|
||||
// self.metric = .time
|
||||
// }
|
||||
func addChild(_ child: WorkoutItem) {
|
||||
if self.workoutItemType == .set {
|
||||
self.set.append(child)
|
||||
}
|
||||
}
|
||||
|
||||
init(rest: Double) {
|
||||
self.workoutItemType = .rest
|
||||
self.name = "Rest"
|
||||
self.plannedReps = 1
|
||||
self.plannedValue = rest
|
||||
self.metric = .time
|
||||
}
|
||||
}
|
||||
|
||||
extension WorkoutItem {
|
||||
@@ -19,17 +19,17 @@ struct WorkoutItemLibrarySheet: View {
|
||||
var body: some View {
|
||||
Group {
|
||||
List {
|
||||
Section(header: Text("Utilities")) {
|
||||
AddItemButton(label: "Set") {
|
||||
addWorkoutItemtoWorkout(WorkoutItem(set: [
|
||||
WorkoutItem(Exercise("Set item 1")),
|
||||
WorkoutItem(Exercise("Set item 2"))
|
||||
]))
|
||||
}
|
||||
AddItemButton(label: "Rest") {
|
||||
addWorkoutItemtoWorkout(WorkoutItem(rest: 45))
|
||||
}
|
||||
}
|
||||
// Section(header: Text("Utilities")) {
|
||||
// AddItemButton(label: "Set") {
|
||||
// addWorkoutItemtoWorkout(WorkoutItem(set: [
|
||||
// WorkoutItem(Exercise("Set item 1")),
|
||||
// WorkoutItem(Exercise("Set item 2"))
|
||||
// ]))
|
||||
// }
|
||||
// AddItemButton(label: "Rest") {
|
||||
// addWorkoutItemtoWorkout(WorkoutItem(rest: 45))
|
||||
// }
|
||||
// }
|
||||
Section(header: Text("Excersises")) {
|
||||
if !exercises.isEmpty {
|
||||
ForEach(exercises) { exercise in
|
||||
@@ -34,18 +34,20 @@ struct WorkoutLibrary: View {
|
||||
NavigationLink {
|
||||
WorkoutDetail(activeWorkoutSession: $activeWorkoutSession, workout: workout)
|
||||
} label: {
|
||||
Button(action: {
|
||||
activeWorkoutSession = workout.start()
|
||||
}) {
|
||||
Image(systemName: "play.fill")
|
||||
.foregroundStyle(.green)
|
||||
}
|
||||
// TODO: Decide if icon should appear here/create custom view
|
||||
// Image(systemName: workout.workoutIconSystemName)
|
||||
// .foregroundStyle(workout.workoutIconColorName.color)
|
||||
Image(systemName: workout.workoutIconSystemName)
|
||||
.foregroundStyle(workout.workoutIconColorName.color)
|
||||
Text(workout.name)
|
||||
}
|
||||
.swipeActions(edge: .leading) {
|
||||
Button {
|
||||
activeWorkoutSession = workout.start()
|
||||
} label: {
|
||||
Label("Start", systemImage: "play")
|
||||
.tint(.green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.onDelete(perform: deleteWorkout)
|
||||
if filteredItems.isEmpty {
|
||||
ContentUnavailableView.search(text: searchText)
|
||||
@@ -37,12 +37,12 @@ struct WorkoutListItem: View {
|
||||
|
||||
#Preview {
|
||||
List {
|
||||
WorkoutListItem(Workout(name: "RR"), WorkoutItem(set: [
|
||||
WorkoutItem(Exercise("Squat")),
|
||||
WorkoutItem(Exercise("Squat")),
|
||||
WorkoutItem(Exercise("Squat"))]))
|
||||
// WorkoutListItem(Workout(name: "RR"), WorkoutItem(set: [
|
||||
// WorkoutItem(Exercise("Squat")),
|
||||
// WorkoutItem(Exercise("Squat")),
|
||||
// WorkoutItem(Exercise("Squat"))]))
|
||||
WorkoutListItem(Workout(name: "RR"), WorkoutItem(Exercise("Push-ups")))
|
||||
WorkoutListItem(Workout(name: "RR"), WorkoutItem(rest: 15))
|
||||
// WorkoutListItem(Workout(name: "RR"), WorkoutItem(rest: 15))
|
||||
WorkoutListItem(Workout(name: "RR"), WorkoutItem(Exercise("Push-ups")))
|
||||
WorkoutListItem(Workout(name: "RR"), WorkoutItem(Exercise("Sprint", .distance)))
|
||||
WorkoutListItem(Workout(name: "RR"), WorkoutItem(Exercise("Run", .time)))
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
|
||||
// This view can only be viewed, if there exists a WorkoutSession that can be considered active (a person working out).
|
||||
struct ActiveWorkoutSession: View {
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
|
||||
@@ -10,17 +11,14 @@ struct ActiveWorkoutSession: View {
|
||||
@Query(sort: \WorkoutSession.name) var workoutSessions: [WorkoutSession]
|
||||
@Binding var activeWorkoutSession: WorkoutSession?
|
||||
|
||||
@Query(sort: \Workout.name) var workouts: [Workout]
|
||||
@State var activeWorkout: Workout
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
List {
|
||||
Section(header: Text("Workout")) {
|
||||
Text(activeWorkout.name)
|
||||
Text(activeWorkoutSession!.name)
|
||||
}
|
||||
Section(header: Text("Exercises")) {
|
||||
ForEach(getActiveWorkoutItems(activeWorkout: activeWorkout)) { workoutItem in
|
||||
ForEach(activeWorkoutSession!.workoutSessionItems) { workoutItem in
|
||||
ActiveWorkoutSessionListItem(workoutItem: workoutItem)
|
||||
}
|
||||
}
|
||||
@@ -28,7 +26,6 @@ struct ActiveWorkoutSession: View {
|
||||
}
|
||||
.navigationTitle("Session")
|
||||
.toolbar {
|
||||
if (isWorkingOut) {
|
||||
Button(action: {
|
||||
isWorkingOut = false
|
||||
activeWorkoutSession?.stop()
|
||||
@@ -41,21 +38,6 @@ struct ActiveWorkoutSession: View {
|
||||
.bold()
|
||||
.fontDesign(.rounded)
|
||||
.tint(.red)
|
||||
}
|
||||
else {
|
||||
Button(action: {
|
||||
isWorkingOut = true
|
||||
activeWorkoutSession = activeWorkout.start()
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "play.fill")
|
||||
Text("Start")
|
||||
}
|
||||
}
|
||||
.bold()
|
||||
.fontDesign(.rounded)
|
||||
.tint(.green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +58,7 @@ struct ActiveWorkoutSession: View {
|
||||
@Previewable @State var workout = Workout.sampleData.first!
|
||||
|
||||
NavigationStack {
|
||||
ActiveWorkoutSession(activeWorkoutSession: $activeWorkoutSession, activeWorkout: workout)
|
||||
ActiveWorkoutSession(activeWorkoutSession: $activeWorkoutSession)
|
||||
}
|
||||
.onAppear {
|
||||
Defaults.shared.isWorkingOut = false
|
||||
@@ -8,14 +8,10 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ActiveWorkoutSessionListItem: View {
|
||||
var workoutItem: WorkoutItem
|
||||
var workoutItem: WorkoutSessionItem
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
switch workoutItem.workoutItemType {
|
||||
case .set:
|
||||
Text(workoutItem.name)
|
||||
case .exercise:
|
||||
Text(workoutItem.name)
|
||||
Spacer()
|
||||
Button(action: {
|
||||
@@ -24,17 +20,15 @@ struct ActiveWorkoutSessionListItem: View {
|
||||
Image(systemName: "info.circle")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
case .rest:
|
||||
Text("Pause")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
@Previewable @State var workoutSession = WorkoutSession(start: Workout.sampleData.first!)
|
||||
List {
|
||||
ForEach(WorkoutItem.sampleDataRecommendedRoutine) { item in
|
||||
ActiveWorkoutSessionListItem(workoutItem: item)
|
||||
ActiveWorkoutSessionListItem(workoutItem: WorkoutSessionItem(workoutSession: workoutSession, planned: item))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,16 @@ import SwiftData
|
||||
@Model
|
||||
final class WorkoutSession: Nameable {
|
||||
var id = UUID()
|
||||
var name = ""
|
||||
// The Workout is what *should* happen
|
||||
var workout: Workout {
|
||||
didSet {
|
||||
self.name = workout?.name ?? "Unknown Workout"
|
||||
}
|
||||
}
|
||||
var name: String
|
||||
// TODO: Think about if a refrence to the workout makes sense; a Workout could change.
|
||||
// var workout: Workout
|
||||
var workoutSessionItems: [WorkoutSessionItem] = []
|
||||
|
||||
init(start with: Workout) {
|
||||
self.workout = with
|
||||
init(start workout: Workout) {
|
||||
self.name = workout.name
|
||||
for workoutItem in workout.getWorkoutItems() {
|
||||
workoutSessionItems.append(WorkoutSessionItem(workoutSession: self, planned: workoutItem))
|
||||
}
|
||||
}
|
||||
|
||||
// State
|
||||
@@ -69,9 +69,7 @@ final class WorkoutSession: Nameable {
|
||||
}
|
||||
|
||||
func nextExercise() {
|
||||
if currentExercise < workout.getWorkoutItems().count - 1 {
|
||||
currentExercise += 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: -- Workout Information
|
||||
@@ -84,7 +82,7 @@ final class WorkoutSession: Nameable {
|
||||
}
|
||||
|
||||
func getTotalExerciseCount() -> Double {
|
||||
return Double(workout.getWorkoutItems().count)
|
||||
return 100.0
|
||||
}
|
||||
|
||||
func getCurrentExerciseIndex() -> Double {
|
||||
@@ -96,10 +94,10 @@ final class WorkoutSession: Nameable {
|
||||
}
|
||||
|
||||
func getCurrentExerciseName() -> String {
|
||||
return workout.getWorkoutItems()[Int(currentExercise)].name
|
||||
return "Hello"
|
||||
}
|
||||
|
||||
func getCurrentExerciseMetric() -> String {
|
||||
return String(workout.getWorkoutItems()[Int(currentExercise)].plannedReps)
|
||||
return "Hello"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// WorkoutSessionItem.swift
|
||||
// WorkoutsPlus
|
||||
//
|
||||
// Created by Felix Förtsch on 15.10.24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftData
|
||||
|
||||
@Model
|
||||
final class WorkoutSessionItem: Nameable, Positionable {
|
||||
var id = UUID()
|
||||
var position: Int
|
||||
var name: String
|
||||
|
||||
var workoutSession: WorkoutSession
|
||||
|
||||
var plannedReps: Int // 8 times | 1 time
|
||||
var plannedValue: Double // With 10 | 42,187
|
||||
var metric: ExerciseMetric? // kg (weight) | km (distance)
|
||||
|
||||
var actualReps: Int?
|
||||
var actualValue: Double?
|
||||
|
||||
init(workoutSession: WorkoutSession, planned: WorkoutItem) {
|
||||
self.workoutSession = workoutSession
|
||||
self.name = planned.exercise.name
|
||||
self.position = planned.position
|
||||
self.plannedReps = planned.plannedReps
|
||||
self.plannedValue = planned.plannedValue
|
||||
self.metric = planned.metric
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
//
|
||||
// WorkoutSessionItem.swift
|
||||
// WorkoutsPlus
|
||||
//
|
||||
// Created by Felix Förtsch on 15.10.24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftData
|
||||
|
||||
@Model
|
||||
final class WorkoutSessionItem {
|
||||
var id = UUID()
|
||||
|
||||
var workoutSession: WorkoutSession
|
||||
|
||||
var exerciseData: WorkoutItem
|
||||
var actualReps: Int?
|
||||
var actualValue: Double?
|
||||
|
||||
init(workoutSession: WorkoutSession, planned: WorkoutItem) {
|
||||
self.workoutSession = workoutSession
|
||||
self.exerciseData = planned
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ erDiagram
|
||||
Exercise 1 .. 0+ Equipment : uses
|
||||
Exercise 1 -- 0+ WorkoutItem : "provides data for"
|
||||
Workout 1 .. 0+ WorkoutItem : collects
|
||||
Workout 1 .. 0+ ViewModel : "provides data for"
|
||||
Workout 1 .. 0+ WorkoutSession : "starts"
|
||||
WorkoutItem 1 -- 1 WorkoutSessionItem : "provides data for"
|
||||
WorkoutSession 1 -- 1+ WorkoutSessionItem : collects
|
||||
ViewModel 1 -- 1+ WorkoutSession : "creates, starts"
|
||||
ContentView 1 -- 1 WorkoutSession : "holds onto"
|
||||
|
||||
Exercise {
|
||||
string name
|
||||
@@ -29,7 +29,7 @@ erDiagram
|
||||
int actualReps
|
||||
double actualValue
|
||||
}
|
||||
ViewModel {
|
||||
ContentView {
|
||||
Workout workout
|
||||
WorkoutSession workoutSession
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user