From ba994fc8f0f5602a93a1dbf7f74a890f61692aa1 Mon Sep 17 00:00:00 2001 From: Krystof Date: Fri, 17 May 2024 14:06:02 +0200 Subject: [PATCH] feat(app): previews --- .../metro-now-types/metroStationsTypes.swift | 2 +- .../metro-now-utils/metroUtils.swift | 8 ++ .../PlatformDetail/PlatformDetailView.swift | 2 +- .../Core/PlatformList/PlatformListItem.swift | 68 +++++++++++++--- .../Core/PlatformList/PlatformListView.swift | 78 ++++++++++++++++--- .../metro-now/Core/TabBar/MainTabView.swift | 22 ++++-- 6 files changed, 153 insertions(+), 27 deletions(-) diff --git a/app/metro-now/metro-now-types/metroStationsTypes.swift b/app/metro-now/metro-now-types/metroStationsTypes.swift index 87eb0d9..fb6b13c 100644 --- a/app/metro-now/metro-now-types/metroStationsTypes.swift +++ b/app/metro-now/metro-now-types/metroStationsTypes.swift @@ -25,7 +25,7 @@ struct MetroStationsGeoJSONFeatureGeometryProperties: Codable { let platforms: [MetroStationsGeoJSONFeatureGeometryPropertiesPlatform] } -struct MetroStationsGeoJSONFeatureGeometryPropertiesPlatform: Codable { +struct MetroStationsGeoJSONFeatureGeometryPropertiesPlatform: Codable, Hashable { let gtfsID: String? let name: String? let direction: String? diff --git a/app/metro-now/metro-now-utils/metroUtils.swift b/app/metro-now/metro-now-utils/metroUtils.swift index 2d5b5cd..907e045 100644 --- a/app/metro-now/metro-now-utils/metroUtils.swift +++ b/app/metro-now/metro-now-utils/metroUtils.swift @@ -40,6 +40,14 @@ func getMetroLineColor(_ letter: MetroLine) -> Color { } } +func getMetroLineIcon(_ letter: String) -> String { + "\(letter.lowercased()).circle.fill" +} + +func getMetroLineIcon(_ letter: MetroLine) -> String { + getMetroLineIcon(letter.rawValue) +} + func getClosestStationFromGeoJSON(location: CLLocation) -> MetroStationsGeoJSONFeature? { let stations: MetroStationsGeoJSON? = getParsedJSONFile(.METRO_STATIONS_FILE) diff --git a/app/metro-now/metro-now/Core/PlatformDetail/PlatformDetailView.swift b/app/metro-now/metro-now/Core/PlatformDetail/PlatformDetailView.swift index 56326a7..6732edf 100644 --- a/app/metro-now/metro-now/Core/PlatformDetail/PlatformDetailView.swift +++ b/app/metro-now/metro-now/Core/PlatformDetail/PlatformDetailView.swift @@ -8,7 +8,7 @@ import SwiftUI struct PlatformDetailView: View { - var direction: String + let direction: String var body: some View { ZStack { diff --git a/app/metro-now/metro-now/Core/PlatformList/PlatformListItem.swift b/app/metro-now/metro-now/Core/PlatformList/PlatformListItem.swift index 2c9c8b5..0893bca 100644 --- a/app/metro-now/metro-now/Core/PlatformList/PlatformListItem.swift +++ b/app/metro-now/metro-now/Core/PlatformList/PlatformListItem.swift @@ -10,33 +10,83 @@ import SwiftUI struct PlatformListItemView: View { var direction: String var departure: String + var metroLine: MetroLine var nextDeparture: String? var body: some View { HStack { - Text(direction) - .bold() + Label( + title: { Text(direction) }, + icon: { Image(systemName: getMetroLineIcon(metroLine)) } + ) + .fontWeight(.bold) + .font(.headline) + .foregroundStyle(.white) Spacer() VStack { - Text(departure).bold() + Text(departure) + .fontWeight(.bold) + .foregroundStyle(.white) + .foregroundStyle(.white) if let nextDeparture { - Text("Next in \(nextDeparture)") - .font(.caption2) - .foregroundStyle(.gray) + Text( + "Also in \(nextDeparture)" + ) + .font(.caption2) + .fontWeight(.bold) + .foregroundStyle(.white) + .opacity(0.9) } } } .padding(.horizontal, 20) .padding(.vertical, 10) + .background( + LinearGradient(colors: [ + getMetroLineColor(metroLine), + getMetroLineColor(metroLine).opacity(0.8), + ], + startPoint: .topLeading, + endPoint: .bottomTrailing) + ) + + .clipShape(.rect(cornerRadius: 15)) } } -#Preview { +#Preview("Last train") { + PlatformListItemView( + direction: "Nemocnice Motol", + departure: formatTime(seconds: 20), + metroLine: MetroLine.A + ) +} + +#Preview("Line A") { + PlatformListItemView( + direction: "Nemocnice Motol", + departure: formatTime(seconds: 20), + metroLine: MetroLine.A, + nextDeparture: formatTime(seconds: 220) + ) +} + +#Preview("Line B") { + PlatformListItemView( + direction: "Černý Most", + departure: formatTime(seconds: 20), + metroLine: MetroLine.B, + nextDeparture: formatTime(seconds: 220) + ) +} + +#Preview("Line C") { PlatformListItemView( direction: "Háje", - departure: "20s", - nextDeparture: "2m 20s" + departure: formatTime(seconds: 20), + metroLine: MetroLine.C, + nextDeparture: formatTime(seconds: 220) ) } diff --git a/app/metro-now/metro-now/Core/PlatformList/PlatformListView.swift b/app/metro-now/metro-now/Core/PlatformList/PlatformListView.swift index 0aacfee..19dcc76 100644 --- a/app/metro-now/metro-now/Core/PlatformList/PlatformListView.swift +++ b/app/metro-now/metro-now/Core/PlatformList/PlatformListView.swift @@ -2,26 +2,31 @@ // PlatformListView.swift // metro-now // -// Created by Kryštof Krátký on 14.05.2024. -// +import CoreLocation import SwiftUI struct PlatformsListView: View { + var station: MetroStationsGeoJSONFeature? + var body: some View { NavigationStack { ScrollView { LazyVStack(spacing: 10) { - ForEach(0 ... 4, id: \.self) { platform in - NavigationLink(value: platform) { - PlatformListItemView( - direction: "Háje", - departure: formatTime(seconds: 20) - ) + if let station { + ForEach(station.properties.platforms, id: \.self) { platform in + NavigationLink(value: platform) { + PlatformListItemView( + direction: platform.direction!, + departure: formatTime(seconds: 20), + metroLine: MetroLine(rawValue: platform.name!)!, + nextDeparture: formatTime(seconds: 200) + ) + } } } } - .padding(20) + .padding(10) } .navigationDestination(for: Int.self) { _ in @@ -29,10 +34,61 @@ struct PlatformsListView: View { direction: "Háje" ) } + .navigationTitle(station?.properties.name ?? "") } } } -#Preview { - PlatformsListView() +#Preview("Muzeum") { + PlatformsListView(station: getClosestStationFromGeoJSON( + location: CLLocation( + latitude: 50.078453, + longitude: 14.430676 + ) + )!) +} + +#Preview("Florenc") { + PlatformsListView(station: getClosestStationFromGeoJSON( + location: CLLocation( + latitude: 50.090583, + longitude: 14.438805 + ) + )!) +} + +#Preview("Můstek") { + PlatformsListView(station: getClosestStationFromGeoJSON( + location: CLLocation( + latitude: 50.083956, + longitude: 14.423844 + ) + )!) +} + +#Preview("Dejvická") { + PlatformsListView(station: getClosestStationFromGeoJSON( + location: CLLocation( + latitude: 50.100485, + longitude: 14.393898 + ) + )!) +} + +#Preview("Hlavní nádraží") { + PlatformsListView(station: getClosestStationFromGeoJSON( + location: CLLocation( + latitude: 50.082637, + longitude: 14.434300 + ) + )!) +} + +#Preview("Černý Most") { + PlatformsListView(station: getClosestStationFromGeoJSON( + location: CLLocation( + latitude: 50.111485, + longitude: 14.587877 + ) + )!) } diff --git a/app/metro-now/metro-now/Core/TabBar/MainTabView.swift b/app/metro-now/metro-now/Core/TabBar/MainTabView.swift index 12238b4..114581f 100644 --- a/app/metro-now/metro-now/Core/TabBar/MainTabView.swift +++ b/app/metro-now/metro-now/Core/TabBar/MainTabView.swift @@ -10,11 +10,13 @@ import SwiftUI struct MainTabView: View { @StateObject private var locationModel = LocationModel() + @State var closestStation: MetroStationsGeoJSONFeature? let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() var body: some View { TabView { - PlatformsListView() + PlatformsListView( + station: closestStation) .tabItem { Label("Near me", systemImage: "location.circle") } @@ -25,14 +27,24 @@ struct MainTabView: View { } } .onReceive(locationModel.$location) { location in + + guard let location else { + print("Unknown location") + return + } print("User's location: \(location)") + + let res = getClosestStationFromGeoJSON(location: location) + + guard let res else { + print("Unknown closest station") + return + } + + closestStation = res } .onAppear { locationModel.checkLocationServicesEnabled() } } } - -#Preview { - MainTabView() -}