Skip to content

Commit

Permalink
feat(app): fresh app project
Browse files Browse the repository at this point in the history
  • Loading branch information
krystxf committed Oct 28, 2024
1 parent 501645d commit 5d4c519
Show file tree
Hide file tree
Showing 24 changed files with 1,307 additions and 0 deletions.
4 changes: 4 additions & 0 deletions apps/mobile/metro-now/common/const/api-const.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// metro-now
// https://github.com/krystxf/metro-now

let ENDPOINT: String = "https://api.metronow.dev"
29 changes: 29 additions & 0 deletions apps/mobile/metro-now/common/managers/location-manager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// metro-now
// https://github.com/krystxf/metro-now

import SwiftUI

import CoreLocation
import Foundation

class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()

@Published var location: CLLocation?

override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}

func locationManager(_: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
DispatchQueue.main.async {
self.location = location
}
}
}
}
121 changes: 121 additions & 0 deletions apps/mobile/metro-now/common/managers/network-manager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// metro-now
// https://github.com/krystxf/metro-now

import Foundation

final class NetworkManager {
static let shared = NetworkManager()

private init() {}

func getMetroStops(
completed: @escaping (Result<[ApiStop], FetchErrorNew>) -> Void
) {
guard let url = URL(string: "\(ENDPOINT)/stop/all?metroOnly=true") else {
completed(.failure(.invalidUrl))
return
}

let task = URLSession.shared.dataTask(
with: URLRequest(url: url)
) {
data, response, error in

if let _ = error {
completed(.failure(.general))
return
}

guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}

guard let data else {
completed(.failure(.invalidData))
return
}

do {
let decoder = JSONDecoder()
let decodedResponse = try decoder.decode([ApiStop].self, from: data)
completed(.success(decodedResponse))
return
} catch {
completed(.failure(.invalidData))
return
}
}

task.resume()
}

func getDepartures(
stopIds: [String], platformIds: [String], completed: @escaping (Result<[ApiDeparture], FetchErrorNew>) -> Void
) {
guard let baseUrl = URL(string: "\(ENDPOINT)/departure") else {
completed(.failure(.invalidUrl))
return
}

let platformsQueryParams: [URLQueryItem] = platformIds.map {
URLQueryItem(name: "platform[]", value: $0)
}
let stopsQueryParams: [URLQueryItem] = stopIds.map {
URLQueryItem(name: "stop[]", value: $0)
}

let url = baseUrl
.appending(queryItems: stopsQueryParams + platformsQueryParams + [
URLQueryItem(name: "metroOnly", value: "true"),
])
print(url)

let task = URLSession.shared.dataTask(
with: URLRequest(url: url)
) {
data, response, error in

if let _ = error {
completed(.failure(.general))
return
}

guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}

guard let data else {
print("Invalid data")
completed(.failure(.invalidData))
return
}

do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

let decodedResponse = try decoder.decode(
[ApiDeparture].self,
from: data
)

completed(.success(decodedResponse))
return
} catch {
completed(.failure(.invalidData))
return
}
}

task.resume()
}
}

enum FetchErrorNew: Error {
case invalidUrl
case invalidResponse
case invalidData
case general
}
37 changes: 37 additions & 0 deletions apps/mobile/metro-now/common/types/api-types.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// metro-now
// https://github.com/krystxf/metro-now

import Foundation

struct ApiStop: Codable {
let id, name: String
let avgLatitude, avgLongitude: Double
let platforms: [ApiPlatform]
}

struct ApiPlatform: Codable {
let id: String
let latitude, longitude: Double
let name: String
let isMetro: Bool
let routes: [ApiRoute]
}

struct ApiRoute: Codable {
let id, name: String
}

struct ApiDepartureDate: Codable {
let predicted: Date
let scheduled: Date
}

struct ApiDeparture: Codable {
let platformId: String
let headsign: String

let departure: ApiDepartureDate
let delay: Int

let route: String
}
8 changes: 8 additions & 0 deletions apps/mobile/metro-now/common/types/metro-line.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// metro-now
// https://github.com/krystxf/metro-now

enum MetroLine: String {
case A
case B
case C
}
13 changes: 13 additions & 0 deletions apps/mobile/metro-now/common/utils/metro-line.utils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// metro-now
// https://github.com/krystxf/metro-now

import SwiftUI

func getMetroLineColor(_ line: MetroLine?) -> Color? {
switch line {
case .A: .green
case .B: .yellow
case .C: .red
default: nil
}
}
86 changes: 86 additions & 0 deletions apps/mobile/metro-now/common/utils/station.utils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// metro-now
// https://github.com/krystxf/metro-now

func shortenStopName(_ stop: String) -> String {
if stop == "Nemocnice Motol" {
return "N. Motol"
} else if stop == "Jiřího z Poděbrad" {
return "J. z Poděbrad"
}

if stop.hasPrefix("Nádraží") {
return stop.replacingOccurrences(of: "Nádraží", with: "Nádr.")
} else if stop.hasSuffix("nádraží") {
return stop.replacingOccurrences(of: "nádraží", with: "nádr.")
}

if stop.hasPrefix("Náměstí") {
return stop.replacingOccurrences(of: "Náměstí", with: "Nám.")
} else if stop.hasSuffix("náměstí") {
return stop.replacingOccurrences(of: "náměstí", with: "nám")
}

return stop
}

// All metro stops
/*
Anděl
Bořislavka
Bubenská
Budějovická
Černý Most
Českomoravská
Dejvická
Depo Hostivař
Flora
Florenc
Háje
Hlavní nádraží
Hloubětín
Hradčanská
Hůrka
Chodov
I. P. Pavlova
Invalidovna
Jinonice
Jiřího z Poděbrad
Kačerov
Karlovo náměstí
Kobylisy
Kolbenova
Křižíkova
Ládví
Letňany
Luka
Lužiny
Malostranská
Masarykovo nádraží
Můstek
Muzeum
Nádraží Holešovice
Nádraží Veleslavín
Nádraží Vysočany
Náměstí Míru
Národní třída
Nemocnice Motol
Nové Butovice
Opatov
Palmovka
Pankrác
Petřiny
Praha-Rajská zahrada
Praha-Smíchov
Pražského povstání
Prosek
Radlická
Roztyly
Skalka
Staroměstská
Stodůlky
Strašnická
Střížkov
Vyšehrad
Zličín
Želivského
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors": [
{
"idiom": "universal"
}
],
"info": {
"author": "xcode",
"version": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"images": [
{
"idiom": "universal",
"platform": "watchos",
"size": "1024x1024"
}
],
"info": {
"author": "xcode",
"version": 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info": {
"author": "xcode",
"version": 1
}
}
Loading

0 comments on commit 5d4c519

Please sign in to comment.