diff --git a/Sources/ManualDCore/Room.swift b/Sources/ManualDCore/Room.swift index d3d58d8..6981917 100644 --- a/Sources/ManualDCore/Room.swift +++ b/Sources/ManualDCore/Room.swift @@ -68,7 +68,7 @@ extension Room { Room( id: UUID(0), projectID: UUID(0), - name: "Test", + name: "Kitchen", heatingLoad: 12345, coolingLoad: .init(total: 12345, sensible: 12345), registerCount: 2, @@ -78,20 +78,20 @@ extension Room { Room( id: UUID(1), projectID: UUID(1), - name: "Test", + name: "Bedroom - 1", heatingLoad: 12345, coolingLoad: .init(total: 12345, sensible: 12345), - registerCount: 2, + registerCount: 1, createdAt: Date(), updatedAt: Date() ), Room( id: UUID(2), projectID: UUID(2), - name: "Test", + name: "Family Room", heatingLoad: 12345, coolingLoad: .init(total: 12345, sensible: 12345), - registerCount: 2, + registerCount: 3, createdAt: Date(), updatedAt: Date() ), diff --git a/Sources/Styleguide/Buttons.swift b/Sources/Styleguide/Buttons.swift index 9390ffa..1d48af7 100644 --- a/Sources/Styleguide/Buttons.swift +++ b/Sources/Styleguide/Buttons.swift @@ -80,3 +80,12 @@ public struct EditButton: HTML, Sendable { } } } + +public struct PlusButton: HTML, Sendable { + + public init() {} + + public var body: some HTML { + button(.type(.button)) { SVG(.circlePlus) } + } +} diff --git a/Sources/Styleguide/Number.swift b/Sources/Styleguide/Number.swift index 1227a0a..fe261dc 100644 --- a/Sources/Styleguide/Number.swift +++ b/Sources/Styleguide/Number.swift @@ -8,6 +8,7 @@ public struct Number: HTML, Sendable { private var formatter: NumberFormatter { let formatter = NumberFormatter() formatter.maximumFractionDigits = fractionDigits + formatter.numberStyle = .decimal return formatter } diff --git a/Sources/ViewController/Live.swift b/Sources/ViewController/Live.swift index e654502..e03ce56 100644 --- a/Sources/ViewController/Live.swift +++ b/Sources/ViewController/Live.swift @@ -40,10 +40,7 @@ extension SiteRoute.View.RoomRoute { func renderView(isHtmxRequest: Bool) async throws -> AnySendableHTML { switch self { case .form(let dismiss): - guard !dismiss else { - return div(.id("roomForm")) {} - } - return RoomForm() + return RoomForm(dismiss: dismiss) case .index: return MainPage(active: .rooms) { RoomsView(rooms: Room.mocks) diff --git a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift index 613f0f5..1bbc11d 100644 --- a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift +++ b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift @@ -7,16 +7,6 @@ struct EffectiveLengthForm: HTML, Sendable { let dismiss: Bool var body: some HTML { - // div( - // .id("effectiveLengthForm"), - // .class( - // """ - // fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800 - // bg-gray-200 border border-gray-400 - // rounded-lg shadow-lg mx-10 - // """ - // ) - // ) { ModalForm(id: "effectiveLengthForm", dismiss: dismiss) { h1(.class("text-2xl font-bold")) { "Effective Length" } form(.class("space-y-4 p-4")) { diff --git a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift index b92beef..6ef27d3 100644 --- a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift +++ b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift @@ -13,13 +13,19 @@ struct EffectiveLengthsView: HTML, Sendable { ) { Row { h1(.class("text-2xl font-bold")) { "Effective Lengths" } - button( - .hx.get(route: .effectiveLength(.form(dismiss: false))), - .hx.target("#effectiveLengthForm"), - .hx.swap(.outerHTML) - ) { - Icon(.circlePlus) - } + PlusButton() + .attributes( + .hx.get(route: .effectiveLength(.form(dismiss: false))), + .hx.target("#effectiveLengthForm"), + .hx.swap(.outerHTML) + ) + // button( + // .hx.get(route: .effectiveLength(.form(dismiss: false))), + // .hx.target("#effectiveLengthForm"), + // .hx.swap(.outerHTML) + // ) { + // Icon(.circlePlus) + // } } .attributes(.class("pb-6")) @@ -32,7 +38,7 @@ struct EffectiveLengthsView: HTML, Sendable { } } - div(.id("effectiveLengthForm")) {} + EffectiveLengthForm(dismiss: true) } } diff --git a/Sources/ViewController/Views/FrictionRate/ComponentLossesView.swift b/Sources/ViewController/Views/FrictionRate/ComponentLossesView.swift index 13cc9b7..68eca59 100644 --- a/Sources/ViewController/Views/FrictionRate/ComponentLossesView.swift +++ b/Sources/ViewController/Views/FrictionRate/ComponentLossesView.swift @@ -21,13 +21,12 @@ struct ComponentPressureLossesView: HTML, Sendable { ) { Row { h1(.class("text-2xl font-bold")) { "Component Pressure Losses" } - button( - .hx.get(route: .frictionRate(.form(.componentPressureLoss, dismiss: false))), - .hx.target("#componentLossForm"), - .hx.swap(.outerHTML) - ) { - Icon(.circlePlus) - } + PlusButton() + .attributes( + .hx.get(route: .frictionRate(.form(.componentPressureLoss, dismiss: false))), + .hx.target("#componentLossForm"), + .hx.swap(.outerHTML) + ) } for row in componentPressureLosses { @@ -44,7 +43,8 @@ struct ComponentPressureLossesView: HTML, Sendable { .attributes(.class("text-xl font-bold")) } } - div(.id("componentLossForm")) {} + // div(.id("componentLossForm")) {} + ComponentLossForm(dismiss: true) } } diff --git a/Sources/ViewController/Views/MainPage.swift b/Sources/ViewController/Views/MainPage.swift index 4478e02..8ccf44a 100644 --- a/Sources/ViewController/Views/MainPage.swift +++ b/Sources/ViewController/Views/MainPage.swift @@ -17,6 +17,7 @@ public struct MainPage: SendableHTMLDocument where Inner: Sendable script(.src("https://unpkg.com/htmx.org@2.0.8")) {} script(.src("https://cdn.tailwindcss.com")) {} script(.src("/js/main.js")) {} + script(.src("https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4")) {} link(.rel(.stylesheet), .href("/css/main.css")) link(.rel(.icon), .href("/images/favicon.ico"), .custom(name: "type", value: "image/x-icon")) } diff --git a/Sources/ViewController/Views/Rooms/RoomForm.swift b/Sources/ViewController/Views/Rooms/RoomForm.swift index ba61792..51c72b5 100644 --- a/Sources/ViewController/Views/Rooms/RoomForm.swift +++ b/Sources/ViewController/Views/Rooms/RoomForm.swift @@ -8,17 +8,10 @@ import Styleguide // TODO: Need to hold the project ID in hidden input field. struct RoomForm: HTML, Sendable { + let dismiss: Bool + var body: some HTML { - div( - .id("roomForm"), - .class( - """ - fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800 - bg-gray-200 border border-gray-400 - rounded-lg shadow-lg mx-10 p-4 - """ - ) - ) { + ModalForm(id: "roomForm", dismiss: dismiss) { h1(.class("text-3xl font-bold pb-6")) { "Room" } form { div { diff --git a/Sources/ViewController/Views/Rooms/RoomsView.swift b/Sources/ViewController/Views/Rooms/RoomsView.swift index 0fbb9ec..e6ee2a9 100644 --- a/Sources/ViewController/Views/Rooms/RoomsView.swift +++ b/Sources/ViewController/Views/Rooms/RoomsView.swift @@ -11,14 +11,26 @@ struct RoomsView: HTML, Sendable { var body: some HTML { div(.class("m-10")) { Row { - h1(.class("text-3xl font-bold pb-6")) { "Rooms" } - button( - .hx.get(route: .room(.form(dismiss: false))), - .hx.target("#roomForm"), - .hx.swap(.outerHTML) - ) { - Icon(.circlePlus) - } + h1(.class("text-3xl font-bold pb-6")) { "Room Loads" } + // div( + // .class("tooltip"), + // .data("tip", value: "Add room") + // ) { + // PlusButton() + // .attributes( + // .hx.get(route: .room(.form(dismiss: false))), + // .hx.target("#roomForm"), + // .hx.swap(.outerHTML), + // .class("btn") + // ) + // } + HTMLRaw( + """ +
+ +
+ """ + ) } div( @@ -26,39 +38,98 @@ struct RoomsView: HTML, Sendable { .class( """ border border-gray-200 rounded-lg shadow-lg - space-y-4 p-4 + grid grid-cols-5 p-4 """ ) ) { // Header + Label("Name") + // Pushes items to right Row { - Label("Name") + div {} Label("Heating Load") + } + Row { + div {} Label("Cooling Total") + } + Row { + div {} Label("Cooling Sensible") + } + Row { + div {} Label("Register Count") } - .attributes(.class("border-b border-gray-200")) + + // Divider + div(.class("border-b border-gray-200 col-span-5 mb-2")) {} // Rows for row in rooms { + span { row.name } + // Pushes items to right Row { - span { row.name } + div {} Number(row.heatingLoad) .attributes(.class("text-red-500")) + } + Row { + div {} Number(row.coolingLoad.total) .attributes(.class("text-green-400")) + } + Row { + div {} Number(row.coolingLoad.sensible) .attributes(.class("text-blue-400")) + } + Row { + div {} Number(row.registerCount) } - .attributes(.class("border-b border-gray-200")) + + // Divider + div(.class("border-b border-gray-200 col-span-5 mb-2")) {} } + // Totals + Label("Total") + Row { + div {} + Number(rooms.heatingTotal) + .attributes(.class("bg-red-500 text-white font-bold rounded-lg shadow-lg px-4 py-2")) + } + Row { + div {} + Number(rooms.coolingTotal) + .attributes(.class("bg-green-400 text-white font-bold rounded-lg shadow-lg px-4 py-2")) + } + Row { + div {} + Number(rooms.coolingSensibleTotal) + .attributes(.class("bg-blue-400 text-white font-bold rounded-lg shadow-lg px-4 py-2")) + } + // Empty register count column + div {} } - div(.id("roomForm")) {} + RoomForm(dismiss: true) } } } + +extension Array where Element == Room { + var heatingTotal: Double { + reduce(into: 0) { $0 += $1.heatingLoad } + } + + var coolingTotal: Double { + reduce(into: 0) { $0 += $1.coolingLoad.total } + } + + var coolingSensibleTotal: Double { + reduce(into: 0) { $0 += $1.coolingLoad.sensible } + } +}