mirror of
https://github.com/tonytins/amtkstat.git
synced 2026-10-24 05:32:54 -04:00
Cleaned up and removed columns so it is what an actual Solari board would show
- This update adds ISO date/time helpers for Amtrak timestamps, refactors the train table to show arrival time, status, and track details, and tracks the current station context in the UI. - It also hardens station status decoding with a safe fallback to Unknown and simplifies the row model to match the new display.
This commit is contained in:
parent
ebff2c9c32
commit
bf67475107
3 changed files with 99 additions and 31 deletions
37
Sources/AmtrakStatus/AmtrakDateFormatting.swift
Normal file
37
Sources/AmtrakStatus/AmtrakDateFormatting.swift
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import Foundation
|
||||
|
||||
struct AmtrakDateFormatting {
|
||||
static let isoFormatter = ISO8601DateFormatter()
|
||||
|
||||
static let timeFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .none
|
||||
formatter.timeStyle = .short
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static let dateFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .none
|
||||
return formatter
|
||||
}()
|
||||
|
||||
static func time(from isoString: String?) -> String? {
|
||||
guard let isoString, !isoString.isEmpty, let date = isoFormatter.date(
|
||||
from: isoString) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return timeFormatter.string(from: date)
|
||||
}
|
||||
|
||||
static func date(from isoString: String?) -> String? {
|
||||
guard let isoString, !isoString.isEmpty, let date = isoFormatter.date(
|
||||
from: isoString) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return dateFormatter.string(from: date)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,9 @@
|
|||
import SwiftCrossUI
|
||||
import Foundation
|
||||
|
||||
extension Train {
|
||||
var displayNumber: String {
|
||||
let parts = trainID.split(separator: "-", maxSplits: 1)
|
||||
|
||||
guard parts.count <= 2 else {
|
||||
return trainNum
|
||||
}
|
||||
|
||||
return "\(trainNum) (\(parts[1]))"
|
||||
var serviceDate: String {
|
||||
AmtrakDateFormatting.date(from: createdAt) ?? "-"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -19,6 +14,9 @@ struct ContentView: View {
|
|||
@State var rows: [TrainStatusRow] = []
|
||||
@State var isLoading = false
|
||||
@State var errorMessage: String?
|
||||
@State var currentStation: String = ""
|
||||
|
||||
let unknown = "Unknown"
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
|
|
@ -56,11 +54,13 @@ struct ContentView: View {
|
|||
}
|
||||
|
||||
Table(rows) {
|
||||
TableColumn("Time", value: \TrainStatusRow.arrival)
|
||||
TableColumn("Number", value: \TrainStatusRow.trainNum)
|
||||
TableColumn("Route", value: \TrainStatusRow.routeName)
|
||||
TableColumn("Platform", value: \TrainStatusRow.platform)
|
||||
TableColumn("Origin", value: \TrainStatusRow.origin)
|
||||
TableColumn("Destination", value: \TrainStatusRow.destination)
|
||||
TableColumn("Train", value: \TrainStatusRow.routeName)
|
||||
TableColumn("To", value: \TrainStatusRow.origin)
|
||||
TableColumn("From", value: \TrainStatusRow.destination)
|
||||
TableColumn("Status", value: \TrainStatusRow.status)
|
||||
TableColumn("Track", value: \TrainStatusRow.platform)
|
||||
|
||||
}.overlay(alignment: .bottomTrailing) {
|
||||
if isLoading {
|
||||
|
|
@ -73,6 +73,8 @@ struct ContentView: View {
|
|||
HStack {
|
||||
if let errorMessage {
|
||||
Text(errorMessage)
|
||||
} else if !currentStation.isEmpty {
|
||||
Text(currentStation)
|
||||
}
|
||||
}.padding(10)
|
||||
}
|
||||
|
|
@ -117,17 +119,7 @@ struct ContentView: View {
|
|||
where: { $0.code == code
|
||||
},
|
||||
)?.platform
|
||||
|
||||
newRows.append(TrainStatusRow(
|
||||
trainID: train.trainID,
|
||||
trainNum: train.displayNumber,
|
||||
routeName: train.routeName,
|
||||
origin: train.origName,
|
||||
destination: train.destName,
|
||||
platform: (
|
||||
platform?.isEmpty == false,
|
||||
) ? platform! : "",
|
||||
))
|
||||
newRows.append(trainStatus(for: train, atStationCode: code))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,4 +133,43 @@ struct ContentView: View {
|
|||
rows = []
|
||||
}
|
||||
}
|
||||
|
||||
func isOnTime(arr: String?, schArr: String?) -> String {
|
||||
let amtrakDate = AmtrakDateFormatting()
|
||||
|
||||
if AmtrakDateFormatting
|
||||
.time(from: arr) != AmtrakDateFormatting
|
||||
.time(from: schArr) {
|
||||
return "Late"
|
||||
}
|
||||
|
||||
return "On Time"
|
||||
}
|
||||
|
||||
func trainStatus(for train: Train, atStationCode code: String) -> TrainStatusRow {
|
||||
let leg = train.stations?.first { $0.code == code }
|
||||
let platform = leg?.platform ?? "-"
|
||||
let stationName = leg?.name ?? unknown
|
||||
let arrival = AmtrakDateFormatting.time(from: leg?.arr) ?? AmtrakDateFormatting.time(
|
||||
from: leg?.schArr
|
||||
)
|
||||
let depature = AmtrakDateFormatting.time(from: leg?.dep) ?? AmtrakDateFormatting.time(
|
||||
from: leg?.schDep
|
||||
)
|
||||
|
||||
currentStation = "\(stationName) station"
|
||||
|
||||
return TrainStatusRow(
|
||||
trainID: train.trainID,
|
||||
trainNum: train.trainNum,
|
||||
routeName: train.routeName,
|
||||
status: isOnTime(arr: leg?.arr, schArr: leg?.schArr),
|
||||
platform: leg?.platform ?? "",
|
||||
arrival: arrival ?? "",
|
||||
departure: depature ?? "",
|
||||
origin: train.origName,
|
||||
destination: train.destName,
|
||||
// serviceDate: train.serviceDate
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@ enum StationStatus: String, Codable, Sendable {
|
|||
case station = "Station"
|
||||
case departed = "Departed"
|
||||
case unknown = "Unknown"
|
||||
|
||||
init(from decoder: any Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let rawValue = try container.decode(String.self)
|
||||
self = StationStatus(rawValue: rawValue) ?? .unknown
|
||||
}
|
||||
}
|
||||
|
||||
struct Train: Codable {
|
||||
|
|
@ -83,12 +89,6 @@ struct StaleData: Codable {
|
|||
typealias TrainResponse = [String: [Train]]
|
||||
typealias StationResponse = [String: StationMeta]
|
||||
|
||||
struct AmtrakDateFormatting {
|
||||
let isoFormatter = ISO8601DateFormatter()
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct TrainStatusRow: Identifiable {
|
||||
var id: String {
|
||||
trainID
|
||||
|
|
@ -96,12 +96,12 @@ struct TrainStatusRow: Identifiable {
|
|||
|
||||
var trainID: String
|
||||
var trainNum: String
|
||||
var originating: String
|
||||
var routeName: String
|
||||
var status: String
|
||||
var platform: String
|
||||
var arrival: String
|
||||
var departure: String
|
||||
var origin: String
|
||||
var syatus: String
|
||||
var destination: String
|
||||
// var serviceDate: String
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue