ui updates
This commit is contained in:
parent
07e8581ee2
commit
28c676fc76
|
@ -289,7 +289,7 @@
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "Gas Man/Gas_Man.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "Gas Man/Gas_Man.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 202503190946;
|
CURRENT_PROJECT_VERSION = 202503191007;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Gas Man/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Gas Man/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = Z734T5CD6B;
|
DEVELOPMENT_TEAM = Z734T5CD6B;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
@ -332,7 +332,7 @@
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "Gas Man/Gas_Man.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "Gas Man/Gas_Man.entitlements";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 202503190946;
|
CURRENT_PROJECT_VERSION = 202503191007;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Gas Man/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Gas Man/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = Z734T5CD6B;
|
DEVELOPMENT_TEAM = Z734T5CD6B;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
|
|
@ -8,6 +8,35 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
|
// Helper function to check if a string is properly formatted (e.g., "18.526")
|
||||||
|
func isProperlyFormatted(_ input: String) -> Bool {
|
||||||
|
let pattern = #"^\d+\.\d{3}$"#
|
||||||
|
return input.range(of: pattern, options: .regularExpression) != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to format input.
|
||||||
|
func formatInput(_ input: String) -> String {
|
||||||
|
// Extract only numeric characters.
|
||||||
|
let digitsOnly = input.filter { $0.isNumber }
|
||||||
|
// If no digits, return empty.
|
||||||
|
guard !digitsOnly.isEmpty else { return "" }
|
||||||
|
// Convert to an integer to remove any leading zeros.
|
||||||
|
let numberValue = Int(digitsOnly) ?? 0
|
||||||
|
// Convert back to a string.
|
||||||
|
let digits = String(numberValue)
|
||||||
|
|
||||||
|
if digits.count > 3 {
|
||||||
|
// Insert decimal point so that the last 3 digits are decimals.
|
||||||
|
let integerPart = digits.dropLast(3)
|
||||||
|
let decimalPart = digits.suffix(3)
|
||||||
|
return "\(integerPart).\(decimalPart)"
|
||||||
|
} else {
|
||||||
|
// If fewer than 4 digits, pad with zeros on the left to 3 digits.
|
||||||
|
let padded = String(repeating: "0", count: 3 - digits.count) + digits
|
||||||
|
return "0." + padded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AddFuelLogView: View {
|
struct AddFuelLogView: View {
|
||||||
@Environment(\.managedObjectContext) private var viewContext
|
@Environment(\.managedObjectContext) private var viewContext
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
|
@ -59,26 +88,53 @@ struct AddFuelLogView: View {
|
||||||
Text("Odometer:")
|
Text("Odometer:")
|
||||||
TextField("", text: $odometer)
|
TextField("", text: $odometer)
|
||||||
.keyboardType(.decimalPad)
|
.keyboardType(.decimalPad)
|
||||||
|
.multilineTextAlignment(.trailing)
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Text("Gallons:")
|
Text("Gallons:")
|
||||||
TextField("", text: $fuelVolume)
|
TextField("", text: $fuelVolume)
|
||||||
.keyboardType(.decimalPad)
|
.keyboardType(.decimalPad)
|
||||||
.onChange(of: fuelVolume) { _ in updateCalculatedValues() }
|
.multilineTextAlignment(.trailing)
|
||||||
|
.onChange(of: fuelVolume) { newValue in
|
||||||
|
// Only reformat if the input is not already in the proper format.
|
||||||
|
// if newValue.contains(".") { return }
|
||||||
|
let pattern = #"^\d+\.\d{3}$"#
|
||||||
|
if newValue.range(of: pattern, options: .regularExpression) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let formatted = formatInput(newValue)
|
||||||
|
if formatted != newValue {
|
||||||
|
fuelVolume = formatted
|
||||||
|
}
|
||||||
|
updateCalculatedValues()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Text("Price/Gal:")
|
Text("Price/Gal:")
|
||||||
TextField("", text: $pricePerGalon)
|
TextField("", text: $pricePerGalon)
|
||||||
.keyboardType(.decimalPad)
|
.keyboardType(.decimalPad)
|
||||||
.onChange(of: pricePerGalon) { _ in updateCalculatedValues() }
|
.multilineTextAlignment(.trailing)
|
||||||
|
.onChange(of: pricePerGalon) { newValue in
|
||||||
|
// if newValue.contains(".") { return }
|
||||||
|
let pattern = #"^\d+\.\d{3}$"#
|
||||||
|
if newValue.range(of: pattern, options: .regularExpression) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let formatted = formatInput(newValue)
|
||||||
|
if formatted != newValue {
|
||||||
|
pricePerGalon = formatted
|
||||||
|
}
|
||||||
|
updateCalculatedValues()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Text("Cost:")
|
Text("Cost:")
|
||||||
TextField("", text: $cost)
|
TextField("", text: $cost)
|
||||||
.keyboardType(.decimalPad)
|
.keyboardType(.decimalPad)
|
||||||
|
.multilineTextAlignment(.trailing)
|
||||||
.onChange(of: cost) { _ in updateCalculatedValues() }
|
.onChange(of: cost) { _ in updateCalculatedValues() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +150,8 @@ struct AddFuelLogView: View {
|
||||||
Text("Coordinates: \(locationCoordinates)")
|
Text("Coordinates: \(locationCoordinates)")
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField("Location Coordinates", text: $locationCoordinates)
|
|
||||||
TextField("Location Name", text: $locationName)
|
TextField("Location Name", text: $locationName)
|
||||||
|
.multilineTextAlignment(.trailing)
|
||||||
|
|
||||||
Picker("Octane", selection: $selectedOctane) {
|
Picker("Octane", selection: $selectedOctane) {
|
||||||
ForEach(octaneOptions, id: \.self) { option in
|
ForEach(octaneOptions, id: \.self) { option in
|
||||||
|
@ -108,7 +164,7 @@ struct AddFuelLogView: View {
|
||||||
Section(header: Text("Vehicle")) {
|
Section(header: Text("Vehicle")) {
|
||||||
Picker("Select Vehicle", selection: $selectedVehicleID) {
|
Picker("Select Vehicle", selection: $selectedVehicleID) {
|
||||||
ForEach(vehicles, id: \.id) { vehicle in
|
ForEach(vehicles, id: \.id) { vehicle in
|
||||||
Text("\(vehicle.year) \(vehicle.make ?? "") \(vehicle.model ?? "")")
|
Text("\(vehicle.year ?? "") \(vehicle.make ?? "") \(vehicle.model ?? "")")
|
||||||
.tag(vehicle.id)
|
.tag(vehicle.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,7 @@ struct AddVehicleView: View {
|
||||||
private func saveVehicle() {
|
private func saveVehicle() {
|
||||||
let newVehicle = Vehicle(context: viewContext)
|
let newVehicle = Vehicle(context: viewContext)
|
||||||
newVehicle.id = UUID()
|
newVehicle.id = UUID()
|
||||||
newVehicle.year = Int16(year) ?? 0
|
newVehicle.year = year
|
||||||
newVehicle.make = make
|
newVehicle.make = make
|
||||||
newVehicle.model = model
|
newVehicle.model = model
|
||||||
newVehicle.color = color
|
newVehicle.color = color
|
||||||
|
|
|
@ -136,7 +136,7 @@ struct EditVehicleView: View {
|
||||||
|
|
||||||
private func loadVehicleData() {
|
private func loadVehicleData() {
|
||||||
// Basic Information
|
// Basic Information
|
||||||
year = "\(vehicle.year)"
|
year = vehicle.year ?? ""
|
||||||
make = vehicle.make ?? ""
|
make = vehicle.make ?? ""
|
||||||
model = vehicle.model ?? ""
|
model = vehicle.model ?? ""
|
||||||
color = vehicle.color ?? ""
|
color = vehicle.color ?? ""
|
||||||
|
@ -218,7 +218,7 @@ struct EditVehicleView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func saveChanges() {
|
private func saveChanges() {
|
||||||
vehicle.year = Int16(year) ?? 0
|
vehicle.year = year
|
||||||
vehicle.make = make
|
vehicle.make = make
|
||||||
vehicle.model = model
|
vehicle.model = model
|
||||||
vehicle.color = color
|
vehicle.color = color
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct FuelLogDetailView: View {
|
||||||
// Vehicle header section
|
// Vehicle header section
|
||||||
if let vehicle = fuelLog.vehicle {
|
if let vehicle = fuelLog.vehicle {
|
||||||
Section {
|
Section {
|
||||||
Text("\(vehicle.year) \(vehicle.model ?? "")")
|
Text("\(vehicle.year ?? "") \(vehicle.model ?? "")")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ struct FuelLogListView: View {
|
||||||
Section {
|
Section {
|
||||||
Picker("Vehicle", selection: $selectedVehicleID) {
|
Picker("Vehicle", selection: $selectedVehicleID) {
|
||||||
ForEach(vehicles, id: \.id) { vehicle in
|
ForEach(vehicles, id: \.id) { vehicle in
|
||||||
Text("\(vehicle.year) \(vehicle.make ?? "") \(vehicle.model ?? "")")
|
Text("\(vehicle.year ?? "") \(vehicle.make ?? "") \(vehicle.model ?? "")")
|
||||||
.tag(vehicle.id)
|
.tag(vehicle.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
<attribute name="wheelModel" optional="YES" attributeType="String"/>
|
<attribute name="wheelModel" optional="YES" attributeType="String"/>
|
||||||
<attribute name="wheelSizeDiameter" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
|
<attribute name="wheelSizeDiameter" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||||
<attribute name="wheelSizeWidth" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
|
<attribute name="wheelSizeWidth" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
|
||||||
<attribute name="year" attributeType="Integer 16" minValueString="1900" maxValueString="2100" defaultValueString="0" usesScalarValueType="YES"/>
|
<attribute name="year" attributeType="String" minValueString="4" maxValueString="4" defaultValueString="2025" regularExpressionString="[0-9][0-9][0-9][0-9]"/>
|
||||||
<relationship name="fuelLog" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="FuelLog" inverseName="vehicle" inverseEntity="FuelLog"/>
|
<relationship name="fuelLog" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="FuelLog" inverseName="vehicle" inverseEntity="FuelLog"/>
|
||||||
</entity>
|
</entity>
|
||||||
</model>
|
</model>
|
|
@ -16,6 +16,7 @@ struct PersistenceController {
|
||||||
// "GasMan" must match the name of your .xcdatamodeld file.
|
// "GasMan" must match the name of your .xcdatamodeld file.
|
||||||
container = NSPersistentCloudKitContainer(name: "Gas_Man")
|
container = NSPersistentCloudKitContainer(name: "Gas_Man")
|
||||||
|
|
||||||
|
|
||||||
if inMemory {
|
if inMemory {
|
||||||
container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
|
container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ extension Vehicle: Identifiable {
|
||||||
id ?? UUID()
|
id ?? UUID()
|
||||||
}
|
}
|
||||||
|
|
||||||
@NSManaged public var year: Int16
|
@NSManaged public var year: String?
|
||||||
@NSManaged public var make: String?
|
@NSManaged public var make: String?
|
||||||
@NSManaged public var model: String?
|
@NSManaged public var model: String?
|
||||||
@NSManaged public var color: String?
|
@NSManaged public var color: String?
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct VehicleDetailView: View {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Year:")
|
Text("Year:")
|
||||||
Spacer()
|
Spacer()
|
||||||
Text("\(vehicle.year)")
|
Text(vehicle.year ?? "")
|
||||||
}
|
}
|
||||||
HStack {
|
HStack {
|
||||||
Text("Make:")
|
Text("Make:")
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct VehicleRowView: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("\(vehicle.year) \(vehicle.make ?? "") \(vehicle.model ?? "")")
|
Text("\(vehicle.year ?? "") \(vehicle.make ?? "") \(vehicle.model ?? "")")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text(vehicle.color ?? "")
|
Text(vehicle.color ?? "")
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
|
|
Loading…
Reference in New Issue