// // MachineSettingsEditor.swift // Workouts // // Copyright 2025 Rouslan Zenetl. All Rights Reserved. // import SwiftUI /// Reusable editor for an ordered list of machine comfort settings (seat height, /// back-rest incline, pin position…). Drop it into a `Form`/`List` `Section`: it /// renders one `name`/`value` row per setting with swipe-to-delete and /// drag-to-reorder, plus an "Add Setting" row. Shared by the exercise add/edit /// screen (Surface 1) and the in-workout settings sheet (Surface 2). /// /// `MachineSetting` is a plain Codable wire type with no identity, so the editor /// keeps a per-row `UUID` internally (stable across edits/reorders, unlike an /// index) and mirrors changes back into the `settings` binding. The editor is the /// sole mutator of `settings` while it's on screen, so a one-way seed at init is /// enough — there's no external write to reconcile. struct MachineSettingsEditor: View { @Binding var settings: [MachineSetting] @State private var rows: [Row] init(settings: Binding<[MachineSetting]>) { _settings = settings _rows = State(initialValue: settings.wrappedValue.map(Row.init)) } var body: some View { ForEach($rows) { $row in HStack { TextField("Setting", text: $row.name) .textInputAutocapitalization(.words) TextField("Value", text: $row.value) .multilineTextAlignment(.trailing) .foregroundStyle(.secondary) .frame(maxWidth: 120) } } .onDelete { rows.remove(atOffsets: $0) } .onMove { rows.move(fromOffsets: $0, toOffset: $1) } Button { withAnimation { rows.append(Row(MachineSetting(name: "", value: ""))) } } label: { Label("Add Setting", systemImage: "plus.circle.fill") } // Mirror the identified rows back into the plain wire-type binding on every // edit/add/delete/reorder. .onChange(of: rows) { _, newRows in settings = newRows.map(\.setting) } } /// Session-only identified wrapper so `ForEach` and reordering have a stable /// identity that survives text edits. fileprivate struct Row: Identifiable, Equatable { let id = UUID() var name: String var value: String init(_ setting: MachineSetting) { name = setting.name value = setting.value } var setting: MachineSetting { MachineSetting(name: name, value: value) } } }