Files
swift-hvac-toolbox/Sources/ViewController/Views/DehumidifierSize.swift

151 lines
5.0 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
if response.warnings.count > 0 {
div(.class("""
w-full mt-6 p-4 rounded-lg shadow-lg
text-amber-500
bg-amber-100 dark:bg-amber-200
border border-amber-500
""")) {
span(.class("font-semibold mb-4 border-b")) { "Warning\(response.warnings.count > 1 ? "s:" : ":")" }
ul(.class("list-disc mx-10")) {
for warning in response.warnings {
li { warning }
}
}
}
}
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.
"""
}
}
}
}
// <div className = "p-4 bg-white rounded-lg shadow-sm">
// <p className = Recommended < "text-sm text-gray-600 mb-2" Size: </p>
// <a
// href = { result.recommendedSize.url }
// target = "_blank"
// rel = "noopener noreferrer"
// className = "block p-4 bg-blue-100 rounded-lg hover:bg-blue-200 transition-colors group"
// >
// <div className = "flex items-center justify-between">
// <div>
// <span className = "text-2xl font-bold text-blue-700">
// { result.recommendedSize.size } PPD
// </span>
// <p className = "text-sm text-blue-600 mt-1">
// Click to view available models
// </p>
// </div>
// <div className = "w-12 h-12 bg-blue-200 rounded-full flex items-center justify-center group-hover:bg-blue-300 transition-colors">
// <Droplets className = "w-6 h-6 text-blue-700" />
// </div>
// </div>
// </a>
// </div >