// // AddItemSheet.swift // SportsTime // // Sheet for adding/editing custom itinerary items // import SwiftUI struct AddItemSheet: View { @Environment(\.dismiss) private var dismiss @Environment(\.colorScheme) private var colorScheme let tripId: UUID let anchorDay: Int let anchorType: CustomItineraryItem.AnchorType let anchorId: String? let existingItem: CustomItineraryItem? var onSave: (CustomItineraryItem) -> Void @State private var selectedCategory: CustomItineraryItem.ItemCategory = .restaurant @State private var title: String = "" @State private var isSaving = false private var isEditing: Bool { existingItem != nil } var body: some View { NavigationStack { VStack(spacing: Theme.Spacing.lg) { // Category picker categoryPicker // Title input TextField("What's the plan?", text: $title) .textFieldStyle(.roundedBorder) .font(.body) Spacer() } .padding() .background(Theme.backgroundGradient(colorScheme)) .navigationTitle(isEditing ? "Edit Item" : "Add Item") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } } ToolbarItem(placement: .confirmationAction) { Button(isEditing ? "Save" : "Add") { saveItem() } .disabled(title.trimmingCharacters(in: .whitespaces).isEmpty || isSaving) } } .onAppear { if let existing = existingItem { selectedCategory = existing.category title = existing.title } } } } @ViewBuilder private var categoryPicker: some View { HStack(spacing: Theme.Spacing.md) { ForEach(CustomItineraryItem.ItemCategory.allCases, id: \.self) { category in CategoryButton( category: category, isSelected: selectedCategory == category ) { selectedCategory = category } } } } private func saveItem() { let trimmedTitle = title.trimmingCharacters(in: .whitespaces) guard !trimmedTitle.isEmpty else { return } isSaving = true let item: CustomItineraryItem if let existing = existingItem { item = CustomItineraryItem( id: existing.id, tripId: existing.tripId, category: selectedCategory, title: trimmedTitle, anchorType: existing.anchorType, anchorId: existing.anchorId, anchorDay: existing.anchorDay, createdAt: existing.createdAt, modifiedAt: Date() ) } else { item = CustomItineraryItem( tripId: tripId, category: selectedCategory, title: trimmedTitle, anchorType: anchorType, anchorId: anchorId, anchorDay: anchorDay ) } onSave(item) dismiss() } } // MARK: - Category Button private struct CategoryButton: View { let category: CustomItineraryItem.ItemCategory let isSelected: Bool let action: () -> Void var body: some View { Button(action: action) { VStack(spacing: 4) { Text(category.icon) .font(.title2) Text(category.label) .font(.caption2) } .frame(maxWidth: .infinity) .padding(.vertical, 12) .background(isSelected ? Theme.warmOrange.opacity(0.2) : Color.clear) .cornerRadius(8) .overlay( RoundedRectangle(cornerRadius: 8) .stroke(isSelected ? Theme.warmOrange : Color.secondary.opacity(0.3), lineWidth: isSelected ? 2 : 1) ) } .buttonStyle(.plain) } } #Preview { AddItemSheet( tripId: UUID(), anchorDay: 1, anchorType: .startOfDay, anchorId: nil, existingItem: nil ) { _ in } }