201 lines
5.9 KiB
Swift
201 lines
5.9 KiB
Swift
import SwiftUI
|
|
|
|
struct GymsView: View {
|
|
@EnvironmentObject var dataManager: ClimbingDataManager
|
|
@State private var showingAddGym = false
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
VStack {
|
|
if dataManager.gyms.isEmpty {
|
|
EmptyGymsView()
|
|
} else {
|
|
GymsList()
|
|
}
|
|
}
|
|
.navigationTitle("Gyms")
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigationBarTrailing) {
|
|
Button("Add") {
|
|
showingAddGym = true
|
|
}
|
|
}
|
|
}
|
|
.sheet(isPresented: $showingAddGym) {
|
|
AddEditGymView()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct GymsList: View {
|
|
@EnvironmentObject var dataManager: ClimbingDataManager
|
|
@State private var gymToDelete: Gym?
|
|
@State private var gymToEdit: Gym?
|
|
|
|
var body: some View {
|
|
List(dataManager.gyms, id: \.id) { gym in
|
|
NavigationLink(destination: GymDetailView(gymId: gym.id)) {
|
|
GymRow(gym: gym)
|
|
}
|
|
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
|
Button(role: .destructive) {
|
|
gymToDelete = gym
|
|
} label: {
|
|
Label("Delete", systemImage: "trash")
|
|
}
|
|
|
|
Button {
|
|
gymToEdit = gym
|
|
} label: {
|
|
HStack {
|
|
Image(systemName: "pencil")
|
|
Text("Edit")
|
|
}
|
|
}
|
|
.tint(.blue)
|
|
}
|
|
}
|
|
.alert("Delete Gym", isPresented: .constant(gymToDelete != nil)) {
|
|
Button("Cancel", role: .cancel) {
|
|
gymToDelete = nil
|
|
}
|
|
Button("Delete", role: .destructive) {
|
|
if let gym = gymToDelete {
|
|
dataManager.deleteGym(gym)
|
|
gymToDelete = nil
|
|
}
|
|
}
|
|
} message: {
|
|
Text(
|
|
"Are you sure you want to delete this gym? This will also delete all associated problems and sessions."
|
|
)
|
|
}
|
|
.sheet(item: $gymToEdit) { gym in
|
|
AddEditGymView(gymId: gym.id)
|
|
}
|
|
}
|
|
}
|
|
|
|
struct GymRow: View {
|
|
let gym: Gym
|
|
@EnvironmentObject var dataManager: ClimbingDataManager
|
|
|
|
private var problemCount: Int {
|
|
dataManager.problems(forGym: gym.id).count
|
|
}
|
|
|
|
private var sessionCount: Int {
|
|
dataManager.sessions(forGym: gym.id).count
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
// Header
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text(gym.name)
|
|
.font(.headline)
|
|
.fontWeight(.bold)
|
|
|
|
if let location = gym.location, !location.isEmpty {
|
|
Text(location)
|
|
.font(.subheadline)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
}
|
|
|
|
// Climb Types
|
|
if !gym.supportedClimbTypes.isEmpty {
|
|
ScrollView(.horizontal, showsIndicators: false) {
|
|
HStack(spacing: 8) {
|
|
ForEach(gym.supportedClimbTypes, id: \.self) { climbType in
|
|
Text(climbType.displayName)
|
|
.font(.caption)
|
|
.padding(.horizontal, 8)
|
|
.padding(.vertical, 4)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 8)
|
|
.fill(.blue.opacity(0.1))
|
|
)
|
|
.foregroundColor(.blue)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Difficulty Systems
|
|
if !gym.difficultySystems.isEmpty {
|
|
Text(
|
|
"Systems: \(gym.difficultySystems.map { $0.displayName }.joined(separator: ", "))"
|
|
)
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
|
|
// Stats
|
|
HStack {
|
|
Label("\(problemCount)", systemImage: "star.fill")
|
|
.font(.caption)
|
|
.foregroundColor(.orange)
|
|
|
|
Label("\(sessionCount)", systemImage: "play.fill")
|
|
.font(.caption)
|
|
.foregroundColor(.green)
|
|
|
|
Spacer()
|
|
}
|
|
|
|
// Notes preview
|
|
if let notes = gym.notes, !notes.isEmpty {
|
|
Text(notes)
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
.lineLimit(2)
|
|
}
|
|
}
|
|
.padding(.vertical, 8)
|
|
}
|
|
}
|
|
|
|
struct EmptyGymsView: View {
|
|
@State private var showingAddGym = false
|
|
|
|
var body: some View {
|
|
VStack(spacing: 20) {
|
|
Spacer()
|
|
|
|
Image(systemName: "location.fill")
|
|
.font(.system(size: 60))
|
|
.foregroundColor(.secondary)
|
|
|
|
VStack(spacing: 8) {
|
|
Text("No Gyms Added")
|
|
.font(.title2)
|
|
.fontWeight(.bold)
|
|
|
|
Text("Add your favorite climbing gyms to start tracking your progress!")
|
|
.font(.body)
|
|
.foregroundColor(.secondary)
|
|
.multilineTextAlignment(.center)
|
|
.padding(.horizontal)
|
|
}
|
|
|
|
Button("Add Gym") {
|
|
showingAddGym = true
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
.controlSize(.large)
|
|
|
|
Spacer()
|
|
}
|
|
.sheet(isPresented: $showingAddGym) {
|
|
AddEditGymView()
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
GymsView()
|
|
.environmentObject(ClimbingDataManager.preview)
|
|
}
|