import SwiftUI struct GoalEditorView: View { @Environment(\.dismiss) private var dismiss @State private var name = "" @State private var targetAmount = "" @State private var targetDate = Date() @State private var includeTargetDate = false @State private var didLoadGoal = false let account: Account? let goal: Goal? private let goalRepository = GoalRepository() init(account: Account?, goal: Goal? = nil) { self.account = account self.goal = goal } var body: some View { NavigationStack { Form { Section { TextField("Goal name", text: $name) TextField("Target amount", text: $targetAmount) .keyboardType(.decimalPad) Toggle("Add target date", isOn: $includeTargetDate) if includeTargetDate { DatePicker("Target date", selection: $targetDate, displayedComponents: .date) .datePickerStyle(.graphical) } } header: { Text("Goal Details") } } .navigationTitle(goal == nil ? "New Goal" : "Edit Goal") .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button("Cancel") { dismiss() } } ToolbarItem(placement: .navigationBarTrailing) { Button("Save") { saveGoal() } .disabled(!isValid) } } } .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) .onAppear { guard let goal, !didLoadGoal else { return } name = goal.name ?? "" if let amount = goal.targetAmount?.decimalValue { targetAmount = NSDecimalNumber(decimal: amount).stringValue } if let target = goal.targetDate { includeTargetDate = true targetDate = target } didLoadGoal = true } } private var isValid: Bool { !name.trimmingCharacters(in: .whitespaces).isEmpty && parseDecimal(targetAmount) != nil } private func saveGoal() { guard let value = parseDecimal(targetAmount) else { return } if let goal { goalRepository.updateGoal( goal, name: name, targetAmount: value, targetDate: includeTargetDate ? targetDate : nil, clearTargetDate: !includeTargetDate ) } else { goalRepository.createGoal( name: name, targetAmount: value, targetDate: includeTargetDate ? targetDate : nil, account: account ) } dismiss() } private func parseDecimal(_ value: String) -> Decimal? { let cleaned = value .replacingOccurrences(of: ",", with: ".") .replacingOccurrences(of: " ", with: "") return Decimal(string: cleaned) } } #Preview { GoalEditorView(account: nil) }