diff --git a/tabatago-swift/TabataGo/Resources/Localizable.xcstrings b/tabatago-swift/TabataGo/Resources/Localizable.xcstrings index 14a9bbf..71a2437 100644 --- a/tabatago-swift/TabataGo/Resources/Localizable.xcstrings +++ b/tabatago-swift/TabataGo/Resources/Localizable.xcstrings @@ -543,6 +543,9 @@ } } } + }, + "All" : { + }, "Any challenges?" : { diff --git a/tabatago-swift/TabataGo/Views/Tabs/ProgramsTab.swift b/tabatago-swift/TabataGo/Views/Tabs/ProgramsTab.swift index b3dd805..ff0e28d 100644 --- a/tabatago-swift/TabataGo/Views/Tabs/ProgramsTab.swift +++ b/tabatago-swift/TabataGo/Views/Tabs/ProgramsTab.swift @@ -9,7 +9,7 @@ struct ProgramsTab: View { @State private var selectedProgram: WorkoutProgram? = nil @State private var searchText = "" - private var zones = ["upper", "lower", "full"] + private var zones = ["upper-body", "lower-body", "full-body"] private var levels = ["Beginner", "Intermediate", "Advanced"] private var filtered: [WorkoutProgram] { @@ -23,47 +23,25 @@ struct ProgramsTab: View { } } + /// Label for the level toolbar button. + private var levelMenuLabel: String { + selectedLevel ?? "All Levels" + } + var body: some View { NavigationStack { ScrollView { VStack(spacing: 16) { - // ── Zone Filter ─────────────────────────────── - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 10) { - FilterChip(label: "All", isSelected: selectedZone == nil) { - selectedZone = nil - } - ForEach(zones, id: \.self) { zone in - FilterChip( - label: zone.capitalized == "Full" ? "Full Body" : zone.capitalized, - isSelected: selectedZone == zone, - color: Theme.zoneColor(zone) - ) { - selectedZone = selectedZone == zone ? nil : zone - } - } + // ── Zone Segmented Control ──────────────────── + Picker("Body Zone", selection: $selectedZone) { + Text("All").tag(String?.none) + ForEach(zones, id: \.self) { zone in + Text(zone.replacingOccurrences(of: "-", with: " ").capitalized) + .tag(Optional(zone)) } - .padding(.horizontal) - } - - // ── Level Filter ────────────────────────────── - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 10) { - FilterChip(label: "All Levels", isSelected: selectedLevel == nil) { - selectedLevel = nil - } - ForEach(levels, id: \.self) { level in - FilterChip( - label: level, - isSelected: selectedLevel == level, - color: Theme.levelColor(level) - ) { - selectedLevel = selectedLevel == level ? nil : level - } - } - } - .padding(.horizontal) } + .pickerStyle(.segmented) + .padding(.horizontal) // ── Program Grid ────────────────────────────── if vm.isLoading { @@ -92,6 +70,27 @@ struct ProgramsTab: View { .navigationTitle("Programs") .navigationBarTitleDisplayMode(.large) .searchable(text: $searchText, prompt: "Search workouts...") + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Menu { + Button { + selectedLevel = nil + } label: { + Label("All Levels", systemImage: selectedLevel == nil ? "checkmark" : "") + } + Divider() + ForEach(levels, id: \.self) { level in + Button { + selectedLevel = selectedLevel == level ? nil : level + } label: { + Label(level, systemImage: selectedLevel == level ? "checkmark" : "") + } + } + } label: { + Label(levelMenuLabel, systemImage: "line.3.horizontal.decrease.circle\(selectedLevel != nil ? ".fill" : "")") + } + } + } .task { await vm.loadPrograms() } .refreshable { await vm.refresh() } .sheet(item: $selectedProgram) { program in @@ -101,32 +100,6 @@ struct ProgramsTab: View { } } -struct FilterChip: View { - let label: String - let isSelected: Bool - var color: Color = .primary - let action: () -> Void - - var body: some View { - Button(action: action) { - Text(label) - .font(.subheadline.weight(isSelected ? .semibold : .regular)) - .foregroundStyle(isSelected ? .white : .primary) - .padding(.horizontal, 14) - .padding(.vertical, 8) - .background { - if isSelected { - Capsule().fill(color == .primary ? Theme.brand : color) - } else { - Capsule().fill(.ultraThinMaterial) - } - } - } - .buttonStyle(.plain) - .animation(.spring(duration: 0.25), value: isSelected) - } -} - #Preview { ProgramsTab() .modelContainer(TabataGoSchema.previewContainer)