diff --git a/Sequor.xcodeproj/project.pbxproj b/Sequor.xcodeproj/project.pbxproj index 71ead22..0fbe282 100644 --- a/Sequor.xcodeproj/project.pbxproj +++ b/Sequor.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ ADA166EE238430E700C53998 /* ActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADA166ED238430E700C53998 /* ActivityView.swift */; }; ADBEB00923743CB9001534CD /* DashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADBEB00823743CB9001534CD /* DashboardView.swift */; }; ADBEB00D2374423D001534CD /* PurchaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADBEB00C2374423D001534CD /* PurchaseView.swift */; }; + ADC2A22B238714B10096F1ED /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADC2A22A238714B10096F1ED /* Network.swift */; }; ADD8B71D237B0C9F00D8DD55 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD8B71C237B0C9F00D8DD55 /* AppState.swift */; }; ADD8B71F237B0DDD00D8DD55 /* Profile.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD8B71E237B0DDD00D8DD55 /* Profile.swift */; }; ADD8B723237B4ECF00D8DD55 /* RelativeTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADD8B722237B4ECF00D8DD55 /* RelativeTime.swift */; }; @@ -73,6 +74,7 @@ ADBEB00823743CB9001534CD /* DashboardView.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = DashboardView.swift; sourceTree = ""; tabWidth = 2; }; ADBEB00A23743E12001534CD /* CouponsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CouponsView.swift; sourceTree = ""; }; ADBEB00C2374423D001534CD /* PurchaseView.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = PurchaseView.swift; sourceTree = ""; tabWidth = 2; }; + ADC2A22A238714B10096F1ED /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; ADD8B71C237B0C9F00D8DD55 /* AppState.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; tabWidth = 2; }; ADD8B71E237B0DDD00D8DD55 /* Profile.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = Profile.swift; sourceTree = ""; tabWidth = 2; }; ADD8B722237B4ECF00D8DD55 /* RelativeTime.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = RelativeTime.swift; sourceTree = ""; tabWidth = 2; }; @@ -151,6 +153,7 @@ AD1F064A236761C800F74D9A /* Views */, AD1F0619236760CC00F74D9A /* AppDelegate.swift */, AD1F061B236760CC00F74D9A /* SceneDelegate.swift */, + ADC2A22A238714B10096F1ED /* Network.swift */, AD1F061F236760CD00F74D9A /* Assets.xcassets */, AD1F0624236760CD00F74D9A /* LaunchScreen.storyboard */, AD1F0627236760CD00F74D9A /* Info.plist */, @@ -395,6 +398,7 @@ files = ( ADECEB142375AAD70097B726 /* Ticket.swift in Sources */, ADD8B723237B4ECF00D8DD55 /* RelativeTime.swift in Sources */, + ADC2A22B238714B10096F1ED /* Network.swift in Sources */, ADD8B71D237B0C9F00D8DD55 /* AppState.swift in Sources */, ADBEB00D2374423D001534CD /* PurchaseView.swift in Sources */, AD1F061A236760CC00F74D9A /* AppDelegate.swift in Sources */, diff --git a/Sequor/Models/AppState.swift b/Sequor/Models/AppState.swift index d9dec75..e330714 100644 --- a/Sequor/Models/AppState.swift +++ b/Sequor/Models/AppState.swift @@ -19,8 +19,6 @@ final class AppState: ObservableObject { /// Valid coupons the user has erned. @Published var coupons: [Coupon] = [] - @Published var lastTrip: Trip? - var locationLogger: LocationLogger? init() { @@ -34,11 +32,14 @@ final class AppState: ObservableObject { locationLogger = LocationLogger(trip: Trip()) } - /// Sends a request to the server to invalidate the ticket but changing experation date. + // Should send a request to the server to invalidate the ticket. + /// Currently invalidates the ticket client side and send the trip to the server. func invalidateTicket() { // Temp for testing. Should make request to server. activeTicket = nil - lastTrip = locationLogger?.end() + if let trip = locationLogger?.end() { + HTTP.post(asJSON: trip, to: URL(string: "http://10.3.10.102:8000/trip")!) + } } } diff --git a/Sequor/Models/LocationLogger.swift b/Sequor/Models/LocationLogger.swift index 24eabdc..5bcbfac 100644 --- a/Sequor/Models/LocationLogger.swift +++ b/Sequor/Models/LocationLogger.swift @@ -41,6 +41,7 @@ final class LocationLogger: NSObject, ObservableObject, CLLocationManagerDelegat func end() -> Trip { locationManager.stopUpdatingLocation() + trip.endDate = Date() return trip } } diff --git a/Sequor/Network.swift b/Sequor/Network.swift new file mode 100644 index 0000000..e653d75 --- /dev/null +++ b/Sequor/Network.swift @@ -0,0 +1,81 @@ +import Foundation + +enum HTTP { + static func get(url: URL, + headders: [AnyHashable: Any]? = nil, + completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) { + let configuration = URLSessionConfiguration.ephemeral + configuration.httpAdditionalHeaders = headders + + let defaultSession = URLSession(configuration: configuration) + let dataTask = defaultSession.dataTask(with: url, completionHandler: completionHandler) + dataTask.resume() + } + + static func get(url: URL, + headders: [AnyHashable: Any]? = nil, + completionHandler: @escaping (Data) -> Void) { + get(url: url) { data, response, _ in + if let data = data, + let response = response as? HTTPURLResponse, + response.statusCode == 200 { + completionHandler(data) + } + } + } + + static func downloadTask(url: URL, + headders: [AnyHashable: Any]? = nil, + completionHandler: @escaping (Data) -> Void) { + let configuration = URLSessionConfiguration.ephemeral + configuration.httpAdditionalHeaders = headders + configuration.shouldUseExtendedBackgroundIdleMode = true + + let defaultSession = URLSession(configuration: configuration) + var dataTask: URLSessionDownloadTask + + dataTask = defaultSession + .downloadTask(with: url) { url, response, _ in + if let url = url, + let response = response as? HTTPURLResponse, + response.statusCode == 200 { + guard let data = try? Data(contentsOf: url) else { + return + } + + completionHandler(data) + } + } + dataTask.resume() + } + + static func post(data body: Data, to url: URL) { + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.httpBody = body + request.addValue("application/json", forHTTPHeaderField: "Content-Type") + + let task = URLSession.shared.dataTask(with: request) { data, _, error in + guard let data = data, error == nil else { + print(error?.localizedDescription ?? "No data") + return + } + let responseJSON = try? JSONSerialization.jsonObject(with: data, options: []) + if let responseJSON = responseJSON as? [String: Any] { + print(responseJSON) + } + } + task.resume() + } + + static func post(asJSON data: Trip, to url: URL) { + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .secondsSince1970 + // swiftlint:disable:next force_try + let json = try! encoder.encode(data) + print(String(data: json, encoding: .utf8)!) + post(data: json, to: url) + + [1,2].firstIndex(of: 4) + } +}