// // RoutineListView.swift // Workouts // // Created by rzen on 7/25/25 at 6:24 PM. // // Copyright 2025 Rouslan Zenetl. All Rights Reserved. // import SwiftUI import SwiftData /// The Routines library screen, pushed from Settings → Library: a plain list of /// routines, one row each. Tapping a row opens `RoutineDetailView`; long-pressing /// offers Delete (the sole routine-delete affordance); the toolbar's + adds a new /// routine. Starter routines are seeded automatically on the true first run /// (`SyncEngine.autoSeedIfEmpty`), so an empty library just invites creating one. struct RoutineListView: View { @Environment(SyncEngine.self) private var sync @Query(sort: \Routine.name) private var routines: [Routine] @State private var showingAddSheet = false @State private var routineToDelete: Routine? var body: some View { List { ForEach(routines) { routine in NavigationLink { RoutineDetailView(routine: routine) } label: { RoutineRow(routine: routine) } .contextMenu { Button(role: .destructive) { routineToDelete = routine } label: { Label("Delete", systemImage: "trash") } } } } .listStyle(.insetGrouped) .overlay { if routines.isEmpty { ContentUnavailableView( "No Routines Yet", systemImage: "dumbbell.fill", description: Text("Create a routine to organize your workout routine.") ) } } .navigationTitle("Routines") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { showingAddSheet = true } label: { Image(systemName: "plus") } .accessibilityLabel("Add Routine") } } .sheet(isPresented: $showingAddSheet) { RoutineAddEditView(routine: nil) } .confirmationDialog( "Delete Routine?", isPresented: Binding( get: { routineToDelete != nil }, set: { if !$0 { routineToDelete = nil } } ), titleVisibility: .visible, presenting: routineToDelete ) { routine in Button("Delete", role: .destructive) { Task { await sync.delete(routine: routine) } routineToDelete = nil } Button("Cancel", role: .cancel) { routineToDelete = nil } } message: { routine in Text("This will permanently delete \"\(routine.name)\" and all its exercises. Past workouts are kept.") } } } /// A single routine row: a small rounded-square badge (the routine's color at low /// opacity, its symbol tinted full-strength) beside the routine name and its /// exercise count. private struct RoutineRow: View { var routine: Routine var body: some View { HStack(spacing: 12) { Image(systemName: routine.systemImage) .font(.title3) .foregroundStyle(routineColor) .frame(width: 36, height: 36) .background(routineColor.opacity(0.12), in: RoundedRectangle(cornerRadius: 8)) VStack(alignment: .leading, spacing: 2) { Text(routine.name) .foregroundStyle(.primary) Text("\(routine.exercisesArray.count) exercises") .font(.caption) .foregroundStyle(.secondary) } } .padding(.vertical, 2) } private var routineColor: Color { Color.color(from: routine.color) } }