Skip to content

Commit

Permalink
feat(ios): bus departures
Browse files Browse the repository at this point in the history
  • Loading branch information
krystxf committed Nov 16, 2024
1 parent e711048 commit 36f505b
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 143 deletions.
120 changes: 85 additions & 35 deletions apps/mobile/metro-now/common/components/route-name.view.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct RouteNameIconView: View {

var body: some View {
Text(label.uppercased())
.font(.system(size: 12, weight: .bold))
.font(.system(size: 12, weight: .bold, design: .monospaced))
.foregroundStyle(.white)
.fixedSize(horizontal: true, vertical: true)
.frame(width: 26, height: 26)
Expand All @@ -19,38 +19,88 @@ struct RouteNameIconView: View {
}

#Preview {
RouteNameIconView(
label: "a",
background: .green
)

RouteNameIconView(
label: "b",
background: .yellow
)

RouteNameIconView(
label: "c",
background: .red
)

RouteNameIconView(
label: "28",
background: .purple
)

RouteNameIconView(
label: "99",
background: .black
)

RouteNameIconView(
label: "149",
background: .blue
)

RouteNameIconView(
label: "912",
background: .black
)
HStack {
RouteNameIconView(
label: "a",
background: getColorByRouteName("a")
)

RouteNameIconView(
label: "b",
background: getColorByRouteName("b")
)

RouteNameIconView(
label: "c",
background: getColorByRouteName("c")
)
}

HStack {
RouteNameIconView(
label: "2",
background: getColorByRouteName("28")
)
RouteNameIconView(
label: "23",
background: getColorByRouteName("28")
)
RouteNameIconView(
label: "28",
background: getColorByRouteName("28")
)
RouteNameIconView(
label: "99",
background: getColorByRouteName("99")
)
}

HStack {
RouteNameIconView(
label: "149",
background: getColorByRouteName("149")
)

RouteNameIconView(
label: "912",
background: getColorByRouteName("912")
)
}

HStack {
RouteNameIconView(
label: "P2",
background: getColorByRouteName("P2")
)
RouteNameIconView(
label: "P4",
background: getColorByRouteName("P2")
)
RouteNameIconView(
label: "P6",
background: getColorByRouteName("P2")
)
}

HStack {
RouteNameIconView(
label: "S9",
background: getColorByRouteName("S49")
)
RouteNameIconView(
label: "S88",
background: getColorByRouteName("S49")
)
RouteNameIconView(
label: "R19",
background: getColorByRouteName("S49")
)
}

HStack {
RouteNameIconView(
label: "LD",
background: getColorByRouteName("LD")
)
}
}
39 changes: 26 additions & 13 deletions apps/mobile/metro-now/common/utils/get-color-by-route-name.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@ import SwiftUI

private let FALLBACK_COLOR: Color = .black

private let METRO_A_COLOR: Color = .green
private let METRO_B_COLOR: Color = .yellow
private let METRO_C_COLOR: Color = .red

private let NIGHT_COLOR: Color = .black
private let BUS_COLOR: Color = .blue
private let TRAM_COLOR: Color = .indigo
private let FERRY_COLOR: Color = .cyan
private let FUNICULAR_COLOR: Color = .brown
private let TRAIN_COLOR: Color = .gray

func getColorByRouteName(_ metroLine: MetroLine?) -> Color {
switch metroLine {
case .A:
.green
case .B:
.yellow
case .C:
.red
case .A: METRO_A_COLOR
case .B: METRO_B_COLOR
case .C: METRO_C_COLOR
default: FALLBACK_COLOR
}
}
Expand All @@ -25,18 +33,18 @@ func getColorByRouteName(_ routeNumber: Int?) -> Color {
// tram
if routeNumber < 100 {
if routeNumber >= 90 {
return .black
return NIGHT_COLOR
}

return .purple
return TRAM_COLOR
}

// bus
if routeNumber >= 900 {
return .black
return NIGHT_COLOR
}

return .blue
return BUS_COLOR
}

func getColorByRouteName(_ routeName: String?) -> Color {
Expand All @@ -46,18 +54,23 @@ func getColorByRouteName(_ routeName: String?) -> Color {

if let routeNumber = Int(routeName) {
return getColorByRouteName(routeNumber)
} else if let metroLine = MetroLine(rawValue: routeName) {
} else if let metroLine = MetroLine(rawValue: routeName.uppercased()) {
return getColorByRouteName(metroLine)
}

// train
if routeName.hasPrefix("S") || routeName.hasPrefix("R") {
return TRAIN_COLOR
}

// ferry
if routeName.hasPrefix("P") {
return Color.blue
return FERRY_COLOR
}

// funicular
if routeName.hasPrefix("LD") {
return Color.blue
return FUNICULAR_COLOR
}

return FALLBACK_COLOR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ struct PlatformDetailView: View {

func getDepartures() {
NetworkManager.shared
.getDepartures(stopIds: [], platformIds: [platformId]) { result in
.getDepartures(
includeVehicle: .METRO,
excludeMetro: false,
stopIds: [], platformIds: [platformId]
) { result in
DispatchQueue.main.async {
switch result {
case let .success(departures):
Expand Down
113 changes: 30 additions & 83 deletions apps/mobile/metro-now/metro-now/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,120 +4,67 @@
import CoreLocation
import SwiftUI


struct ContentView: 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()
@State var metroStops: [ApiStop]? = nil

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)
NavigationStack {
if let metroStops {
List {
Section(header: Text("Metro")) {
MetroDeparturesView(stops: metroStops)
}


if let allStops {
NonMetroDeparturesView(stops: allStops)
}
}
// .navigationTitle(
// findClosestStop(
// to: location,
// stops: metroStops
// )?.name ??
// "Loading..."
// )
} 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
}

if distance < closestDistance! {
closestStop = stop
closestDistance = distance
.onAppear {
getMetroStops()
getAllStops()
}
}

return closestStop

}

func getAllMetroStops() {
NetworkManager.shared.getMetroStops { result in
func getAllStops() {
NetworkManager.shared.getStops(metroOnly: false) { result in
DispatchQueue.main.async {
switch result {
case let .success(stops):

metroStops = stops

allStops = stops
case let .failure(error):
print(error.localizedDescription)
}
}
}
}

func getAllStops() {
NetworkManager.shared.getAllStops { result in
func getMetroStops() {
NetworkManager.shared.getStops(metroOnly: true) { result in
DispatchQueue.main.async {
switch result {
case let .success(stops):

allStops = stops

metroStops = stops
case let .failure(error):
print(error.localizedDescription)
}
}
}
}

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)
}
}
}
}
}

#Preview {
Expand Down
Loading

0 comments on commit 36f505b

Please sign in to comment.