Files
workoutsplus/WorkoutsPlus/Models/Workout.swift
T

130 lines
3.0 KiB
Swift

//
// Workout.swift
// WorkoutsPlus
//
// Created by Felix Förtsch on 10.08.24.
//
import SwiftUI
import SwiftData
@Model
final class Workout: Nameable {
static var systemImage = "figure.run.square.stack"
var id = UUID()
@Attribute(.unique) var name: String
// Icon
var workoutIconSystemName = "figure.run.square.stack"
var workoutIconColorName = ColorName.black
// Other properties and methods
var timestamp = Date.now
@Relationship(deleteRule: .cascade) var workoutItems: [WorkoutItem] = []
init(name: String) {
self.name = name
}
func add(workoutItem: WorkoutItem) {
self.workoutItems.append(workoutItem)
updateWorkoutItemsPositions()
}
func add(workoutItems: [WorkoutItem]) {
for workoutItem in workoutItems {
self.workoutItems.append(workoutItem)
}
updateWorkoutItemsPositions()
}
func moveWorkoutItem(from source: IndexSet, to destination: Int) {
workoutItems.move(fromOffsets: source, toOffset: destination)
updateWorkoutItemsPositions()
}
private func updateWorkoutItemsPositions() {
for (index, exercise) in workoutItems.enumerated() {
exercise.position = index
}
}
}
extension Workout {
// This enum maps the system colors to enable storing them with the SwiftData model data as String.
// See Workout.workoutIconColorName for a usage example.
// TODO: Use a Macro to reduce this horrible contraption to something maintainable.
enum ColorName: String, Codable {
case black
case blue
case cyan
case gray
case green
case indigo
case mint
case orange
case pink
case purple
case red
case white
case yellow
var color: Color {
switch self {
case .black: return .black
case .blue: return .blue
case .cyan: return .cyan
case .gray: return .gray
case .green: return .green
case .indigo: return .indigo
case .mint: return .mint
case .orange: return .orange
case .pink: return .pink
case .purple: return .purple
case .red: return .red
case .white: return .white
case .yellow: return .yellow
}
}
static func fromColor(_ color: Color) -> ColorName? {
switch color {
case .black: return .black
case .blue: return .blue
case .cyan: return .cyan
case .gray: return .gray
case .green: return .green
case .indigo: return .indigo
case .mint: return .mint
case .orange: return .orange
case .pink: return .pink
case .purple: return .purple
case .red: return .red
case .white: return .white
case .yellow: return .yellow
default: return nil
}
}
}
}
extension Workout {
private convenience init(name: String, exercises: [WorkoutItem]) {
self.init(name: name)
self.workoutItems = exercises
}
static let sampleData: Workout = {
var workout = Workout(name: "Recommended Routine")
for workoutItem in WorkoutItem.sampleData {
workout.add(workoutItem: workoutItem)
}
return workout
}()
}