diff --git a/apps/mobile/metro-now/common/const/api-const.swift b/apps/mobile/metro-now/common/const/api-const.swift index 170fb630..85fb1dad 100644 --- a/apps/mobile/metro-now/common/const/api-const.swift +++ b/apps/mobile/metro-now/common/const/api-const.swift @@ -1,5 +1,5 @@ // metro-now // https://github.com/krystxf/metro-now -let ENDPOINT: String = "https://api.metronow.dev" -// let ENDPOINT: String = "http://localhost:3001" +//let ENDPOINT: String = "https://api.metronow.dev" + let ENDPOINT: String = "http://localhost:3001" diff --git a/apps/mobile/metro-now/common/managers/network-manager.swift b/apps/mobile/metro-now/common/managers/network-manager.swift index 339f0dfe..e1876daa 100644 --- a/apps/mobile/metro-now/common/managers/network-manager.swift +++ b/apps/mobile/metro-now/common/managers/network-manager.swift @@ -8,6 +8,8 @@ final class NetworkManager { ) private init() {} + + func getMetroStops( completed: @escaping (Result<[ApiStop], FetchErrorNew>) -> Void diff --git a/apps/mobile/metro-now/metro-now Watch App/pages/stop/stop-detail.view.swift b/apps/mobile/metro-now/metro-now Watch App/pages/stop/stop-detail.view.swift index 2518af6b..510a01ec 100644 --- a/apps/mobile/metro-now/metro-now Watch App/pages/stop/stop-detail.view.swift +++ b/apps/mobile/metro-now/metro-now Watch App/pages/stop/stop-detail.view.swift @@ -14,6 +14,8 @@ struct MainPagePlatform { let departures: [ApiDeparture]? } + + struct StopDeparturesView: View { let title: String let platforms: [MainPagePlatform] diff --git a/apps/mobile/metro-now/metro-now.xcodeproj/project.pbxproj b/apps/mobile/metro-now/metro-now.xcodeproj/project.pbxproj index 9a9ab567..d9b4af5c 100644 --- a/apps/mobile/metro-now/metro-now.xcodeproj/project.pbxproj +++ b/apps/mobile/metro-now/metro-now.xcodeproj/project.pbxproj @@ -55,11 +55,21 @@ ); target = 2D001BB72CC8099C00C6B4F8 /* metro-now Watch App */; }; + 2DAD22172CE5174B000A2087 /* Exceptions for "metro-now" folder in "metro-now" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 2D001BA72CC8099B00C6B4F8 /* metro-now */; + }; /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ 2D001BAA2CC8099B00C6B4F8 /* metro-now */ = { isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 2DAD22172CE5174B000A2087 /* Exceptions for "metro-now" folder in "metro-now" target */, + ); path = "metro-now"; sourceTree = ""; }; @@ -438,6 +448,7 @@ DEVELOPMENT_TEAM = R6WU5ABNG2; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "metro-now/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "metro-now"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.navigation"; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "We need your location to provide live updates."; @@ -472,6 +483,7 @@ DEVELOPMENT_TEAM = R6WU5ABNG2; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "metro-now/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "metro-now"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.navigation"; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "We need your location to provide live updates."; diff --git a/apps/mobile/metro-now/metro-now/ContentView.swift b/apps/mobile/metro-now/metro-now/ContentView.swift index e05d8ec6..6e767a0a 100644 --- a/apps/mobile/metro-now/metro-now/ContentView.swift +++ b/apps/mobile/metro-now/metro-now/ContentView.swift @@ -4,67 +4,62 @@ import CoreLocation import SwiftUI -struct ContentView: View { +func findClosestStop(to location: CLLocation, stops: [ApiStop]) -> ApiStop? { + var closestStop: ApiStop? + var closestDistance: CLLocationDistance? + + for stop in stops { + let stopLocation = CLLocation(latitude: stop.avgLatitude, longitude: stop.avgLongitude) + + let distance = location.distance(from: stopLocation) + + guard closestDistance != nil else { + closestStop = stop + closestDistance = distance + continue + } + + if distance < closestDistance! { + closestStop = stop + closestDistance = distance + } + } + + return closestStop +} + +struct MetroDeparturesView: View { @StateObject private var locationManager = LocationManager() @State var metroStops: [ApiStop]? = nil @State var allStops: [ApiStop]? = nil @State var departures: [ApiDeparture]? = nil private let timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect() + var body: some View { - NavigationStack { - List { - if let location = locationManager.location, - let metroStops, - let closestMetroStop = findClosestStop(to: location, stops: metroStops) - { - Section(header: Text("Metro")) { - ClosestMetroStopSectionView( - closestStop: closestMetroStop, - departures: departures - ) - .navigationTitle(closestMetroStop.name) - } - } else { - ProgressView() - } - } + if let location = locationManager.location, + let metroStops, + let closestMetroStop = findClosestStop(to: location, stops: metroStops) + { + ClosestMetroStopSectionView( + closestStop: closestMetroStop, + departures: departures + ) + .navigationTitle(closestMetroStop.name) + } else { + ProgressView() } - .onAppear { - getAllMetroStops() - getAllStops() - } - .onReceive(timer) { _ in - getAllMetroStops() - getAllStops() - getStopDepartures() - } - } - - func findClosestStop(to location: CLLocation, stops: [ApiStop]) -> ApiStop? { - var closestStop: ApiStop? - var closestDistance: CLLocationDistance? - - for stop in stops { - let stopLocation = CLLocation(latitude: stop.avgLatitude, longitude: stop.avgLongitude) - - let distance = location.distance(from: stopLocation) - - guard closestDistance != nil else { - closestStop = stop - closestDistance = distance - continue + + EmptyView() + .onAppear { + getAllMetroStops() } - - if distance < closestDistance! { - closestStop = stop - closestDistance = distance + .onReceive(timer) { _ in + getAllMetroStops() + getStopDepartures() } - } - - return closestStop } - + func getAllMetroStops() { NetworkManager.shared.getMetroStops { result in DispatchQueue.main.async { @@ -80,13 +75,82 @@ struct ContentView: View { } } + func getStopDepartures() { + guard + let location = locationManager.location, + let metroStops, + let closestStop = findClosestStop(to: location, stops: metroStops) + else { + return + } + + NetworkManager.shared + .getDepartures(stopIds: [closestStop.id], platformIds: []) { result in + DispatchQueue.main.async { + switch result { + case let .success(departures): + + self.departures = departures + + case let .failure(error): + print(error.localizedDescription) + } + } + } + } + +} + +struct NonMetroDeparturesView: View { + @StateObject private var locationManager = LocationManager() + @State var allStops: [ApiStop]? = nil + @State var departures: [ApiDeparture]? = nil + private let timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect() + + var body: some View { + if let location = locationManager.location, + let allStops, + let closestStop = findClosestStop(to: location, stops: allStops) + { +// ClosestMetroStopSectionView( +// closestStop: closestMetroStop, +// departures: departures +// ) + let platforms = closestStop.platforms.filter{!$0.isMetro } + let groupedPlatforms = Dictionary.init( + grouping: platforms, + by: \.name + ) + + + ForEach(platforms, id: \.id) { platform in + Section(header: Text(platform.name)){ + EmptyView() + } +// Text(stop.routes.map(\.name).joined(separator: ", ")) + } + + } else { + ProgressView() + } + + EmptyView() + .onAppear { + getAllStops() + } + .onReceive(timer) { _ in + getAllStops() + getStopDepartures() + } + } + func getAllStops() { NetworkManager.shared.getAllStops { result in DispatchQueue.main.async { switch result { case let .success(stops): - allStops = stops + allStops = stops case let .failure(error): print(error.localizedDescription) @@ -98,8 +162,8 @@ struct ContentView: View { func getStopDepartures() { guard let location = locationManager.location, - let metroStops, - let closestStop = findClosestStop(to: location, stops: metroStops) + let allStops, + let closestStop = findClosestStop(to: location, stops: allStops) else { return } @@ -118,6 +182,32 @@ struct ContentView: View { } } } +} + +struct ContentView: View { + @StateObject private var locationManager = LocationManager() + + var body: some View { + if let _ = locationManager.location { + NavigationStack { + List { + Section(header: Text("Metro")) { + MetroDeparturesView() + } + + NonMetroDeparturesView() + } + } + } + else { + NoLocationView() + } + } + + + + + } #Preview { diff --git a/apps/mobile/metro-now/metro-now/Info.plist b/apps/mobile/metro-now/metro-now/Info.plist new file mode 100644 index 00000000..caa51fdb --- /dev/null +++ b/apps/mobile/metro-now/metro-now/Info.plist @@ -0,0 +1,8 @@ + + + + + Preference + + +