Skip to content

Commit 5a2dfcc

Browse files
committed
feat(app): link to station detail from map
1 parent dceab74 commit 5a2dfcc

File tree

6 files changed

+125
-14
lines changed

6 files changed

+125
-14
lines changed

app/Common/Types/departuresResponseTypes.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,3 @@ struct ApiDeparture: Codable {
99
let line: String
1010
let heading: String
1111
}
12-
13-

app/Common/Utils/networkUtils.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ func getDeparturesByGtfsID(gtfsIDs: [String]) async throws -> DeparturesByGtfsID
3737
decoder.keyDecodingStrategy = .convertFromSnakeCase
3838
decoder.dateDecodingStrategy = .iso8601
3939
return try decoder.decode(DeparturesByGtfsIDs.self, from: data)
40-
41-
}
42-
catch {
40+
} catch {
4341
throw FetchError.InvalidaData
4442
}
4543
}

app/metro-now.xcodeproj/project.pbxproj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 56;
6+
objectVersion = 70;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -41,6 +41,7 @@
4141
2D4D8F852C0010A5006F9080 /* networkUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D4D8F842C0010A5006F9080 /* networkUtils.swift */; };
4242
2D84CCA12BF8BD7500D2382B /* PlatformListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D84CCA02BF8BD7500D2382B /* PlatformListViewModel.swift */; };
4343
2D9213E92C081D99004A37C2 /* WidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D9213E82C081D99004A37C2 /* WidgetView.swift */; };
44+
2D94BD8E2C21DE250006CA04 /* StationLocationMapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D94BD8D2C21DE250006CA04 /* StationLocationMapView.swift */; };
4445
2DC639DC2BF3CCBA00A72C7F /* metro_nowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DC639DB2BF3CCBA00A72C7F /* metro_nowApp.swift */; };
4546
2DC639DE2BF3CCBA00A72C7F /* PlatformListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DC639DD2BF3CCBA00A72C7F /* PlatformListView.swift */; };
4647
2DC639E02BF3CCBC00A72C7F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DC639DF2BF3CCBC00A72C7F /* Assets.xcassets */; };
@@ -149,6 +150,7 @@
149150
2D4D8F842C0010A5006F9080 /* networkUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = networkUtils.swift; sourceTree = "<group>"; };
150151
2D84CCA02BF8BD7500D2382B /* PlatformListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformListViewModel.swift; sourceTree = "<group>"; };
151152
2D9213E82C081D99004A37C2 /* WidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetView.swift; sourceTree = "<group>"; };
153+
2D94BD8D2C21DE250006CA04 /* StationLocationMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StationLocationMapView.swift; sourceTree = "<group>"; };
152154
2DC639D82BF3CCBA00A72C7F /* metro-now.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "metro-now.app"; sourceTree = BUILT_PRODUCTS_DIR; };
153155
2DC639DB2BF3CCBA00A72C7F /* metro_nowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = metro_nowApp.swift; sourceTree = "<group>"; };
154156
2DC639DD2BF3CCBA00A72C7F /* PlatformListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformListView.swift; sourceTree = "<group>"; };
@@ -182,6 +184,10 @@
182184
2DF66D972BFD39B000B31FA2 /* test-coordinates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "test-coordinates.swift"; sourceTree = "<group>"; };
183185
/* End PBXFileReference section */
184186

