// // EditFuelLogView.swift // Gas Man // // Created by Kameron Kenny on 3/19/25. // import SwiftUI import CoreData struct EditFuelLogView: View { @Environment(\.managedObjectContext) private var viewContext @Environment(\.dismiss) var dismiss @ObservedObject var fuelLog: FuelLog // Form fields for fuel log @State private var date = Date() @State private var odometer = "" @State private var fuelVolume: String = "" @State private var cost = "" @State private var locationCoordinates = "" @State private var locationName = "" @State private var selectedOctane: Int = 87 @State private var pricePerGalon = "" // Full Tank toggle @State private var fullTank: Bool = true // Allowed octane options let octaneOptions = [87, 89, 91, 92, 93, 95] // For calculation update control @State private var isUpdatingCalculation = false var body: some View { NavigationView { Form { Section(header: Text("Fuel Log Details")) { DatePicker("Date", selection: $date, displayedComponents: [.date, .hourAndMinute]) HStack { Text("Odometer:") TextField("", text: $odometer) .keyboardType(.decimalPad) .multilineTextAlignment(.trailing) } HStack { Text("Gallons:") TextField("", text: $fuelVolume) .keyboardType(.decimalPad) .multilineTextAlignment(.trailing) .onChange(of: fuelVolume) { newValue in if !newValue.contains(".") { let formatted = formatInput(newValue) if formatted != newValue { fuelVolume = formatted } } updateCalculatedValues() } } HStack { Text("Price/Gal:") TextField("", text: $pricePerGalon) .keyboardType(.decimalPad) .multilineTextAlignment(.trailing) .onChange(of: pricePerGalon) { newValue in if !newValue.contains(".") { let formatted = formatInput(newValue) if formatted != newValue { pricePerGalon = formatted } } updateCalculatedValues() } } HStack { Text("Cost:") TextField("", text: $cost) .keyboardType(.decimalPad) .multilineTextAlignment(.trailing) .onChange(of: cost) { _ in updateCalculatedValues() } } Toggle("Full Tank", isOn: $fullTank) .toggleStyle(SwitchToggleStyle(tint: .blue)) Button("Get Current Location") { // Optionally trigger location update } if !locationCoordinates.isEmpty { Text("Coordinates: \(locationCoordinates)") } TextField("Location Name", text: $locationName) .multilineTextAlignment(.trailing) Picker("Octane", selection: $selectedOctane) { ForEach(octaneOptions, id: \.self) { option in Text("\(option)").tag(option) } } .pickerStyle(MenuPickerStyle()) } } .navigationTitle("Edit Fuel Log") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Save") { saveFuelLog() } } ToolbarItem(placement: .navigationBarLeading) { Button("Cancel") { dismiss() } } } } .onAppear { loadFuelLogData() } } private func loadFuelLogData() { date = fuelLog.date ?? Date() odometer = String(format: "%.0f", fuelLog.odometer) fuelVolume = String(format: "%.3f", fuelLog.fuelVolume) cost = String(format: "%.2f", fuelLog.cost) pricePerGalon = String(format: "%.3f", fuelLog.pricePerGalon) fullTank = fuelLog.fullTank locationCoordinates = fuelLog.locationCoordinates ?? "" locationName = fuelLog.locationName ?? "" selectedOctane = Int(fuelLog.octane) } private func roundToThree(_ value: Double) -> Double { return (value * 1000).rounded() / 1000 } private func roundToTwo(_ value: Double) -> Double { return (value * 100).rounded() / 100 } private func updateCalculatedValues() { guard !isUpdatingCalculation else { return } isUpdatingCalculation = true let fuel = Double(fuelVolume) let costVal = Double(cost) let price = Double(pricePerGalon) if let f = fuel, let p = price, f > 0 { let computedCost = roundToTwo(f * p) let computedCostStr = String(format: "%.2f", computedCost) if cost != computedCostStr { cost = computedCostStr } } else if let f = fuel, let c = costVal, f > 0, pricePerGalon.trimmingCharacters(in: .whitespaces).isEmpty { let computedPrice = roundToThree(c / f) let computedPriceStr = String(format: "%.3f", computedPrice) if pricePerGalon != computedPriceStr { pricePerGalon = computedPriceStr } } else if let p = price, let c = costVal, p > 0, fuelVolume.trimmingCharacters(in: .whitespaces).isEmpty { let computedFuel = roundToThree(c / p) let computedFuelStr = String(format: "%.3f", computedFuel) if fuelVolume != computedFuelStr { fuelVolume = computedFuelStr } } isUpdatingCalculation = false } private func saveFuelLog() { guard let newOdometer = Double(odometer) else { return } // Optional: Validate odometer vs. previous logs if needed. fuelLog.date = date fuelLog.odometer = newOdometer fuelLog.fuelVolume = Double(fuelVolume) ?? 0 fuelLog.cost = Double(cost) ?? 0 fuelLog.locationCoordinates = locationCoordinates fuelLog.locationName = locationName fuelLog.octane = Int16(selectedOctane) fuelLog.pricePerGalon = Double(pricePerGalon) ?? 0 fuelLog.fullTank = fullTank do { try viewContext.save() dismiss() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } }