// // ExercisePickerView.swift // Workouts // // Created by rzen on 7/13/25 at 7:17 PM. // // Copyright 2025 Rouslan Zenetl. All Rights Reserved. // import SwiftUI struct ExercisePickerView: View { @Environment(\.dismiss) private var dismiss @State private var selectedExercises: Set = [] @State private var searchText = "" var onExerciseSelected: ([String]) -> Void var allowMultiSelect: Bool = false /// How many times each exercise already appears in the routine being edited — /// shown as a "×N" badge so picking it again (for interval-style segments like /// a treadmill's warmup/brisk/cooldown) doesn't read as a mistake. Keyed by /// library name. Empty for callers with no notion of "already in this routine". var inRoutineCounts: [String: Int] = [:] init(onExerciseSelected: @escaping ([String]) -> Void, allowMultiSelect: Bool = false, inRoutineCounts: [String: Int] = [:]) { self.onExerciseSelected = onExerciseSelected self.allowMultiSelect = allowMultiSelect self.inRoutineCounts = inRoutineCounts } /// The same curated, searchable grouping `ExerciseLibraryView` uses, so picking an /// exercise reads the same way as browsing the library. private var sections: [ExerciseCatalogSection] { ExerciseCatalog.sections(matching: searchText) } var body: some View { NavigationStack { Group { if sections.isEmpty { ContentUnavailableView.search(text: searchText) } else { List { ForEach(sections, id: \.title) { section in Section(section.title) { ForEach(section.names, id: \.self) { exerciseName in row(for: exerciseName) } } } } } } .navigationTitle("Exercise Library") .searchable( text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Name, category, or muscle") .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button("Cancel") { dismiss() } } if allowMultiSelect { ToolbarItem(placement: .navigationBarTrailing) { Button("Select") { if !selectedExercises.isEmpty { onExerciseSelected(Array(selectedExercises)) dismiss() } } .disabled(selectedExercises.isEmpty) } } } } } @ViewBuilder private func row(for exerciseName: String) -> some View { if allowMultiSelect { Button(action: { if selectedExercises.contains(exerciseName) { selectedExercises.remove(exerciseName) } else { selectedExercises.insert(exerciseName) } }) { HStack { Text(exerciseName) Spacer() if let count = inRoutineCounts[exerciseName], count > 0 { Text("×\(count)") .foregroundStyle(.secondary) } if selectedExercises.contains(exerciseName) { Image(systemName: "checkmark") .foregroundColor(.accentColor) } } } } else { Button(action: { onExerciseSelected([exerciseName]) dismiss() }) { HStack { Text(exerciseName) Spacer() if let count = inRoutineCounts[exerciseName], count > 0 { Text("×\(count)") .foregroundStyle(.secondary) } } } } } }