feat: Adds hydronic system pressure calculator.
This commit is contained in:
3
Sources/ViewController/Extensions/String+units.swift
Normal file
3
Sources/ViewController/Extensions/String+units.swift
Normal file
@@ -0,0 +1,3 @@
|
||||
public extension String {
|
||||
static let fahrenheit = "°F"
|
||||
}
|
||||
@@ -61,6 +61,12 @@ struct HomePage: HTML, Sendable {
|
||||
svg: .droplets,
|
||||
route: .psychrometrics(.index)
|
||||
)
|
||||
group(
|
||||
label: "Hydronic System Pressure",
|
||||
description: HydronicSystemPressure.description,
|
||||
svg: .circleGauge,
|
||||
route: .hydronicSystemPressure(.index)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,6 +133,15 @@ extension ViewController: DependencyKey {
|
||||
return HVACSystemPerformanceResult(response: response)
|
||||
}
|
||||
|
||||
case let .hydronicSystemPressure(route):
|
||||
switch route {
|
||||
case .index:
|
||||
return request.respond(HydronicSystemPressureForm(response: nil))
|
||||
case let .submit(request):
|
||||
let response = try await request.respond(logger: logger)
|
||||
return HydronicSystemPressureResponse(response: response)
|
||||
}
|
||||
|
||||
case let .moldRisk(route):
|
||||
switch route {
|
||||
case .index:
|
||||
|
||||
74
Sources/ViewController/Views/HydronicSystemPressure.swift
Normal file
74
Sources/ViewController/Views/HydronicSystemPressure.swift
Normal file
@@ -0,0 +1,74 @@
|
||||
import Elementary
|
||||
import ElementaryHTMX
|
||||
import PsychrometricClient
|
||||
import Routes
|
||||
import Styleguide
|
||||
|
||||
struct HydronicSystemPressureForm: HTML, Sendable {
|
||||
let response: HydronicSystemPressure.Response?
|
||||
|
||||
typealias Key = HydronicSystemPressure.Request.FieldKey
|
||||
|
||||
var content: some HTML {
|
||||
FormHeader(label: "Hydronic System Pressure", svg: .circleGauge)
|
||||
|
||||
form(
|
||||
.hx.post(route: .hydronicSystemPressure(.index)),
|
||||
.hx.target("#result")
|
||||
) {
|
||||
div(.class("space-y-6")) {
|
||||
div(.class("grid grid-cols-2 gap-4")) {
|
||||
LabeledContent(label: "Height (ft.)") {
|
||||
Input(id: Key.height, placeholder: "Building height")
|
||||
.attributes(.type(.number), .min("0.1"), .step("0.1"), .autofocus, .required)
|
||||
}
|
||||
|
||||
LabeledContent(label: "Water Temperature (\(String.fahrenheit))") {
|
||||
Input(id: Key.waterTemperature, placeholder: "Temperature (optional)")
|
||||
.attributes(.type(.number), .min("32.0"), .step("0.1"))
|
||||
}
|
||||
}
|
||||
|
||||
Note {
|
||||
"""
|
||||
Water temperature should be the coldest water temperature the system sees, which for boilers will be
|
||||
when the system is filled with water.
|
||||
"""
|
||||
}
|
||||
|
||||
div {
|
||||
SubmitButton(label: "Calculate System Pressure")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div(.id("result")) {
|
||||
if let response {
|
||||
HydronicSystemPressureResponse(response: response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct HydronicSystemPressureResponse: HTML, Sendable {
|
||||
let response: HydronicSystemPressure.Response
|
||||
|
||||
var content: some HTML {
|
||||
ResultContainer(reset: .hydronicSystemPressure(.index)) {
|
||||
ResultBox {
|
||||
div(.class("grid grid-cols-2")) {
|
||||
VerticalGroup(label: "Pressure", value: "\(double: response.pressure)", valueLabel: "psi")
|
||||
VerticalGroup(
|
||||
label: "Water Density",
|
||||
value: "\(double: response.waterDensity.value)",
|
||||
valueLabel: response.waterDensity.units.rawValue
|
||||
)
|
||||
}
|
||||
}
|
||||
WarningBox(warnings: response.warnings)
|
||||
Note {
|
||||
"Expansion tank pressure should match system fill pressure."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user