feat: Begins room-pressure calculator
This commit is contained in:
166
Sources/ViewController/Views/RoomPressure.swift
Normal file
166
Sources/ViewController/Views/RoomPressure.swift
Normal file
@@ -0,0 +1,166 @@
|
||||
import Elementary
|
||||
import ElementaryHTMX
|
||||
import Routes
|
||||
import Styleguide
|
||||
|
||||
struct RoomPressureForm: HTML, Sendable {
|
||||
let response: RoomPressure.Response?
|
||||
let mode: RoomPressure.Mode
|
||||
|
||||
init(mode: RoomPressure.Mode? = nil, response: RoomPressure.Response? = nil) {
|
||||
self.mode = mode ?? .knownAirflow
|
||||
self.response = response
|
||||
}
|
||||
|
||||
var content: some HTML {
|
||||
div(.class("relative")) {
|
||||
FormHeader(label: "Room Pressure Calculator", svg: .leftRightArrow)
|
||||
|
||||
// Mode toggle / buttons.
|
||||
div(.class("absolute top-0 right-0 flex items-center gap-x-0")) {
|
||||
switch mode {
|
||||
case .knownAirflow:
|
||||
SecondaryButton(label: "Known Airflow")
|
||||
.attributes(.class("rounded-s-lg"))
|
||||
.attributes(.disabled, when: mode == .knownAirflow)
|
||||
.attributes(
|
||||
.hx.get(route: .roomPressure(.index(mode: .knownAirflow))),
|
||||
.hx.target("#content"),
|
||||
when: mode == .measuredPressure
|
||||
)
|
||||
PrimaryButton(label: "Measured Pressure")
|
||||
.attributes(.class("rounded-e-lg"))
|
||||
.attributes(
|
||||
.hx.get(route: .roomPressure(.index(mode: .measuredPressure))),
|
||||
.hx.target("#content"),
|
||||
when: mode == .knownAirflow
|
||||
)
|
||||
case .measuredPressure:
|
||||
PrimaryButton(label: "Known Airflow")
|
||||
.attributes(.class("rounded-s-lg"))
|
||||
.attributes(
|
||||
.hx.get(route: .roomPressure(.index(mode: .knownAirflow))),
|
||||
.hx.target("#content"),
|
||||
when: mode == .measuredPressure
|
||||
)
|
||||
SecondaryButton(label: "Measured Pressure")
|
||||
.attributes(.class("rounded-e-lg"))
|
||||
.attributes(.disabled, when: mode == .measuredPressure)
|
||||
.attributes(
|
||||
.hx.get(route: .roomPressure(.index(mode: .measuredPressure))),
|
||||
.hx.target("#content"),
|
||||
when: mode == .knownAirflow
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Form(mode: mode)
|
||||
|
||||
div(.id("result")) {
|
||||
if let response {
|
||||
RoomPressureResult(response: response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Form: HTML, Sendable {
|
||||
let mode: RoomPressure.Mode
|
||||
|
||||
var content: some HTML<HTMLTag.form> {
|
||||
form {
|
||||
div(.class("space-y-6")) {
|
||||
LabeledContent(label: pressureLabel) {
|
||||
// NB: using .attributes(..., when:...) not working, so using a switch statement.
|
||||
switch mode {
|
||||
case .knownAirflow:
|
||||
Input(id: pressureID, placeholder: pressurePlaceholder)
|
||||
.attributes(.type(.number), .step("0.1"), .min("0.1"), .max("3.0"), .autofocus, .required)
|
||||
case .measuredPressure:
|
||||
Input(id: pressureID, placeholder: pressurePlaceholder)
|
||||
.attributes(.type(.number), .step("0.1"), .min("0.1"), .autofocus, .required)
|
||||
}
|
||||
}
|
||||
|
||||
DoorDetails()
|
||||
|
||||
if mode == .knownAirflow {
|
||||
LabeledContent(label: "Supply Airflow (CFM)") {
|
||||
Input(id: "supplyAirflow", placeholder: "Airflow")
|
||||
.attributes(.type(.number), .step("0.1"), .min("0.1"), .required)
|
||||
}
|
||||
}
|
||||
|
||||
PreferredGrilleHeight()
|
||||
|
||||
div {
|
||||
SubmitButton(label: "Calculate Return Path Size")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var pressureLabel: String {
|
||||
switch mode {
|
||||
case .knownAirflow: return "Target Room Pressure (Pascals)"
|
||||
case .measuredPressure: return "Measured Room Pressure (Pascals)"
|
||||
}
|
||||
}
|
||||
|
||||
private var pressureID: String {
|
||||
switch mode {
|
||||
case .knownAirflow: return "targetRoomPressure"
|
||||
case .measuredPressure: return "measuredRoomPressure"
|
||||
}
|
||||
}
|
||||
|
||||
private var pressurePlaceholder: String {
|
||||
switch mode {
|
||||
case .knownAirflow: return "Room pressure (max 3 pa.)"
|
||||
case .measuredPressure: return "Measure pressure"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct DoorDetails: HTML, Sendable {
|
||||
|
||||
var content: some HTML {
|
||||
div(.class("grid grid-cols-1 lg:grid-cols-2 gap-6")) {
|
||||
LabeledContent(label: "Door Width (in.)") {
|
||||
Input(id: "doorWidth", placeholder: "Width")
|
||||
.attributes(.type(.number), .step("0.1"), .min("0.1"), .required)
|
||||
}
|
||||
|
||||
LabeledContent(label: "Door Height (in.)") {
|
||||
Input(id: "doorHeight", placeholder: "Height")
|
||||
.attributes(.type(.number), .step("0.1"), .min("0.1"), .required)
|
||||
}
|
||||
}
|
||||
|
||||
LabeledContent(label: "Door Undercut (in.)") {
|
||||
Input(id: "doorUndercut", placeholder: "Undercut height")
|
||||
.attributes(.type(.number), .step("0.1"), .min("0.1"), .required)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct PreferredGrilleHeight: HTML, Sendable {
|
||||
|
||||
var content: some HTML {
|
||||
InputLabel(for: "preferredGrilleHeight") { "Preferred Grille Height" }
|
||||
select(
|
||||
.id("preferredGrilleHeight"),
|
||||
.name("preferredGrilleHeight"),
|
||||
.class("w-full px-4 py-2 rounded-md border")
|
||||
) {
|
||||
for height in RoomPressure.CommonReturnGrilleHeight.allCases {
|
||||
option(.value("\(height.rawValue)")) { height.label }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RoomPressureResult: HTML, Sendable {
|
||||
let response: RoomPressure.Response
|
||||
}
|
||||
Reference in New Issue
Block a user