// // SplitDetailView.swift // Workouts // // Created by rzen on 7/25/25 at 3:27 PM. // // Copyright 2025 Rouslan Zenetl. All Rights Reserved. // import SwiftUI import SwiftData struct SplitDetailView: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) private var dismiss @State var split: Split @State private var showingAddSheet: Bool = false @State private var itemToEdit: Exercise? = nil @State private var itemToDelete: Exercise? = nil @State private var createdWorkout: Workout? = nil @State private var showingDeleteConfirmation: Bool = false var body: some View { NavigationStack { Form { Section (header: Text("What is a Split?")) { Text("A “split” is simply how you divide (or “split up”) your weekly training across different days. Instead of working every muscle group every session, you assign certain muscle groups, movement patterns, or training emphases to specific days.") .font(.caption) } Section (header: Text("Exercises")) { List { if let assignments = split.exercises, !assignments.isEmpty { let sortedAssignments = assignments.sorted(by: { $0.order == $1.order ? $0.name < $1.name : $0.order < $1.order }) ForEach(sortedAssignments) { item in ListItem( title: item.name, subtitle: "\(item.sets) × \(item.reps) × \(item.weight) lbs \(item.order)" ) .swipeActions { Button { itemToDelete = item } label: { Label("Delete", systemImage: "trash") } .tint(.red) Button { itemToEdit = item } label: { Label("Edit", systemImage: "pencil") } .tint(.indigo) } } .onMove(perform: { indices, destination in var exerciseArray = Array(sortedAssignments) exerciseArray.move(fromOffsets: indices, toOffset: destination) for (index, exercise) in exerciseArray.enumerated() { exercise.order = index } if let modelContext = exerciseArray.first?.modelContext { do { try modelContext.save() } catch { print("Error saving after reordering: \(error)") } } }) Button { showingAddSheet = true } label: { ListItem(title: "Add Exercise") } } else { Text("No exercises added yet.") Button(action: { showingAddSheet.toggle() }) { ListItem(title: "Add Exercise") } } } } Button ("Delete This Split", role: .destructive) { showingDeleteConfirmation = true } .tint(.red) } .navigationTitle("\(split.name)") } .toolbar { ToolbarItem(placement: .primaryAction) { Button("Start This Split") { let workout = Workout(start: Date(), end: Date(), split: split) modelContext.insert(workout) if let exercises = split.exercises { for assignment in exercises { let workoutLog = WorkoutLog( workout: workout, exerciseName: assignment.name, date: Date(), order: assignment.order, sets: assignment.sets, reps: assignment.reps, weight: assignment.weight ) modelContext.insert(workoutLog) } } try? modelContext.save() // Set the created workout to trigger navigation createdWorkout = workout } } } .navigationDestination(item: $createdWorkout, destination: { workout in WorkoutLogListView(workout: workout) }) .sheet (isPresented: $showingAddSheet) { ExercisePickerView(onExerciseSelected: { exerciseNames in let splitId = split.persistentModelID print("exerciseNames: \(exerciseNames)") if exerciseNames.count == 1 { itemToEdit = Exercise( split: split, exerciseName: exerciseNames.first ?? "Exercise.unnamed", order: 0, sets: 3, reps: 10, weight: 40 ) } else { for exerciseName in exerciseNames { var duplicateExercise: [Exercise]? = nil do { duplicateExercise = try modelContext.fetch(FetchDescriptor(predicate: #Predicate{ exercise in exerciseName == exercise.name && splitId == exercise.split?.persistentModelID })) } catch { print("ERROR: failed to fetch \(exerciseName)") } if let dup = duplicateExercise, dup.count > 0 { print("Skipping duplicate \(exerciseName) found \(dup.count) duplicate(s)") } else { print("Creating \(exerciseName) for \(split.name)") modelContext.insert(Exercise( split: split, exerciseName: exerciseName, order: 0, sets: 3, reps: 10, weight: 40 )) } } } try? modelContext.save() }, allowMultiSelect: true) } .sheet(item: $itemToEdit) { item in ExerciseAddEditView(model: item) } .confirmationDialog( "Delete Exercise?", isPresented: .constant(itemToDelete != nil), titleVisibility: .visible ) { Button("Delete", role: .destructive) { if let item = itemToDelete { withAnimation { modelContext.delete(item) try? modelContext.save() itemToDelete = nil } } } } .confirmationDialog( "Delete This Split?", isPresented: $showingDeleteConfirmation, titleVisibility: .visible ) { Button("Delete", role: .destructive) { modelContext.delete(split) try? modelContext.save() dismiss() } } } }