feat: ✨ Ability to view stations from the API
Addition of a single component for stations; creation of structure; creation of function to retrieve bikes in real time
This commit is contained in:
parent
752a1f8b32
commit
701d163547
@ -11,6 +11,9 @@
|
|||||||
2C5BDABF2AA3611000DBEC93 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BDABE2AA3611000DBEC93 /* ContentView.swift */; };
|
2C5BDABF2AA3611000DBEC93 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BDABE2AA3611000DBEC93 /* ContentView.swift */; };
|
||||||
2C5BDAC12AA3611000DBEC93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C5BDAC02AA3611000DBEC93 /* Assets.xcassets */; };
|
2C5BDAC12AA3611000DBEC93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C5BDAC02AA3611000DBEC93 /* Assets.xcassets */; };
|
||||||
2C5BDAC52AA3611000DBEC93 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C5BDAC42AA3611000DBEC93 /* Preview Assets.xcassets */; };
|
2C5BDAC52AA3611000DBEC93 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C5BDAC42AA3611000DBEC93 /* Preview Assets.xcassets */; };
|
||||||
|
2CDC317E2AA3654800BF98B9 /* VelibStationStruct.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CDC317D2AA3654800BF98B9 /* VelibStationStruct.swift */; };
|
||||||
|
2CDC31802AA3672600BF98B9 /* StationComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CDC317F2AA3672600BF98B9 /* StationComponent.swift */; };
|
||||||
|
2CDC31822AA387AB00BF98B9 /* fetchVelibData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CDC31812AA387AB00BF98B9 /* fetchVelibData.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@ -20,6 +23,9 @@
|
|||||||
2C5BDAC02AA3611000DBEC93 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
2C5BDAC02AA3611000DBEC93 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
2C5BDAC22AA3611000DBEC93 /* velibtracker.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = velibtracker.entitlements; sourceTree = "<group>"; };
|
2C5BDAC22AA3611000DBEC93 /* velibtracker.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = velibtracker.entitlements; sourceTree = "<group>"; };
|
||||||
2C5BDAC42AA3611000DBEC93 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
2C5BDAC42AA3611000DBEC93 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||||
|
2CDC317D2AA3654800BF98B9 /* VelibStationStruct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VelibStationStruct.swift; sourceTree = "<group>"; };
|
||||||
|
2CDC317F2AA3672600BF98B9 /* StationComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StationComponent.swift; sourceTree = "<group>"; };
|
||||||
|
2CDC31812AA387AB00BF98B9 /* fetchVelibData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = fetchVelibData.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -52,11 +58,14 @@
|
|||||||
2C5BDABB2AA3611000DBEC93 /* velibtracker */ = {
|
2C5BDABB2AA3611000DBEC93 /* velibtracker */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
2CDC317C2AA3653200BF98B9 /* struct */,
|
||||||
|
2C5BDACB2AA3632C00DBEC93 /* components */,
|
||||||
2C5BDABC2AA3611000DBEC93 /* velibtrackerApp.swift */,
|
2C5BDABC2AA3611000DBEC93 /* velibtrackerApp.swift */,
|
||||||
2C5BDABE2AA3611000DBEC93 /* ContentView.swift */,
|
2C5BDABE2AA3611000DBEC93 /* ContentView.swift */,
|
||||||
2C5BDAC02AA3611000DBEC93 /* Assets.xcassets */,
|
2C5BDAC02AA3611000DBEC93 /* Assets.xcassets */,
|
||||||
2C5BDAC22AA3611000DBEC93 /* velibtracker.entitlements */,
|
2C5BDAC22AA3611000DBEC93 /* velibtracker.entitlements */,
|
||||||
2C5BDAC32AA3611000DBEC93 /* Preview Content */,
|
2C5BDAC32AA3611000DBEC93 /* Preview Content */,
|
||||||
|
2CDC31812AA387AB00BF98B9 /* fetchVelibData.swift */,
|
||||||
);
|
);
|
||||||
path = velibtracker;
|
path = velibtracker;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -69,6 +78,22 @@
|
|||||||
path = "Preview Content";
|
path = "Preview Content";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
2C5BDACB2AA3632C00DBEC93 /* components */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
2CDC317F2AA3672600BF98B9 /* StationComponent.swift */,
|
||||||
|
);
|
||||||
|
path = components;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
2CDC317C2AA3653200BF98B9 /* struct */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
2CDC317D2AA3654800BF98B9 /* VelibStationStruct.swift */,
|
||||||
|
);
|
||||||
|
path = struct;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@ -139,7 +164,10 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
2CDC317E2AA3654800BF98B9 /* VelibStationStruct.swift in Sources */,
|
||||||
2C5BDABF2AA3611000DBEC93 /* ContentView.swift in Sources */,
|
2C5BDABF2AA3611000DBEC93 /* ContentView.swift in Sources */,
|
||||||
|
2CDC31822AA387AB00BF98B9 /* fetchVelibData.swift in Sources */,
|
||||||
|
2CDC31802AA3672600BF98B9 /* StationComponent.swift in Sources */,
|
||||||
2C5BDABD2AA3611000DBEC93 /* velibtrackerApp.swift in Sources */,
|
2C5BDABD2AA3611000DBEC93 /* velibtrackerApp.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Bucket
|
||||||
|
uuid = "E086F483-B1A2-457D-A7AA-DFBB29D4A987"
|
||||||
|
type = "1"
|
||||||
|
version = "2.0">
|
||||||
|
</Bucket>
|
@ -9,16 +9,20 @@ import SwiftUI
|
|||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
NavigationView {
|
||||||
Image(systemName: "globe")
|
ScrollView {
|
||||||
.imageScale(.large)
|
ForEach(velibStations, id: \.stationcode) { station in
|
||||||
.foregroundColor(.accentColor)
|
StationComponent(station: station)
|
||||||
Text("Hello, world!")
|
.padding(.bottom, 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationBarTitle("Stations Vélib")
|
||||||
}
|
}
|
||||||
.padding()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct ContentView_Previews: PreviewProvider {
|
struct ContentView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ContentView()
|
ContentView()
|
||||||
|
48
velibtracker/components/StationComponent.swift
Normal file
48
velibtracker/components/StationComponent.swift
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// StationComponent.swift
|
||||||
|
// velibtracker
|
||||||
|
//
|
||||||
|
// Created by Louis Gallet on 02/09/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct StationComponent: View {
|
||||||
|
|
||||||
|
let station: VelibStation
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text(station.name)
|
||||||
|
.font(.title)
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text("Capacité: \(station.capacity)")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text("Disponibles: \(station.numbikesavailable)")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(Color.white)
|
||||||
|
.cornerRadius(10)
|
||||||
|
.shadow(radius: 5)
|
||||||
|
.padding(.horizontal, 16)
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct StationComponent_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
StationComponent(station: test[1])
|
||||||
|
}
|
||||||
|
}
|
52
velibtracker/fetchVelibData.swift
Normal file
52
velibtracker/fetchVelibData.swift
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// fetchVelibData.swift
|
||||||
|
// velibtracker
|
||||||
|
//
|
||||||
|
// Created by Louis Gallet on 02/09/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
var velibStations: [VelibStation] = []
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
func fetchVelibData() {
|
||||||
|
// L'URL de l'API Vélib
|
||||||
|
let apiUrl = URL(string: "https://opendata.paris.fr/api/explore/v2.1/catalog/datasets/velib-disponibilite-en-temps-reel/records?select=stationcode,name,capacity,numdocksavailable,numbikesavailable,mechanical,ebike,coordonnees_geo")!
|
||||||
|
|
||||||
|
// Créez une session URLSession pour effectuer la requête
|
||||||
|
let session = URLSession.shared
|
||||||
|
|
||||||
|
// Créez la tâche de requête
|
||||||
|
let task = session.dataTask(with: apiUrl) { (data, response, error) in
|
||||||
|
// Vérifiez s'il y a des erreurs
|
||||||
|
if let error = error {
|
||||||
|
print("Erreur de requête : \(error.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifiez si les données sont présentes
|
||||||
|
guard let data = data else {
|
||||||
|
print("Aucune donnée reçue.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Décodez les données en utilisant le décodeur JSON
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
let velibResponse = try decoder.decode(VelibResponse.self, from: data)
|
||||||
|
|
||||||
|
// Stockez les données dans la variable globale velibStations
|
||||||
|
velibStations = velibResponse.results
|
||||||
|
|
||||||
|
print("Données Vélib récupérées avec succès.")
|
||||||
|
} catch {
|
||||||
|
print("Erreur lors du décodage JSON : \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lancez la tâche de requête
|
||||||
|
task.resume()
|
||||||
|
}
|
75
velibtracker/struct/VelibStationStruct.swift
Normal file
75
velibtracker/struct/VelibStationStruct.swift
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// VelibStationStruct.swift
|
||||||
|
// velibtracker
|
||||||
|
//
|
||||||
|
// Created by Louis Gallet on 02/09/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct VelibResponse: Codable {
|
||||||
|
let totalCount: Int
|
||||||
|
let results: [VelibStation]
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case totalCount = "total_count"
|
||||||
|
case results
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VelibStation: Codable {
|
||||||
|
let stationcode: String
|
||||||
|
let name: String
|
||||||
|
let capacity: Int
|
||||||
|
let numdocksavailable: Int
|
||||||
|
let numbikesavailable: Int
|
||||||
|
let mechanical: Int
|
||||||
|
let ebike: Int
|
||||||
|
let coordonnees_geo: Coordinates
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Coordinates: Codable {
|
||||||
|
let lon: Double
|
||||||
|
let lat: Double
|
||||||
|
}
|
||||||
|
|
||||||
|
let test = [
|
||||||
|
VelibStation(stationcode: "293", name: "Test", capacity: 3, numdocksavailable: 3, numbikesavailable: 3, mechanical: 3, ebike: 1, coordonnees_geo: Coordinates(lon: 3.5939, lat: 2.59094)),
|
||||||
|
VelibStation(stationcode: "293R", name: "Test2", capacity: 5, numdocksavailable: 3, numbikesavailable: 2, mechanical: 3, ebike: 1, coordonnees_geo: Coordinates(lon: 5.5939, lat: 3.59094))
|
||||||
|
]
|
||||||
|
|
||||||
|
let testAPI2 = VelibResponse(totalCount: 2, results: [
|
||||||
|
VelibStation(stationcode: "293", name: "Test", capacity: 3, numdocksavailable: 3, numbikesavailable: 3, mechanical: 3, ebike: 1, coordonnees_geo: Coordinates(lon: 3.5939, lat: 2.59094)),
|
||||||
|
VelibStation(stationcode: "293R", name: "Test2", capacity: 5, numdocksavailable: 3, numbikesavailable: 2, mechanical: 3, ebike: 1, coordonnees_geo: Coordinates(lon: 5.5939, lat: 3.59094))
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
func fetchVelibStations(completion: @escaping ([VelibStation]?, Error?) -> Void) {
|
||||||
|
guard let url = URL(string: "https://opendata.paris.fr/api/explore/v2.1/catalog/datasets/velib-disponibilite-en-temps-reel/records?select=stationcode,name,capacity,numdocksavailable,numbikesavailable,mechanical,ebike,coordonnees_geo") else {
|
||||||
|
completion(nil, NSError(domain: "fr.louisgallet.velibtracker", code: 1, userInfo: nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
URLSession.shared.dataTask(with: url) { data, response, error in
|
||||||
|
if let error = error {
|
||||||
|
completion(nil, error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let data = data else {
|
||||||
|
completion(nil, NSError(domain: "fr.louisgallet.velibtracker", code: 2, userInfo: nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
do {
|
||||||
|
let velibResponse = try decoder.decode(VelibResponse.self, from: data)
|
||||||
|
let stations = velibResponse.results
|
||||||
|
// Utilisez la liste des stations dans votre application
|
||||||
|
} catch {
|
||||||
|
print("Erreur lors du décodage JSON : \(error)")
|
||||||
|
}
|
||||||
|
print("Fetched + decoded")
|
||||||
|
}.resume()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -14,4 +14,7 @@ struct velibtrackerApp: App {
|
|||||||
ContentView()
|
ContentView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
init() {
|
||||||
|
fetchVelibData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user