From 8328e3f7840760347826d1c64c96049ae808b077 Mon Sep 17 00:00:00 2001 From: gbaranski Date: Mon, 14 Nov 2022 21:09:15 +0100 Subject: [PATCH] feat(ios): parsing opening hours --- ios/wheretopark.xcodeproj/project.pbxproj | 17 ++++++ .../xcshareddata/swiftpm/Package.resolved | 9 +++ ios/wheretopark/DetailsView.swift | 59 +++++++++---------- ios/wheretopark/MapView.swift | 3 +- ios/wheretopark/ParkingLot.swift | 3 +- ios/wheretopark/Utilities.swift | 15 +++++ 6 files changed, 73 insertions(+), 33 deletions(-) diff --git a/ios/wheretopark.xcodeproj/project.pbxproj b/ios/wheretopark.xcodeproj/project.pbxproj index 1fe3c9f..1ede498 100644 --- a/ios/wheretopark.xcodeproj/project.pbxproj +++ b/ios/wheretopark.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 68BBFAB4290EFC750012512D /* Swift-ISO8601-DurationParser in Frameworks */ = {isa = PBXBuildFile; productRef = 68BBFAB3290EFC750012512D /* Swift-ISO8601-DurationParser */; }; 68BBFAB7290EFD600012512D /* DefaultCodable in Frameworks */ = {isa = PBXBuildFile; productRef = 68BBFAB6290EFD600012512D /* DefaultCodable */; }; 68E2318E291569A3004EA1B2 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 68E23190291569A3004EA1B2 /* Localizable.strings */; }; + 68F7162E2922D5650040B942 /* OpeningHours in Frameworks */ = {isa = PBXBuildFile; productRef = 68F7162D2922D5650040B942 /* OpeningHours */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -91,6 +92,7 @@ 68BBFAB4290EFC750012512D /* Swift-ISO8601-DurationParser in Frameworks */, 68BBFAB7290EFD600012512D /* DefaultCodable in Frameworks */, 68BBFAA7290ED8E40012512D /* PhoneNumberKit in Frameworks */, + 68F7162E2922D5650040B942 /* OpeningHours in Frameworks */, 68BBFAAE290EED880012512D /* CodableGeoJSON in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -207,6 +209,7 @@ 68BBFAAD290EED880012512D /* CodableGeoJSON */, 68BBFAB3290EFC750012512D /* Swift-ISO8601-DurationParser */, 68BBFAB6290EFD600012512D /* DefaultCodable */, + 68F7162D2922D5650040B942 /* OpeningHours */, ); productName = wheretopark; productReference = 68239D9F290ED14200C25ED6 /* wheretopark.app */; @@ -286,6 +289,7 @@ 68BBFAAC290EED880012512D /* XCRemoteSwiftPackageReference "CodableGeoJSON" */, 68BBFAB2290EFC750012512D /* XCRemoteSwiftPackageReference "Swift-ISO8601-DurationParser" */, 68BBFAB5290EFD600012512D /* XCRemoteSwiftPackageReference "DefaultCodable" */, + 68F7162C2922D5650040B942 /* XCRemoteSwiftPackageReference "opening-hours-swift" */, ); productRefGroup = 68239DA0290ED14200C25ED6 /* Products */; projectDirPath = ""; @@ -761,6 +765,14 @@ minimumVersion = 1.0.0; }; }; + 68F7162C2922D5650040B942 /* XCRemoteSwiftPackageReference "opening-hours-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "git@github.com:gbaranski/opening-hours-swift.git"; + requirement = { + branch = master; + kind = branch; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -784,6 +796,11 @@ package = 68BBFAB5290EFD600012512D /* XCRemoteSwiftPackageReference "DefaultCodable" */; productName = DefaultCodable; }; + 68F7162D2922D5650040B942 /* OpeningHours */ = { + isa = XCSwiftPackageProductDependency; + package = 68F7162C2922D5650040B942 /* XCRemoteSwiftPackageReference "opening-hours-swift" */; + productName = OpeningHours; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 68239D97290ED14100C25ED6 /* Project object */; diff --git a/ios/wheretopark.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/wheretopark.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6a6261a..f712f66 100644 --- a/ios/wheretopark.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ios/wheretopark.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -27,6 +27,15 @@ "version" : "1.2.1" } }, + { + "identity" : "opening-hours-swift", + "kind" : "remoteSourceControl", + "location" : "git@github.com:gbaranski/opening-hours-swift.git", + "state" : { + "branch" : "master", + "revision" : "d04206e0e0cf68ffb9732dda8ff792266371b570" + } + }, { "identity" : "phonenumberkit", "kind" : "remoteSourceControl", diff --git a/ios/wheretopark/DetailsView.swift b/ios/wheretopark/DetailsView.swift index fc5b989..aa13abc 100644 --- a/ios/wheretopark/DetailsView.swift +++ b/ios/wheretopark/DetailsView.swift @@ -100,36 +100,35 @@ struct DetailsView: View { } } Divider() -// VStack(alignment: .leading) { -// Text("parkingLot.hours") -// .fontWeight(.black) -// .font(.caption) -// .foregroundColor(.secondary) -// .textCase(.uppercase) -// // TODO: Use real status -// let status = ParkingLotStatus.closed -// switch status { -// case .opensSoon: -// Text(LocalizedStringKey("parkingLot.status.opensSoon")) -// .fontWeight(.heavy) -// .foregroundColor(.yellow) -// case .open: -// Text(LocalizedStringKey("parkingLot.status.open")) -// .fontWeight(.heavy) -// .foregroundColor(.green) -// case .closesSoon: -// Text(LocalizedStringKey("parkingLot.status.closesSoon")) -// .fontWeight(.heavy) -// .foregroundColor(.yellow) -// case .closed: -// Text(LocalizedStringKey("parkingLot.status.closed")) -// .fontWeight(.heavy) -// .foregroundColor(.red) -// // default: -// // fatalError("unknown status \(status)") -// } -// } -// Divider() + VStack(alignment: .leading) { + Text("parkingLot.hours") + .fontWeight(.black) + .font(.caption) + .foregroundColor(.secondary) + .textCase(.uppercase) + let status = parkingLot.metadata.status() + switch status { + case .opensSoon: + Text(LocalizedStringKey("parkingLot.status.opensSoon")) + .fontWeight(.heavy) + .foregroundColor(.yellow) + case .open: + Text(LocalizedStringKey("parkingLot.status.open")) + .fontWeight(.heavy) + .foregroundColor(.green) + case .closesSoon: + Text(LocalizedStringKey("parkingLot.status.closesSoon")) + .fontWeight(.heavy) + .foregroundColor(.yellow) + case .closed: + Text(LocalizedStringKey("parkingLot.status.closed")) + .fontWeight(.heavy) + .foregroundColor(.red) + // default: + // fatalError("unknown status \(status)") + } + } + Divider() VStack(alignment: .leading) { let formatter = RelativeDateTimeFormatter() let lastUpdatedString = formatter.localizedString(for: parkingLot.state.lastUpdated, relativeTo: Date.now) diff --git a/ios/wheretopark/MapView.swift b/ios/wheretopark/MapView.swift index 9a745aa..418bf22 100644 --- a/ios/wheretopark/MapView.swift +++ b/ios/wheretopark/MapView.swift @@ -252,8 +252,7 @@ class ParkingLotAnnotation: NSObject, MKAnnotation { } var subtitle: String? { - // TODO: Change that - let status = ParkingLotStatus.closed + let status = parkingLot.metadata.status() if status == .closed || status == .opensSoon { return status.rawValue.capitalizingFirstLetter() } else { diff --git a/ios/wheretopark/ParkingLot.swift b/ios/wheretopark/ParkingLot.swift index 0ce6b56..bf4fe5f 100644 --- a/ios/wheretopark/ParkingLot.swift +++ b/ios/wheretopark/ParkingLot.swift @@ -41,7 +41,8 @@ extension ParkingLotPricingRule: Decodable { let values = try decoder.container(keyedBy: CodingKeys.self) let durationString = try values.decode(String.self, forKey: .duration) duration = DateComponents.durationFrom8601String(durationString)! - price = try values.decode(Decimal.self, forKey: .price) + let priceString = try values.decode(String.self, forKey: .price) + price = Decimal(string: priceString)! repeating = try values.decodeIfPresent(Bool.self, forKey: .repeating) ?? false } } diff --git a/ios/wheretopark/Utilities.swift b/ios/wheretopark/Utilities.swift index a1bd45f..5403ad4 100644 --- a/ios/wheretopark/Utilities.swift +++ b/ios/wheretopark/Utilities.swift @@ -102,12 +102,27 @@ extension ParkingLotPricingRule { } +import OpeningHours + extension ParkingLotMetadata { var commentForLocale: String? { let languageCode = Locale.current.language.languageCode?.identifier ?? "en" let comment = comment[languageCode] ?? comment ["en"] return comment } + + func status() -> ParkingLotStatus { + let rawOpeningHours = rules.map{ $0.hours }.joined(separator: "; ") + print("rawOpeningHours: \(rawOpeningHours)") + let openingHours = OpeningHours(rawOpeningHours) + let dateTime = now_at(timezone) + if openingHours.is_open(dateTime) { + return .open + } else { + return .closed + } + + } } extension URL {