187+
/* Begin PBXFileSystemSynchronizedRootGroup section */
188+
2D94BD892C21BFB90006CA04 /* StationDetail */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = StationDetail; sourceTree = "<group>"; };
189+
/* End PBXFileSystemSynchronizedRootGroup section */
190+
185191
/* Begin PBXFrameworksBuildPhase section */
186192
2D4486802BFAA10A005C59CE /* Frameworks */ = {
187193
isa = PBXFrameworksBuildPhase;
@@ -341,6 +347,7 @@
341347
2DC639E92BF3CD3900A72C7F /* Core */ = {
342348
isa = PBXGroup;
343349
children = (
350+
2D94BD892C21BFB90006CA04 /* StationDetail */,
344351
2DC63A062BF4C24C00A72C7F /* Map */,
345352
2DC639FE2BF4B1C600A72C7F /* PlatformDetail */,
346353
2DC639EA2BF3CD4700A72C7F /* PlatformList */,
@@ -381,6 +388,7 @@
381388
children = (
382389
2DC63A072BF4C25B00A72C7F /* MapView.swift */,
383390
2D350E662BFBE50600F68039 /* MapStationAnnotationView.swift */,
391+
2D94BD8D2C21DE250006CA04 /* StationLocationMapView.swift */,
384392
);
385393
path = Map;
386394
sourceTree = "<group>";
@@ -663,6 +671,7 @@
663671
2D1B2C3B2BFAD6CC007ED5EB /* LocationModel.swift in Sources */,
664672
2D350E672BFBE50600F68039 /* MapStationAnnotationView.swift in Sources */,
665673
2D1B2C422BFAD72C007ED5EB /* jsonUtils.swift in Sources */,
674+
2D94BD8E2C21DE250006CA04 /* StationLocationMapView.swift in Sources */,
666675
2D1B2C3F2BFAD70F007ED5EB /* timeUtils.swift in Sources */,
667676
2DC639DC2BF3CCBA00A72C7F /* metro_nowApp.swift in Sources */,
668677
2D4D8F852C0010A5006F9080 /* networkUtils.swift in Sources */,

app/metro-now/Core/Map/MapView.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import MapKit
66
import SwiftUI
77

88
private struct MetroStationAnnotation {
9-
let name: String
9+
var name: String
1010
let coordinate: CLLocationCoordinate2D
1111
let metroLines: [String] // A | B | C
1212
}
@@ -15,12 +15,16 @@ struct MapView: View {
1515
@State private var metroStationAnnotations: [MetroStationAnnotation] = []
1616

1717
var body: some View {
18-
Map {
19-
UserAnnotation()
18+
NavigationStack {
19+
Map {
20+
UserAnnotation()
2021

21-
ForEach(metroStationAnnotations, id: \.name) { station in
22-
Annotation(station.name, coordinate: station.coordinate) {
23-
MapMetroStationView(metroLines: station.metroLines)
22+
ForEach(metroStationAnnotations, id: \.name) { station in
23+
Annotation(station.name, coordinate: station.coordinate) {
24+
NavigationLink(destination: StationLocationMapView(stationName: station.name)) {
25+
MapMetroStationView(metroLines: station.metroLines)
26+
}
27+
}
2428
}
2529
}
2630
}
@@ -31,6 +35,7 @@ struct MapView: View {
3135
}
3236

3337
metroStationAnnotations = metroStationsGeoJSON.features.map { feature in
38+
3439
MetroStationAnnotation(
3540
name: feature.properties.name,
3641
coordinate: CLLocationCoordinate2D(
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
2+
import MapKit
3+
import SwiftUI
4+
5+
struct StationLocationMapView: View {
6+
let stationName: String
7+
let station: MetroStationsGeoJSONFeature
8+
let stationCoordinate: CLLocationCoordinate2D
9+
let distanceFormatter = MKDistanceFormatter()
10+
@StateObject private var locationModel = LocationModel()
11+
@State var distance: Double = -1
12+
13+
init(stationName: String) {
14+
self.stationName = stationName
15+
let stations: MetroStationsGeoJSON = getParsedJSONFile(.METRO_STATIONS_FILE)!
16+
station = stations.features.first(where: { $0.properties.name == stationName })!
17+
stationCoordinate = CLLocationCoordinate2D(latitude: station.geometry.coordinates[1], longitude: station.geometry.coordinates[0])
18+
}
19+
20+
var body: some View { ScrollView {
21+
ZStack {
22+
Text("Map")
23+
.hidden()
24+
.frame(height: 350)
25+
.frame(maxWidth: .infinity)
26+
}
27+
28+
.background(alignment: .bottom) {
29+
Map {
30+
Marker(stationName, coordinate: stationCoordinate)
31+
}
32+
33+
.mask {
34+
LinearGradient(
35+
stops: [
36+
.init(color: .clear, location: 0),
37+
.init(color: .black.opacity(0.15), location: 0.1),
38+
.init(color: .black, location: 0.6),
39+
.init(color: .black, location: 1),
40+
],
41+
startPoint: .top,
42+
endPoint: .bottom
43+
)
44+
}
45+
.padding(.top, -150)
46+
}
47+
.ignoresSafeArea(edges: .top)
48+
VStack(spacing: 20) {
49+
HStack(spacing: 20) {
50+
Button(action: {}) {
51+
Label("Navigate", systemImage: "figure.walk.circle.fill")
52+
.padding()
53+
.background(Color.blue)
54+
.foregroundColor(.white)
55+
.cornerRadius(8)
56+
}
57+
if distance > -1 {
58+
VStack(alignment: .leading) {
59+
Text("DISTANCE")
60+
.font(.subheadline)
61+
.foregroundColor(.secondary)
62+
Label {
63+
Text(distanceFormatter.string(fromDistance: distance))
64+
} icon: {
65+
Image(systemName: "point.topleft.down.to.point.bottomright.curvepath")
66+
.foregroundColor(.secondary)
67+
}
68+
}
69+
}
70+
Spacer()
71+
}
72+
73+
HStack {
74+
Text("Departures")
75+
.font(.headline)
76+
Spacer()
77+
}
78+
}
79+
.padding()
80+
}
81+
.navigationTitle(stationName)
82+
.onReceive(locationModel.$location) { location in
83+
84+
guard let location else {
85+
print("Unknown location")
86+
return
87+
}
88+
print("User's location: \(location)")
89+
90+
let userLocation = CLLocation(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
91+
let stationLocation = CLLocation(latitude: stationCoordinate.latitude, longitude: stationCoordinate.longitude)
92+
distance = userLocation.distance(from: stationLocation)
93+
}
94+
}
95+
}
96+
97+
#Preview {
98+
StationLocationMapView(
99+
stationName: "I. P. Pavlova"
100+
)
101+
}

app/metro-now/Core/PlatformList/PlatformListView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct PlatformsListView: View {
4141
// let platformDepartures = departuresByGtfsID?[platform.gtfsId]
4242
// let platformDepartures = departuresByGtfsID?[platform.gtfsId]
4343
// let direction = platformDepartures.first?.heading ?? platform.direction
44-
44+
4545
// NavigationLink {
4646
// PlatformDetailView(
4747
// defaultDirection: platform.direction,
@@ -77,7 +77,7 @@ struct PlatformsListView: View {
7777
// )
7878
// }
7979
// }
80-
//
80+
//
8181
// }
8282
}
8383
.padding(10)

0 commit comments

Comments
 (0)