import Dependencies import Elementary import ElementaryHTMX import Foundation import ManualDCore import Styleguide struct RoomsView: HTML, Sendable { @Environment(ProjectViewValue.$projectID) var projectID // let projectID: Project.ID let rooms: [Room] let sensibleHeatRatio: Double? var body: some HTML { div(.class("flex w-full flex-col")) { PageTitleRow { div(.class("flex grid grid-cols-3 w-full gap-y-4")) { div(.class("col-span-2")) { PageTitle { "Room Loads" } } div(.class("flex justify-end grow")) { Tooltip("Set 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" } if let sensibleHeatRatio { Badge(number: sensibleHeatRatio) } else { Badge { "set" } } } } .attributes(.class("border border-error"), when: sensibleHeatRatio == nil) } .attributes(.class("tooltip-open"), when: sensibleHeatRatio == nil) } div(.class("flex items-end space-x-4 font-bold")) { span(.class("text-lg")) { "Heating Total" } Badge(number: rooms.totalHeatingLoad, 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" } // TODO: ResultView ?? Badge(number: try! rooms.totalCoolingLoad(shr: sensibleHeatRatio ?? 1.0), 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" } // TODO: ResultView ?? Badge(number: try! rooms.totalCoolingSensible(shr: sensibleHeatRatio ?? 1.0), digits: 0) .attributes(.class("badge-info")) } } } SHRForm( sensibleHeatRatio: sensibleHeatRatio, dismiss: true ) table(.class("table table-zebra text-lg"), .id("roomsTable")) { thead { tr(.class("text-lg font-bold")) { th { "Name" } th { div(.class("flex justify-center")) { "Heating Load" } } th { div(.class("flex justify-center")) { "Cooling Total" } } th { div(.class("flex justify-center")) { "Cooling Sensible" } } th { div(.class("flex justify-center")) { "Register Count" } } th { div(.class("flex justify-end me-2")) { Tooltip("Add Room") { PlusButton() .attributes( .class("btn-primary mx-auto"), .showModal(id: RoomForm.id()) ) .attributes(.class("tooltip-left")) } } } } } tbody { for room in rooms { RoomRow(room: room, shr: sensibleHeatRatio) } } } RoomForm(dismiss: true, projectID: projectID, room: nil) } } public struct RoomRow: HTML, Sendable { let room: Room let shr: Double var coolingSensible: Double { try! room.coolingLoad.ensured(shr: shr).sensible // guard let value = room.coolingSensible else { // return room.coolingTotal * shr // } // return value } init(room: Room, shr: Double?) { self.room = room self.shr = shr ?? 1.0 } public var body: some HTML { tr(.id("roomRow_\(room.id.idString)")) { td { room.name } td { div(.class("flex justify-center")) { Number(room.heatingLoad, digits: 0) // .attributes(.class("text-error")) } } td { div(.class("flex justify-center")) { Number(try! room.coolingLoad.ensured(shr: shr).total, digits: 0) // .attributes(.class("text-success")) } } td { div(.class("flex justify-center")) { Number(coolingSensible, digits: 0) // .attributes(.class("text-info")) } } td { div(.class("flex justify-center")) { Number(room.registerCount) } } td { div(.class("flex justify-end")) { div(.class("join")) { Tooltip("Delete room", position: .bottom) { TrashButton() .attributes( .class("join-item btn-ghost"), .hx.delete( route: .project(.detail(room.projectID, .rooms(.delete(id: room.id))))), .hx.target("closest tr"), .hx.confirm("Are you sure?") ) } Tooltip("Edit room", position: .bottom) { EditButton() .attributes( .class("join-item btn-ghost"), .showModal(id: RoomForm.id(room)) ) } } } RoomForm( dismiss: true, projectID: room.projectID, room: room ) } } } } struct SHRForm: HTML, Sendable { static let id = "shrForm" @Environment(ProjectViewValue.$projectID) var projectID let sensibleHeatRatio: Double? let dismiss: Bool var route: String { SiteRoute.View.router .path(for: .project(.detail(projectID, .rooms(.index)))) .appendingPath("update-shr") } var body: some HTML { ModalForm(id: Self.id, dismiss: dismiss) { h1(.class("text-xl font-bold mb-6")) { "Sensible Heat Ratio" } form( .class("grid grid-cols-1 gap-4"), .hx.patch(route), .hx.target("body"), .hx.swap(.outerHTML) ) { input(.class("hidden"), .name("projectID"), .value("\(projectID)")) LabeledInput( "SHR", .name("sensibleHeatRatio"), .type(.number), .value(sensibleHeatRatio), .placeholder("0.83"), .min("0"), .max("1"), .step("0.01"), .autofocus ) SubmitButton() .attributes(.class("btn-block my-6")) } } } } }