import SwiftUI struct AccountEditorView: View { @Environment(\.dismiss) private var dismiss @EnvironmentObject private var accountStore: AccountStore let account: Account? @State private var name = "" @State private var currencyCode = AppSettings.getOrCreate(in: CoreDataStack.shared.viewContext).currency @State private var inputMode: InputMode = .simple @State private var notificationFrequency: NotificationFrequency = .monthly @State private var customFrequencyMonths = 1 @State private var errorMessage: String? private let accountRepository = AccountRepository() var body: some View { NavigationStack { Form { Section { TextField("Account name", text: $name) Picker("Currency", selection: $currencyCode) { ForEach(CurrencyPicker.commonCodes, id: \.self) { code in Text(code).tag(code) } } } header: { Text("Account") } footer: { if let errorMessage { Text(errorMessage) .foregroundColor(.negativeRed) } } Section { Picker("Input Mode", selection: $inputMode) { ForEach(InputMode.allCases) { mode in Text(mode.title).tag(mode) } } } header: { Text("Input") } footer: { Text(inputMode.description) } } .navigationTitle(account == nil ? "New Account" : "Edit Account") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button("Cancel") { dismiss() } } ToolbarItem(placement: .navigationBarTrailing) { Button("Save") { saveAccount() } .disabled(!isValid) } } .onAppear { loadAccount() } .onChange(of: name) { _, _ in validateName() } } .presentationDetents([.large]) } private var isValid: Bool { let trimmed = name.trimmingCharacters(in: .whitespaces) return !trimmed.isEmpty && !isDuplicateName(trimmed) } private func validateName() { let trimmed = name.trimmingCharacters(in: .whitespaces) if trimmed.isEmpty { errorMessage = nil return } errorMessage = isDuplicateName(trimmed) ? "An account with this name already exists." : nil } private func isDuplicateName(_ trimmed: String) -> Bool { let normalized = trimmed.lowercased() return accountRepository.accounts.contains { existing in if let account, existing.id == account.id { return false } return (existing.name).trimmingCharacters(in: .whitespaces).lowercased() == normalized } } private func loadAccount() { guard let account else { return } name = account.name currencyCode = account.currencyCode ?? currencyCode inputMode = InputMode(rawValue: account.inputMode) ?? .simple notificationFrequency = .monthly customFrequencyMonths = 1 validateName() } private func saveAccount() { validateName() guard errorMessage == nil else { return } let trimmedName = name.trimmingCharacters(in: .whitespaces) let enforcedFrequency: NotificationFrequency = .monthly let enforcedCustomMonths = 1 if let account { accountRepository.updateAccount( account, name: trimmedName, currency: currencyCode, inputMode: inputMode, notificationFrequency: enforcedFrequency, customFrequencyMonths: enforcedCustomMonths ) } else { _ = accountRepository.createAccount( name: trimmedName, currency: currencyCode, inputMode: inputMode, notificationFrequency: enforcedFrequency, customFrequencyMonths: enforcedCustomMonths ) } accountStore.persistSelection() dismiss() } } #Preview { AccountEditorView(account: nil) .environmentObject(AccountStore(iapService: IAPService())) }