113 lines
3.7 KiB
Swift
113 lines
3.7 KiB
Swift
import Elementary
|
|
import ElementaryHTMX
|
|
import Routes
|
|
import Styleguide
|
|
|
|
struct DehumidifierSizeForm: HTML {
|
|
|
|
let response: DehumidifierSize.Response?
|
|
|
|
init(response: DehumidifierSize.Response? = nil) {
|
|
self.response = response
|
|
}
|
|
|
|
var content: some HTML {
|
|
FormHeader(label: "Dehumidifier Sizing Calculator", svg: .droplets)
|
|
form(
|
|
// Using index to get the correct path, but really uses the `submit` end-point.
|
|
.hx.post(route: .dehumidifierSize(.index)),
|
|
.hx.target("#result")
|
|
) {
|
|
div(.class("space-y-6")) {
|
|
LabeledContent(label: "Latent Load (BTU/h)") {
|
|
Input(id: "latentLoad", placeholder: "Latent load from Manual-J")
|
|
.attributes(.type(.number), .step("0.1"), .min("0.1"), .autofocus, .required)
|
|
}
|
|
|
|
LabeledContent(label: "Indoor Temperature (°F)") {
|
|
Input(id: "temperature", placeholder: "Indoor dry bulb temperature")
|
|
.attributes(.type(.number), .step("0.1"), .min("0.1"), .required)
|
|
}
|
|
|
|
LabeledContent(label: "Indoor Humdity (%)") {
|
|
Input(id: "humidity", placeholder: "Relative humidity")
|
|
.attributes(.type(.number), .step("0.1"), .min("0.1"), .required)
|
|
}
|
|
|
|
div {
|
|
SubmitButton(label: "Calculate Dehumidifier Size")
|
|
}
|
|
}
|
|
}
|
|
div(.id("result")) {
|
|
if let response {
|
|
DehumidifierSizeResult(response: response)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct DehumidifierSizeResult: HTML {
|
|
let response: DehumidifierSize.Response
|
|
|
|
var content: some HTML {
|
|
ResultContainer(reset: .dehumidifierSize(.index)) {
|
|
div(.class("py-4 block")) {
|
|
// Display calculated metrics.
|
|
div(.class("""
|
|
mb-6 sm:grid sm:grid-cols-1 sm:gap-4 lg:flex items-center lg:justify-between
|
|
text-blue-500 dark:text-slate-200
|
|
""")) {
|
|
div {
|
|
span(.class("font-semibold")) { "Base Moisture Load: " }
|
|
span(.class("font-light")) { "\(double: response.pintsPerDay) pints/day" }
|
|
}
|
|
if response.requiredCapacity != response.pintsPerDay {
|
|
div {
|
|
span(.class("font-semibold")) { "Required Capacity (derated): " }
|
|
span(.class("font-light")) { "\(double: response.requiredCapacity) pints/day" }
|
|
}
|
|
}
|
|
}
|
|
|
|
p(.class("font-semibold mb-4 dark:text-yellow-300")) { "Recommended Size:" }
|
|
|
|
a(
|
|
.target("_blank"), .href(response.recommendedUrl ?? "#"), .rel("noopener noreferrer")
|
|
) {
|
|
div(.class("""
|
|
px-8 py-2 flex items-center justify-between border border-blue-700 rounded-lg shadow-lg group
|
|
dark:bg-blue-400 hover:bg-blue-300 hover:dark:bg-blue-600
|
|
transition-colors
|
|
""")) {
|
|
div {
|
|
span(.class("font-extrabold text-4xl text-blue-800")) { "\(response.recommendedSize) PPD" }
|
|
p(.class("text-sm mt-1")) { "Click to view recommended model →" }
|
|
}
|
|
|
|
div(.class("""
|
|
w-12 h-12 rounded-full flex items-center justify-center
|
|
bg-blue-500 dark:bg-blue-600
|
|
group-hover:bg-blue-600 group-hover:dark:bg-blue-700
|
|
transition-colors
|
|
""")) {
|
|
SVG(.droplets, color: .white)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Display warnings, if applicable
|
|
WarningBox(warnings: response.warnings)
|
|
|
|
Note {
|
|
"""
|
|
Sizing is based on continuous operation at rated conditions. Actual performance will vary based on
|
|
operating conditions. Consider Energy Star rated units for better efficiency. For whole-house
|
|
applications, ensure proper air distribution and drainage.
|
|
"""
|
|
}
|
|
}
|
|
}
|
|
}
|