import SwiftUI import UIKit // MARK: - CARD DETAIL VIEW struct CardDetailView: View { @State var card: SavedCard @ObservedObject var vm: CollectionViewModel var scannerVM: ScannerViewModel var isNewEntry: Bool = false @Environment(\.dismiss) var dismiss @FocusState private var isInputActive: Bool @State private var displayImage: UIImage? @State private var originalCard: SavedCard? @State private var showContributionAlert = false let conditions = ["Near Mint (NM)", "Excellent (EX)", "Played (PL)", "Damaged"] let foilTypes = ["None", "Traditional", "Etched", "Galaxy", "Surge", "Textured", "Oil Slick", "Halo", "Confetti", "Neon Ink", "Other"] var body: some View { NavigationStack { Form { Section { HStack { Spacer(); if let img = displayImage { Image(uiImage: img).resizable().scaledToFit().frame(height: 300).cornerRadius(12).shadow(radius: 5) } else { ProgressView().frame(height: 300) }; Spacer() }.listRowBackground(Color.clear) } Section(header: Text("Card Info")) { TextField("Card Name", text: $card.name) HStack { TextField("Set", text: $card.setCode).autocorrectionDisabled() TextField("Number", text: $card.collectorNumber).keyboardType(.numbersAndPunctuation) } Toggle("Serialized Card", isOn: Binding(get: { card.isSerialized ?? false }, set: { card.isSerialized = $0 })) Picker("Condition", selection: $card.condition) { ForEach(conditions, id: \.self) { Text($0) } } Picker("Foil / Finish", selection: $card.foilType) { ForEach(foilTypes, id: \.self) { Text($0) } } } Section(header: Text("Grading (Slab Mode)")) { Toggle("Is Graded?", isOn: Binding(get: { card.gradingService != nil }, set: { if !$0 { card.gradingService = nil; card.grade = nil; card.certNumber = nil } else { card.gradingService = "PSA"; card.grade = "10"; card.isCustomValuation = true } })) if card.gradingService != nil { TextField("Service (e.g. PSA)", text: Binding(get: { card.gradingService ?? "" }, set: { card.gradingService = $0 })) TextField("Grade (e.g. 10)", text: Binding(get: { card.grade ?? "" }, set: { card.grade = $0 })) TextField("Cert #", text: Binding(get: { card.certNumber ?? "" }, set: { card.certNumber = $0 })) } } Section(header: Text("Valuation")) { Toggle("Custom Price", isOn: $card.isCustomValuation) if card.isCustomValuation { TextField("Value (\(vm.selectedCurrency.symbol))", value: Binding(get: { card.currentValuation ?? 0.0 }, set: { card.currentValuation = $0 }), format: .number).keyboardType(.decimalPad).focused($isInputActive) } else { if vm.isConnected { if let val = card.currentValuation, card.currencyCode == vm.selectedCurrency.rawValue { Text("Market Price: \(vm.selectedCurrency.symbol)\(val, specifier: "%.2f")").foregroundColor(.gray) } else { Text("Market Price: Updating...").foregroundColor(.gray) } } else { Text("Market Price: Unavailable (Offline)").foregroundColor(.red) } } } } .navigationTitle("Edit Card") .scrollDismissesKeyboard(.interactively) .toolbar { ToolbarItemGroup(placement: .keyboard) { Spacer(); Button("Done") { isInputActive = false } } Button("Save") { isInputActive = false; saveChanges() } } .task { if let img = await Task.detached(priority: .userInitiated, operation: { return ImageManager.load(name: card.imageFileName) }).value { self.displayImage = img } if originalCard == nil { originalCard = card } } .alert("Contribute Correction?", isPresented: $showContributionAlert) { Button("Send Image", role: .none) { scannerVM.uploadCorrection(image: displayImage, card: card, original: originalCard); finishSave() } Button("No Thanks", role: .cancel) { finishSave() } } message: { Text("You changed the card details. Would you like to send the image to help train the AI?") } } } func saveChanges() { let hasChanges = card.name != originalCard?.name || card.setCode != originalCard?.setCode || card.condition != originalCard?.condition || card.foilType != originalCard?.foilType if hasChanges && !AppConfig.isTrainingOptIn && !isNewEntry { showContributionAlert = true } else { if hasChanges && AppConfig.isTrainingOptIn && !isNewEntry { scannerVM.uploadCorrection(image: displayImage, card: card, original: originalCard) } finishSave() } } func finishSave() { if isNewEntry { vm.saveManualCard(card) } else { vm.updateCardDetails(card) } dismiss() } }