diff --git a/Gas Man.xcodeproj/project.pbxproj b/Fuel Man.xcodeproj/project.pbxproj similarity index 99% rename from Gas Man.xcodeproj/project.pbxproj rename to Fuel Man.xcodeproj/project.pbxproj index d7fd816..d8e0d5d 100644 --- a/Gas Man.xcodeproj/project.pbxproj +++ b/Fuel Man.xcodeproj/project.pbxproj @@ -199,7 +199,7 @@ }; }; }; - buildConfigurationList = 3D34444B2D889F7D00AA3172 /* Build configuration list for PBXProject "Gas Man" */; + buildConfigurationList = 3D34444B2D889F7D00AA3172 /* Build configuration list for PBXProject "Fuel Man" */; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -575,7 +575,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 3D34444B2D889F7D00AA3172 /* Build configuration list for PBXProject "Gas Man" */ = { + 3D34444B2D889F7D00AA3172 /* Build configuration list for PBXProject "Fuel Man" */ = { isa = XCConfigurationList; buildConfigurations = ( 3D34447D2D889F8000AA3172 /* Debug */, diff --git a/Gas Man.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Fuel Man.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Gas Man.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Fuel Man.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Gas Man.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Fuel Man.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from Gas Man.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to Fuel Man.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Gas Man.xcodeproj/project.xcworkspace/xcuserdata/kkenny.xcuserdatad/WorkspaceSettings.xcsettings b/Fuel Man.xcodeproj/project.xcworkspace/xcuserdata/kkenny.xcuserdatad/WorkspaceSettings.xcsettings similarity index 100% rename from Gas Man.xcodeproj/project.xcworkspace/xcuserdata/kkenny.xcuserdatad/WorkspaceSettings.xcsettings rename to Fuel Man.xcodeproj/project.xcworkspace/xcuserdata/kkenny.xcuserdatad/WorkspaceSettings.xcsettings diff --git a/Gas Man.xcodeproj/xcshareddata/xcschemes/Gas Man.xcscheme b/Fuel Man.xcodeproj/xcshareddata/xcschemes/Gas Man.xcscheme similarity index 91% rename from Gas Man.xcodeproj/xcshareddata/xcschemes/Gas Man.xcscheme rename to Fuel Man.xcodeproj/xcshareddata/xcschemes/Gas Man.xcscheme index 26fe07a..f762f51 100644 --- a/Gas Man.xcodeproj/xcshareddata/xcschemes/Gas Man.xcscheme +++ b/Fuel Man.xcodeproj/xcshareddata/xcschemes/Gas Man.xcscheme @@ -18,7 +18,7 @@ BlueprintIdentifier = "3D34444F2D889F7D00AA3172" BuildableName = "Gas Man.app" BlueprintName = "Gas Man" - ReferencedContainer = "container:Gas Man.xcodeproj"> + ReferencedContainer = "container:Fuel Man.xcodeproj"> @@ -38,7 +38,7 @@ BlueprintIdentifier = "3D3444662D889F7F00AA3172" BuildableName = "Gas ManTests.xctest" BlueprintName = "Gas ManTests" - ReferencedContainer = "container:Gas Man.xcodeproj"> + ReferencedContainer = "container:Fuel Man.xcodeproj"> + ReferencedContainer = "container:Fuel Man.xcodeproj"> @@ -71,7 +71,7 @@ BlueprintIdentifier = "3D34444F2D889F7D00AA3172" BuildableName = "Gas Man.app" BlueprintName = "Gas Man" - ReferencedContainer = "container:Gas Man.xcodeproj"> + ReferencedContainer = "container:Fuel Man.xcodeproj"> @@ -88,7 +88,7 @@ BlueprintIdentifier = "3D34444F2D889F7D00AA3172" BuildableName = "Gas Man.app" BlueprintName = "Gas Man" - ReferencedContainer = "container:Gas Man.xcodeproj"> + ReferencedContainer = "container:Fuel Man.xcodeproj"> diff --git a/Gas Man.xcodeproj/xcuserdata/kkenny.xcuserdatad/xcschemes/xcschememanagement.plist b/Fuel Man.xcodeproj/xcuserdata/kkenny.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 100% rename from Gas Man.xcodeproj/xcuserdata/kkenny.xcuserdatad/xcschemes/xcschememanagement.plist rename to Fuel Man.xcodeproj/xcuserdata/kkenny.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/Gas Man/FuelLogs/FuelLogListView.swift b/Gas Man/FuelLogs/FuelLogListView.swift index d907c70..52b1ae3 100644 --- a/Gas Man/FuelLogs/FuelLogListView.swift +++ b/Gas Man/FuelLogs/FuelLogListView.swift @@ -93,7 +93,7 @@ struct FuelLogListView: View { List { // Vehicle Picker Section Section { - Picker("Vehicle", selection: $selectedVehicleID) { + Picker("Vehicle:", selection: $selectedVehicleID) { ForEach(vehicles, id: \.id) { vehicle in Text("\(vehicle.year ?? "") \(vehicle.make ?? "") \(vehicle.model ?? "")") .tag(vehicle.id) @@ -102,6 +102,29 @@ struct FuelLogListView: View { .pickerStyle(MenuPickerStyle()) } + // Vehicle Photo Section + Section { + if let selectedVehicle = vehicles.first(where: { $0.id == selectedVehicleID }) { + if let photoData = selectedVehicle.photo, let uiImage = UIImage(data: photoData) { + Image(uiImage: uiImage) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(maxWidth: .infinity, maxHeight: 200) + .clipShape(Circle()) +// .cornerRadius(8) + } else { + // Fallback image if no photo is available + Image(systemName: "car.fill") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(maxWidth: .infinity, maxHeight: 200) + .foregroundColor(.gray) + .padding() + } + } + } + .listRowBackground(Color.black) + // Average MPG Section Section { HStack { diff --git a/Gas Man/Gas_Man.entitlements b/Gas Man/Gas_Man.entitlements index 2665a5d..adcc3fa 100644 --- a/Gas Man/Gas_Man.entitlements +++ b/Gas Man/Gas_Man.entitlements @@ -19,9 +19,13 @@ com.apple.security.assets.pictures.read-only + com.apple.security.device.camera + com.apple.security.files.user-selected.read-write com.apple.security.personal-information.location + com.apple.security.personal-information.photos-library + diff --git a/Gas Man/Gas_Man.xcdatamodeld/Gas_Man.xcdatamodel/contents b/Gas Man/Gas_Man.xcdatamodeld/Gas_Man.xcdatamodel/contents index bf0faf0..d184a86 100644 --- a/Gas Man/Gas_Man.xcdatamodeld/Gas_Man.xcdatamodel/contents +++ b/Gas Man/Gas_Man.xcdatamodeld/Gas_Man.xcdatamodel/contents @@ -34,6 +34,7 @@ + diff --git a/Gas Man/ImagePicker.swift b/Gas Man/ImagePicker.swift new file mode 100644 index 0000000..300ec0d --- /dev/null +++ b/Gas Man/ImagePicker.swift @@ -0,0 +1,41 @@ +// +// ImagePicker.swift +// Gas Man +// +// Created by Kameron Kenny on 3/19/25. +// + + +import SwiftUI +import UIKit + +struct ImagePicker: UIViewControllerRepresentable { + class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { + let parent: ImagePicker + init(_ parent: ImagePicker) { + self.parent = parent + } + func imagePickerController(_ picker: UIImagePickerController, + didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { + if let uiImage = info[.originalImage] as? UIImage { + parent.image = uiImage + } + parent.presentationMode.wrappedValue.dismiss() + } + } + + @Environment(\.presentationMode) var presentationMode + var sourceType: UIImagePickerController.SourceType = .photoLibrary + @Binding var image: UIImage? + + func makeCoordinator() -> Coordinator { + Coordinator(self) + } + func makeUIViewController(context: Context) -> UIImagePickerController { + let picker = UIImagePickerController() + picker.sourceType = sourceType + picker.delegate = context.coordinator + return picker + } + func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) { } +} diff --git a/Gas Man/Vehicle/Vehicle.swift b/Gas Man/Vehicle/Vehicle.swift index 5d2249c..1aa7240 100644 --- a/Gas Man/Vehicle/Vehicle.swift +++ b/Gas Man/Vehicle/Vehicle.swift @@ -25,6 +25,7 @@ extension Vehicle: Identifiable { id ?? UUID() } + @NSManaged public var photo: Data? @NSManaged public var year: String? @NSManaged public var make: String? @NSManaged public var model: String? diff --git a/Gas Man/Vehicle/VehicleDetailView.swift b/Gas Man/Vehicle/VehicleDetailView.swift index 74259a2..29a67f9 100644 --- a/Gas Man/Vehicle/VehicleDetailView.swift +++ b/Gas Man/Vehicle/VehicleDetailView.swift @@ -9,6 +9,14 @@ import SwiftUI struct VehicleDetailView: View { @ObservedObject var vehicle: Vehicle @State private var showingEditVehicle = false + + // Image state for the vehicle photo. + @State private var vehicleImage: Image? = nil + @State private var inputImage: UIImage? = nil + @State private var showImagePicker = false + @State private var imagePickerSource: UIImagePickerController.SourceType = .photoLibrary + @State private var showImageSourceOptions = false + private let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .short @@ -17,6 +25,45 @@ struct VehicleDetailView: View { var body: some View { Form { + // Photo Section at the very top + Section { + ZStack { + if let vehicleImage = vehicleImage { + vehicleImage + .resizable() + .scaledToFill() + } else { + Rectangle() + .fill(Color.gray.opacity(0.2)) + Image(systemName: "camera.fill") + .font(.largeTitle) + .foregroundColor(.gray) + } + } + .frame(height: 200) + .clipped() + .onTapGesture { + showImageSourceOptions = true + } + .confirmationDialog("Select Photo Source", isPresented: $showImageSourceOptions) { + if UIImagePickerController.isSourceTypeAvailable(.camera) { + Button("Camera") { + imagePickerSource = .camera + showImagePicker = true + } + } + Button("Photo Library") { + imagePickerSource = .photoLibrary + showImagePicker = true + } + Button("Cancel", role: .cancel) { } + } + .sheet(isPresented: $showImagePicker, onDismiss: loadImage) { + ImagePicker(sourceType: imagePickerSource, image: $inputImage) + } + } + + // Rest of the details... Section(header: Text("Basic Information")) { HStack { Text("Vehicle Type:") @@ -31,17 +78,17 @@ struct VehicleDetailView: View { HStack { Text("Make:") Spacer() - Text(vehicle.make ?? "") + Text(vehicle.make ?? "N/A") } HStack { Text("Model:") Spacer() - Text(vehicle.model ?? "") + Text(vehicle.model ?? "N/A") } HStack { Text("Color:") Spacer() - Text(vehicle.color ?? "") + Text(vehicle.color ?? "N/A") } } Section(header: Text("Purchase Information")) { @@ -69,7 +116,6 @@ struct VehicleDetailView: View { } } } - Section(header: Text("Engine & Transmission")) { HStack { Text("Engine Name:") @@ -91,7 +137,6 @@ struct VehicleDetailView: View { Text(vehicle.transmission ?? "Automatic") } } - Section(header: Text("Tires")) { HStack { Text("Brand:") @@ -123,10 +168,8 @@ struct VehicleDetailView: View { } else { Text("-") } - } } - Section(header: Text("Wheels")) { HStack { Text("Brand:") @@ -154,7 +197,6 @@ struct VehicleDetailView: View { } } } - if vehicle.soldDate != nil { Section(header: Text("Sale Information")) { HStack { @@ -173,7 +215,6 @@ struct VehicleDetailView: View { } } } - Section(header: Text("Notes")) { Text(vehicle.notes ?? "") } @@ -190,6 +231,21 @@ struct VehicleDetailView: View { EditVehicleView(vehicle: vehicle) .environment(\.managedObjectContext, vehicle.managedObjectContext!) } + .onAppear { + if let data = vehicle.photo, let uiImage = UIImage(data: data) { + vehicleImage = Image(uiImage: uiImage) + } + } + } + + // This function is called when the image picker is dismissed. + func loadImage() { + guard let inputImage = inputImage else { return } + vehicleImage = Image(uiImage: inputImage) + // Save the image to the vehicle. + if let imageData = inputImage.jpegData(compressionQuality: 0.8) { + vehicle.photo = imageData + try? vehicle.managedObjectContext?.save() + } } } - diff --git a/Gas Man/Vehicle/VehicleRowView.swift b/Gas Man/Vehicle/VehicleRowView.swift index edae2c8..2b5e31a 100644 --- a/Gas Man/Vehicle/VehicleRowView.swift +++ b/Gas Man/Vehicle/VehicleRowView.swift @@ -9,15 +9,31 @@ import SwiftUI struct VehicleRowView: View { - var vehicle: Vehicle - + let vehicle: Vehicle + var body: some View { - VStack(alignment: .leading) { - Text("\(vehicle.year ?? "") \(vehicle.make ?? "") \(vehicle.model ?? "")") - .font(.headline) - Text(vehicle.color ?? "") - .font(.subheadline) - .foregroundColor(.secondary) + HStack { + if let imageData = vehicle.photo, let uiImage = UIImage(data: imageData) { + Image(uiImage: uiImage) + .resizable() + .scaledToFill() + .frame(width: 50, height: 50) + .clipShape(Circle()) + } else { + Circle() + .fill(Color.gray.opacity(0.3)) + .frame(width: 50, height: 50) + .overlay( + Image(systemName: "car.fill") + .foregroundColor(.gray) + ) + } + VStack(alignment: .leading) { + Text("\(vehicle.year ?? "") \(vehicle.make ?? "") \(vehicle.model ?? "")") + .font(.headline) + // Add other details if needed. + } } } } +