feat: Adds page header styles, starts an Alert component.

This commit is contained in:
2026-01-14 23:09:28 -05:00
parent 86307dfa05
commit 1b88f81b5f
15 changed files with 272 additions and 140 deletions

View File

@@ -31,13 +31,12 @@ struct ComponentPressureLossesView: HTML, Sendable {
th { "Value" }
th {
div(.class("flex justify-end mx-auto")) {
Tooltip("Add Component Loss") {
PlusButton()
.attributes(
.class("btn-ghost text-2xl me-2"),
.showModal(id: ComponentLossForm.id())
)
}
PlusButton()
.attributes(
.class("btn-primary text-2xl me-2"),
.showModal(id: ComponentLossForm.id())
)
.tooltip("Add component loss")
}
}
}

View File

@@ -3,8 +3,6 @@ import ElementaryHTMX
import ManualDCore
import Styleguide
// TODO: Add trunk size table.
struct DuctSizingView: HTML, Sendable {
@Environment(ProjectViewValue.$projectID) var projectID
@@ -14,32 +12,40 @@ struct DuctSizingView: HTML, Sendable {
var body: some HTML {
div(.class("space-y-4")) {
PageTitle { "Duct Sizes" }
PageTitleRow {
div(.class("space-y-4")) {
PageTitle("Duct Sizes")
if rooms.count == 0 {
p(.class("text-error italic")) {
"Must complete all the previous sections to display duct sizing calculations."
}
} else {
RoomsTable(rooms: rooms)
div(.class("divider mb-6")) {}
}
Row {
h2(.class("text-2xl font-bold")) {
"Trunk / Runout Sizes"
}
PlusButton()
.attributes(
.class("me-6"),
.showModal(id: TrunkSizeForm.id())
Alert(
"""
Must complete all the previous sections to display duct sizing calculations.
"""
)
.hidden(when: rooms.count > 0)
.attributes(.class("text-error font-bold italic"))
}
}
if trunks.count > 0 {
div(.class("divider -mt-2")) {}
TrunkTable(trunks: trunks, rooms: rooms)
if rooms.count != 0 {
RoomsTable(rooms: rooms)
PageTitleRow {
PageTitle {
"Trunk / Runout Sizes"
}
PlusButton()
.attributes(
.class("btn-primary"),
.showModal(id: TrunkSizeForm.id())
)
.tooltip("Add trunk / runout")
}
if trunks.count > 0 {
TrunkTable(trunks: trunks, rooms: rooms)
}
}
TrunkSizeForm(rooms: rooms, dismiss: true)

View File

@@ -21,13 +21,14 @@ struct EffectiveLengthsView: HTML, Sendable {
var body: some HTML {
div(.class("space-y-4")) {
Row {
PageTitleRow {
PageTitle { "Equivalent Lengths" }
PlusButton()
.attributes(
.class("btn-ghost me-4"),
.class("btn-primary"),
.showModal(id: EffectiveLengthForm.id(nil))
)
.tooltip("Add equivalent length")
}
.attributes(.class("pb-6"))

View File

@@ -12,16 +12,15 @@ struct EquipmentInfoView: HTML, Sendable {
.id("equipmentInfo")
) {
Row {
PageTitle { "Equipment Info" }
PageTitleRow {
PageTitle { "Equipment Details" }
Tooltip("Edit equipment info") {
EditButton()
.attributes(
.class("btn-ghost"),
.showModal(id: EquipmentInfoForm.id)
)
}
EditButton()
.attributes(
.class("btn-primary"),
.showModal(id: EquipmentInfoForm.id)
)
.tooltip("Edit equipment details")
}
if let equipmentInfo {

View File

@@ -42,60 +42,75 @@ struct FrictionRateView: HTML, Sendable {
var body: some HTML {
div(.class("space-y-6")) {
div(.class("grid grid-cols-2 px-4")) {
PageTitleRow {
div(.class("grid grid-cols-2 px-4 gap-y-4")) {
PageTitle { "Friction Rate" }
PageTitle { "Friction Rate" }
div(.class("space-y-4 justify-end")) {
div(.class("space-y-4 justify-end")) {
if let frictionRateDesignValue {
LabeledContent("Friction Rate Design Value") {
Badge(number: frictionRateDesignValue, digits: 2)
.attributes(.class("\(badgeColor)"))
if let frictionRateDesignValue {
LabeledContent("Friction Rate Design Value") {
Badge(number: frictionRateDesignValue, digits: 2)
.attributes(.class("\(badgeColor)"))
}
.attributes(.class("justify-end"))
}
if let availableStaticPressure {
LabeledContent("Available Static Pressure") {
Badge(number: availableStaticPressure, digits: 2)
}
.attributes(.class("justify-end"))
}
.attributes(.class("justify-end"))
}
if let availableStaticPressure {
LabeledContent("Available Static Pressure") {
Badge(number: availableStaticPressure, digits: 2)
div(.class("text-error font-bold italic col-span-2")) {
Alert {
p {
"Must complete previous sections."
}
}
.attributes(.class("justify-end"))
.hidden(
when: availableStaticPressure != nil && frictionRateDesignValue != nil
)
Alert {
p {
"No component pressures losses"
}
}
.hidden(when: componentLosses.totalComponentPressureLoss > 0)
Alert {
p(.class("block")) {
"Calculated friction rate is below 0.02. The fan may not deliver the required CFM."
br()
" * Increase the blower speed"
br()
" * Increase the blower size"
br()
" * Decrease the Total Effective Length (TEL)"
}
}
.hidden(when: !showLowErrors)
Alert {
p(.class("block")) {
"Calculated friction rate is above 0.18. The fan may deliver too many CFM."
br()
" * Decrease the blower speed"
br()
" * Decreae the blower size"
br()
" * Increase the Total Effective Length (TEL)"
}
}
.hidden(when: !showHighErrors)
}
}
}
div(.class("text-error italic")) {
p {
"No component pressures losses"
}
.attributes(.class("hidden"), when: componentLosses.totalComponentPressureLoss > 0)
p {
"Calculated friction rate is below 0.02. The fan may not deliver the required CFM."
br()
" * Increase the blower speed"
br()
" * Increase the blower size"
br()
" * Decrease the Total Effective Length (TEL)"
}
.attributes(.class("hidden"), when: !showLowErrors)
p {
"Calculated friction rate is above 0.18. The fan may deliver too many CFM."
br()
" * Decrease the blower speed"
br()
" * Decreae the blower size"
br()
" * Increase the Total Effective Length (TEL)"
}
.attributes(.class("hidden"), when: !showHighErrors)
}
div(.class("divider")) {}
ComponentPressureLossesView(
componentPressureLosses: componentLosses, projectID: projectID
)

View File

@@ -82,7 +82,7 @@ public struct MainPage<Inner: HTML>: SendableHTMLDocument where Inner: Sendable
public var body: some HTML {
div(.class("flex flex-col min-h-screen min-w-full")) {
main(.class("overflow-auto grow")) {
main(.class("grow")) {
inner
}

View File

@@ -8,13 +8,15 @@ struct ProjectDetail: HTML, Sendable {
var body: some HTML {
div {
Row {
h1(.class("text-3xl font-bold")) { "Project" }
PageTitleRow {
PageTitle { "Project" }
EditButton()
.attributes(
.class("btn-ghost"),
.class("btn-primary"),
.on(.click, "projectForm.showModal()")
)
.tooltip("Edit project", position: .left)
}
table(.class("table table-zebra text-lg")) {

View File

@@ -13,63 +13,58 @@ struct RoomsView: HTML, Sendable {
var body: some HTML {
div(.class("flex w-full flex-col")) {
Row {
PageTitle { "Room Loads" }
PageTitleRow {
div(.class("flex grid grid-cols-3 w-full gap-y-4")) {
div(.class("flex justify-end items-end -my-2")) {
Tooltip("Project wide sensible heat ratio", position: .left) {
button(
.class(
"""
justify-end items-end p-4
hover:bg-neutral hover:text-white hover:rounded-lg
"""
),
.showModal(id: SHRForm.id)
) {
LabeledContent {
div(.class("flex justify-end items-end space-x-4")) {
Label {
div(.class("col-span-2")) {
PageTitle { "Room Loads" }
}
div(.class("flex justify-end grow")) {
Tooltip("Project wide sensible heat ratio", position: .left) {
button(
.class(
"""
btn btn-primary text-lg font-bold py-2
"""
),
.showModal(id: SHRForm.id)
) {
div(.class("flex grow justify-end items-end space-x-4")) {
span {
"Sensible Heat Ratio"
}
.attributes(.class("me-8"), when: sensibleHeatRatio == nil)
}
} content: {
if let sensibleHeatRatio {
Badge(number: sensibleHeatRatio)
} else {
SVG(.squarePen)
if let sensibleHeatRatio {
Badge(number: sensibleHeatRatio)
} else {
Badge { "set" }
}
}
}
.attributes(.class("border border-error"), when: sensibleHeatRatio == nil)
}
.attributes(.class("border rounded-lg border-error"), when: sensibleHeatRatio == nil)
}
div(.class("flex items-end space-x-4 font-bold")) {
span(.class("text-lg")) { "Heating Total" }
Badge(number: rooms.heatingTotal, digits: 0)
.attributes(.class("badge-error"))
}
div(.class("flex justify-center items-end space-x-4 my-auto font-bold")) {
span(.class("text-lg")) { "Cooling Total" }
Badge(number: rooms.coolingTotal, digits: 0)
.attributes(.class("badge-success"))
}
div(.class("flex grow justify-end items-end space-x-4 me-4 my-auto font-bold")) {
span(.class("text-lg")) { "Cooling Sensible" }
Badge(number: rooms.coolingSensible(shr: sensibleHeatRatio), digits: 0)
.attributes(.class("badge-info"))
}
}
}
div(.class("flex flex-wrap justify-between mt-6")) {
div(.class("flex items-end space-x-4")) {
Label { "Heating Total" }
Badge(number: rooms.heatingTotal, digits: 0)
.attributes(.class("badge-error"))
}
div(.class("flex items-end space-x-4")) {
Label { "Cooling Total" }
Badge(number: rooms.coolingTotal, digits: 0)
.attributes(.class("badge-success"))
}
div(.class("flex justify-end items-end space-x-4 me-4")) {
Label { "Cooling Sensible" }
Badge(number: rooms.coolingSensible(shr: sensibleHeatRatio), digits: 0)
.attributes(.class("badge-info"))
}
}
// .attributes(.class("mt-6 me-4"))
div(.class("divider")) {}
SHRForm(projectID: projectID, sensibleHeatRatio: sensibleHeatRatio)
table(.class("table table-zebra text-lg"), .id("roomsTable")) {
@@ -101,7 +96,7 @@ struct RoomsView: HTML, Sendable {
Tooltip("Add Room") {
PlusButton()
.attributes(
.class("btn-ghost mx-auto"),
.class("btn-primary mx-auto"),
.showModal(id: RoomForm.id())
)
.attributes(.class("tooltip-left"))