92 lines
3.4 KiB
Swift
92 lines
3.4 KiB
Swift
import Elementary
|
|
import PsychrometricClient
|
|
import Routes
|
|
import Styleguide
|
|
|
|
struct MoldRiskForm: HTML {
|
|
|
|
var content: some HTML {
|
|
FormHeader(label: "Mold Risk Calculator", svg: .thermometer)
|
|
form {
|
|
div(.class("space-y-6")) {
|
|
LabeledContent(label: "Indoor Temperature (°F)") {
|
|
Input(id: "temperature", placeholder: "Dry bulb temperature")
|
|
.attributes(.type(.number), .step("0.1"), .min("0.1"), .autofocus)
|
|
}
|
|
|
|
LabeledContent(label: "Indor Humdity (%)") {
|
|
Input(id: "humidity", placeholder: "Relative humidity")
|
|
.attributes(.type(.number), .step("0.1"), .min("0.1"))
|
|
}
|
|
|
|
div {
|
|
SubmitButton(label: "Calculate Mold Risk")
|
|
}
|
|
|
|
div(.id("result")) {
|
|
MoldRiskResponse(response: .mock)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct MoldRiskResponse: HTML {
|
|
let response: MoldRisk.Response
|
|
|
|
var content: some HTML {
|
|
ResultContainer {
|
|
// TODO: Color needs to be derived from risk level.
|
|
div(.class("p-2 rounded-lg shadow-lg bg-lime-100 border-2 border border-lime-600")) {
|
|
LabeledContent {
|
|
p(.class("text-lg font-semibold \(text: .green) dark:text-lime-600 mt-2")) {
|
|
"Risk Level: \(response.riskLevel.rawValue.capitalized)"
|
|
}
|
|
} label: {
|
|
SVG(.exclamation, color: "\(text: .green) dark:text-lime-600")
|
|
}
|
|
.attributes(.class("flex items-center gap-2"))
|
|
}
|
|
|
|
PsychrometricPropertiesGrid(properties: response.psychrometricProperties)
|
|
.attributes(.class("mx-6"))
|
|
|
|
div(.class("mt-8 p-4 bg-gray-700 rounded-md shadow-md border border-blue-500")) {
|
|
p(.class("text-sm \(text: .blue)")) {
|
|
span(.class("font-extrabold pe-2")) { "Note:" }
|
|
"""
|
|
These calculations are based on typical indoor conditions and common mold species. Actual mold growth can
|
|
vary based on surface materials, air movement, and other environmental factors. Always address moisture
|
|
issues promptly and consult professionals for severe cases.
|
|
"""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct PsychrometricPropertiesGrid: HTML {
|
|
let properties: PsychrometricProperties
|
|
|
|
var content: some HTML<HTMLTag.div> {
|
|
div(.class("grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-6 md:mx-20")) {
|
|
displayProperty("Dew Point", "\(properties.dewPoint.value) \(properties.dewPoint.units.symbol)")
|
|
displayProperty("Wet Bulb", "\(properties.wetBulb.value) \(properties.wetBulb.units.symbol)")
|
|
displayProperty("Enthalpy", "\(properties.enthalpy.value) \(properties.wetBulb.units.symbol)")
|
|
displayProperty("Density", "\(properties.density.value) \(properties.density.units.rawValue)")
|
|
displayProperty("Vapor Pressure", "\(properties.vaporPressure.value) \(properties.vaporPressure.units.symbol)")
|
|
displayProperty("Specific Volume", "\(properties.specificVolume.rawValue)")
|
|
displayProperty("Absolute Humidity", "\(properties.absoluteHumidity.value) \(properties.absoluteHumidity.units.symbol)")
|
|
displayProperty("Humidity Ratio", "\(properties.humidityRatio.value)")
|
|
displayProperty("Degree of Saturation", "\(properties.degreeOfSaturation.value)")
|
|
}
|
|
}
|
|
|
|
func displayProperty(_ label: String, _ value: String) -> some HTML {
|
|
p(.class("\(text: .darkGray) dark:\(text: .white)")) {
|
|
span(.class("font-semibold")) { "\(label): " }
|
|
span(.class("font-light")) { value }
|
|
}
|
|
}
|
|
}
|