feat: Begins adding climate zone client and location clients.

This commit is contained in:
2025-03-03 17:04:02 -05:00
parent 1727e9a905
commit 9da4149391
8 changed files with 158 additions and 1 deletions

View File

@@ -9,6 +9,9 @@ let package = Package(
products: [ products: [
.executable(name: "App", targets: ["App"]), .executable(name: "App", targets: ["App"]),
.library(name: "ApiController", targets: ["ApiController"]), .library(name: "ApiController", targets: ["ApiController"]),
.library(name: "ClimateZoneClient", targets: ["ClimateZoneClient"]),
.library(name: "CoreModels", targets: ["CoreModels"]),
.library(name: "LocationClient", targets: ["LocationClient"]),
.library(name: "Routes", targets: ["Routes"]), .library(name: "Routes", targets: ["Routes"]),
.library(name: "Styleguide", targets: ["Styleguide"]), .library(name: "Styleguide", targets: ["Styleguide"]),
.library(name: "ViewController", targets: ["ViewController"]) .library(name: "ViewController", targets: ["ViewController"])
@@ -59,6 +62,27 @@ let package = Package(
], ],
swiftSettings: swiftSettings swiftSettings: swiftSettings
), ),
.target(
name: "LocationClient",
dependencies: [
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "DependenciesMacros", package: "swift-dependencies")
],
swiftSettings: swiftSettings
),
.target(
name: "ClimateZoneClient",
dependencies: [
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "DependenciesMacros", package: "swift-dependencies")
],
swiftSettings: swiftSettings
),
.target(
name: "CoreModels",
dependencies: [],
swiftSettings: swiftSettings
),
.target( .target(
name: "HTMLSnapshotTesting", name: "HTMLSnapshotTesting",
dependencies: [ dependencies: [
@@ -67,9 +91,18 @@ let package = Package(
], ],
swiftSettings: swiftSettings swiftSettings: swiftSettings
), ),
.target(
name: "LocationClient",
dependencies: [
.product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "DependenciesMacros", package: "swift-dependencies")
],
swiftSettings: swiftSettings
),
.target( .target(
name: "Routes", name: "Routes",
dependencies: [ dependencies: [
"CoreModels",
.product(name: "CasePaths", package: "swift-case-paths"), .product(name: "CasePaths", package: "swift-case-paths"),
.product(name: "Dependencies", package: "swift-dependencies"), .product(name: "Dependencies", package: "swift-dependencies"),
.product(name: "Elementary", package: "elementary"), .product(name: "Elementary", package: "elementary"),

View File

@@ -1,4 +1,4 @@
// TODO: This should be renamed to ClimateZoneType. import Foundation
public enum ClimateZone { public enum ClimateZone {

View File

@@ -0,0 +1,11 @@
/// Represents a location coordinates.
public struct Coordinates: Codable, Equatable, Sendable {
public let latitude: Double
public let longitude: Double
public init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}

View File

@@ -0,0 +1,11 @@
/// Represents design temperature conditions.
public struct DesignTemperatures: Codable, Equatable, Sendable {
public let cooling: Double
public let heating: Double
public init(cooling: Double, heating: Double) {
self.cooling = cooling
self.heating = heating
}
}

View File

@@ -0,0 +1,27 @@
import Foundation
public struct Location: Codable, Equatable, Sendable {
public let city: String
public let state: String
public let zipCode: String
public let stateCode: String
public let county: String
public let coordinates: Coordinates
public init(
city: String,
state: String,
stateCode: String,
zipCode: String,
county: String,
coordinates: Coordinates
) {
self.city = city
self.zipCode = zipCode
self.state = state
self.stateCode = stateCode
self.county = county
self.coordinates = coordinates
}
}

View File

@@ -0,0 +1,74 @@
import Dependencies
import DependenciesMacros
import Foundation
public extension DependencyValues {
var locationClient: LocationClient {
get { self[LocationClient.self] }
set { self[LocationClient.self] = newValue }
}
}
@DependencyClient
public struct LocationClient: Sendable {
public var search: @Sendable (Int) async throws -> [Response]
// TODO: Add ClimateZone.ZoneIdentifier??
public struct Response: Codable, Equatable, Sendable {
public let city: String
public let latitude: String
public let longitude: String
public let zipCode: String
public let state: String
public let stateCode: String
public let county: String
public init(
city: String,
latitude: String,
longitude: String,
zipCode: String,
state: String,
stateCode: String,
county: String
) {
self.city = city
self.latitude = latitude
self.longitude = longitude
self.zipCode = zipCode
self.state = state
self.stateCode = stateCode
self.county = county
}
private enum CodingKeys: String, CodingKey {
case city
case latitude
case longitude
case zipCode = "postal_code"
case state
case stateCode = "state_code"
case county = "province"
}
}
}
extension LocationClient: TestDependencyKey {
public static let testValue: LocationClient = Self()
}
#if DEBUG
public extension LocationClient.Response {
static let mock = Self(
city: "Monroe",
latitude: "39.4413000",
longitude: "-84.3652000",
zipCode: "45050",
state: "Ohio",
stateCode: "OH",
county: "Butler"
)
}
#endif

View File

@@ -1,4 +1,5 @@
import CasePaths import CasePaths
@_exported import CoreModels
import Foundation import Foundation
import PsychrometricClient import PsychrometricClient
@preconcurrency import URLRouting @preconcurrency import URLRouting