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." } } } }