From df07e0a043d9c8e74b022b9ba998cd8453bcb308 Mon Sep 17 00:00:00 2001 From: rzen Date: Sat, 11 Jul 2026 11:39:29 -0400 Subject: [PATCH] Polish the New Workout form: segmented When on top, pushed routine list - When section moves to the top as a segmented control (3 or 4 segments depending on whether Now is offered) - Routine selection is a pushed list with each routine's symbol and color, checkmark on the current pick, select-and-pop - Goal "None" reserves the symbol slot so all goal labels align --- .../Views/Today/ScheduleAddEditView.swift | 75 ++++++++++++++++--- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/Workouts/Views/Today/ScheduleAddEditView.swift b/Workouts/Views/Today/ScheduleAddEditView.swift index 432a4a4..bcdb18d 100644 --- a/Workouts/Views/Today/ScheduleAddEditView.swift +++ b/Workouts/Views/Today/ScheduleAddEditView.swift @@ -111,6 +111,13 @@ struct ScheduleAddEditView: View { /// The live routine currently selected; nil when the stored id no longer resolves. private var selectedRoutine: Routine? { routines.first { $0.id == routineID } } + /// The When choices this presentation offers — "Now" only when adding on today. + /// Built as a list (rather than conditionally hiding a tag inside the Picker) + /// so the segmented control renders a clean 3- or 4-segment strip. + private var availableChoices: [WhenChoice] { + offersNow ? WhenChoice.allCases : WhenChoice.allCases.filter { $0 != .now } + } + private var canSave: Bool { guard selectedRoutine != nil else { return false } if when == .fixedDays { return !weekdays.isEmpty } @@ -120,11 +127,11 @@ struct ScheduleAddEditView: View { var body: some View { NavigationStack { Form { + whenSection routineSection if when != .now { goalSection } - whenSection } .navigationTitle(isEditing ? "Edit Workout" : "New Workout") .navigationBarTitleDisplayMode(.inline) @@ -148,9 +155,14 @@ struct ScheduleAddEditView: View { private var routineSection: some View { Section { - Picker("Routine", selection: $routineID) { - ForEach(routines) { routine in - Text(routine.name).tag(routine.id) + NavigationLink { + RoutinePickerList(routines: routines, selectedID: $routineID) + } label: { + HStack { + Text("Routine") + Spacer() + Text(selectedRoutine?.name ?? "Choose…") + .foregroundStyle(.secondary) } } } header: { @@ -165,7 +177,14 @@ struct ScheduleAddEditView: View { private var goalSection: some View { Section { Picker("Goal", selection: $goal) { - Text("None").tag(GoalKind?.none) + // A hidden symbol placeholder keeps "None" aligned with the + // symbol-bearing goal rows below it. + Label { + Text("None") + } icon: { + Image(systemName: "tag").hidden() + } + .tag(GoalKind?.none) ForEach(GoalKind.orderedCases()) { kind in Label(kind.displayName, systemImage: kind.systemImage) .foregroundStyle(Color.color(from: kind.colorName)) @@ -183,12 +202,11 @@ struct ScheduleAddEditView: View { private var whenSection: some View { Section { Picker("When", selection: $when) { - ForEach(WhenChoice.allCases) { choice in - if choice != .now || offersNow { - Text(choice.displayName).tag(choice) - } + ForEach(availableChoices) { choice in + Text(choice.displayName).tag(choice) } } + .pickerStyle(.segmented) switch when { case .now, .daily: @@ -260,3 +278,42 @@ struct ScheduleAddEditView: View { return (existing.map(\.order).max() ?? -1) + 1 } } + +// MARK: - Routine picker + +/// The pushed routine-selection list: each routine with its own symbol and color +/// (the Today board's row treatment), a checkmark on the current selection. +/// Tapping selects and pops back. +private struct RoutinePickerList: View { + let routines: [Routine] + @Binding var selectedID: String + @Environment(\.dismiss) private var dismiss + + var body: some View { + List(routines) { routine in + Button { + selectedID = routine.id + dismiss() + } label: { + HStack(spacing: 12) { + Image(systemName: routine.systemImage) + .font(.title3) + .foregroundStyle(Color.color(from: routine.color)) + .frame(width: 32) + Text(routine.name) + .foregroundStyle(.primary) + Spacer() + if routine.id == selectedID { + Image(systemName: "checkmark") + .fontWeight(.semibold) + .foregroundStyle(Color.accentColor) + } + } + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + } + .navigationTitle("Routine") + .navigationBarTitleDisplayMode(.inline) + } +}