import CasePaths import PsychrometricClient @preconcurrency import URLRouting public enum FeetOfHead { public static let description = """ Convert PSI to Feet of Head, to aid in pump flow calculations. """ public struct Request: Codable, Equatable, Hashable, Sendable { public let pressure: Double public let waterTemperature: Double? public init(pressure: Double, waterTemperature: Double? = nil) { self.pressure = pressure self.waterTemperature = waterTemperature } public enum FieldKey: String, CaseIterable { case pressure case waterTemperature } } public struct Response: Codable, Equatable, Sendable { public let feetOfHead: Double public let density: DensityOf public let warnings: [String] public init(feetOfHead: Double, density: DensityOf, warnings: [String]) { self.feetOfHead = feetOfHead self.density = density self.warnings = warnings } } } // MARK: - Router public extension SiteRoute.View { enum FeetOfHead: Equatable, Hashable, Sendable { case index case submit(Routes.FeetOfHead.Request) static let rootPath = "feet-of-head" typealias Key = Routes.FeetOfHead.Request.FieldKey public static let router = OneOf { Route(.case(Self.index)) { Path { rootPath } Method.get } Route(.case(Self.submit)) { Path { rootPath } Method.post Body { FormData { Field(Key.pressure) { Double.parser() } Optionally { Field(Key.waterTemperature) { Double.parser() } } } .map(.memberwise(Routes.FeetOfHead.Request.init)) } } } } } #if DEBUG public extension FeetOfHead.Response { static let mock = Self(feetOfHead: 7.95, density: 62.37, warnings: []) } #endif