WIP: Rooms table style updates in duct sizing tab, but room form is not working properly on all rows for some reason.

This commit is contained in:
2026-01-13 22:47:50 -05:00
parent 62a82ed674
commit 71848c607a
6 changed files with 196 additions and 250 deletions

View File

@@ -20,8 +20,6 @@
--spacing: 0.25rem; --spacing: 0.25rem;
--text-sm: 0.875rem; --text-sm: 0.875rem;
--text-sm--line-height: calc(1.25 / 0.875); --text-sm--line-height: calc(1.25 / 0.875);
--text-base: 1rem;
--text-base--line-height: calc(1.5 / 1);
--text-lg: 1.125rem; --text-lg: 1.125rem;
--text-lg--line-height: calc(1.75 / 1.125); --text-lg--line-height: calc(1.75 / 1.125);
--text-xl: 1.25rem; --text-xl: 1.25rem;
@@ -30,8 +28,6 @@
--text-2xl--line-height: calc(2 / 1.5); --text-2xl--line-height: calc(2 / 1.5);
--text-3xl: 1.875rem; --text-3xl: 1.875rem;
--text-3xl--line-height: calc(2.25 / 1.875); --text-3xl--line-height: calc(2.25 / 1.875);
--text-4xl: 2.25rem;
--text-4xl--line-height: calc(2.5 / 2.25);
--font-weight-bold: 700; --font-weight-bold: 700;
--radius-md: 0.375rem; --radius-md: 0.375rem;
--radius-lg: 0.5rem; --radius-lg: 0.5rem;
@@ -5231,9 +5227,6 @@
.m-1 { .m-1 {
margin: calc(var(--spacing) * 1); margin: calc(var(--spacing) * 1);
} }
.m-4 {
margin: calc(var(--spacing) * 4);
}
.m-6 { .m-6 {
margin: calc(var(--spacing) * 6); margin: calc(var(--spacing) * 6);
} }
@@ -5282,9 +5275,6 @@
} }
} }
} }
.mx-2 {
margin-inline: calc(var(--spacing) * 2);
}
.mx-auto { .mx-auto {
margin-inline: auto; margin-inline: auto;
} }
@@ -5377,21 +5367,12 @@
.-my-2 { .-my-2 {
margin-block: calc(var(--spacing) * -2); margin-block: calc(var(--spacing) * -2);
} }
.-my-4 {
margin-block: calc(var(--spacing) * -4);
}
.my-1 {
margin-block: calc(var(--spacing) * 1);
}
.my-1\.5 { .my-1\.5 {
margin-block: calc(var(--spacing) * 1.5); margin-block: calc(var(--spacing) * 1.5);
} }
.my-6 { .my-6 {
margin-block: calc(var(--spacing) * 6); margin-block: calc(var(--spacing) * 6);
} }
.my-auto {
margin-block: auto;
}
.label { .label {
@layer daisyui.l1.l2.l3 { @layer daisyui.l1.l2.l3 {
display: inline-flex; display: inline-flex;
@@ -5649,12 +5630,6 @@
.-mt-2 { .-mt-2 {
margin-top: calc(var(--spacing) * -2); margin-top: calc(var(--spacing) * -2);
} }
.mt-1 {
margin-top: calc(var(--spacing) * 1);
}
.mt-2 {
margin-top: calc(var(--spacing) * 2);
}
.mt-4 { .mt-4 {
margin-top: calc(var(--spacing) * 4); margin-top: calc(var(--spacing) * 4);
} }
@@ -6607,12 +6582,6 @@
.w-full { .w-full {
width: 100%; width: 100%;
} }
.max-w-1 {
max-width: calc(var(--spacing) * 1);
}
.max-w-1\/3 {
max-width: calc(1/3 * 100%);
}
.flex-1 { .flex-1 {
flex: 1; flex: 1;
} }
@@ -6818,9 +6787,6 @@
.flex-col { .flex-col {
flex-direction: column; flex-direction: column;
} }
.flex-row {
flex-direction: row;
}
.flex-wrap { .flex-wrap {
flex-wrap: wrap; flex-wrap: wrap;
} }
@@ -6867,13 +6833,6 @@
margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse))); margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)));
} }
} }
.space-y-2 {
:where(& > :not(:last-child)) {
--tw-space-y-reverse: 0;
margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));
margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)));
}
}
.space-y-4 { .space-y-4 {
:where(& > :not(:last-child)) { :where(& > :not(:last-child)) {
--tw-space-y-reverse: 0; --tw-space-y-reverse: 0;
@@ -6888,9 +6847,6 @@
margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse))); margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));
} }
} }
.gap-x-4 {
column-gap: calc(var(--spacing) * 4);
}
.space-x-2 { .space-x-2 {
:where(& > :not(:last-child)) { :where(& > :not(:last-child)) {
--tw-space-x-reverse: 0; --tw-space-x-reverse: 0;
@@ -6912,9 +6868,6 @@
margin-inline-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-x-reverse))); margin-inline-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-x-reverse)));
} }
} }
.gap-y-6 {
row-gap: calc(var(--spacing) * 6);
}
.overflow-x-auto { .overflow-x-auto {
overflow-x: auto; overflow-x: auto;
} }
@@ -7313,21 +7266,12 @@
border-color: currentColor; border-color: currentColor;
} }
} }
.border-base-300 {
border-color: var(--color-base-300);
}
.border-error { .border-error {
border-color: var(--color-error); border-color: var(--color-error);
} }
.border-gray-200 { .border-gray-200 {
border-color: var(--color-gray-200); border-color: var(--color-gray-200);
} }
.border-primary {
border-color: var(--color-primary);
}
.border-secondary {
border-color: var(--color-secondary);
}
.menu-active { .menu-active {
:where(:not(ul, details, .menu-title, .btn))& { :where(:not(ul, details, .menu-title, .btn))& {
@layer daisyui.l1.l2 { @layer daisyui.l1.l2 {
@@ -7896,30 +7840,18 @@
} }
} }
} }
.px-2 {
padding-inline: calc(var(--spacing) * 2);
}
.px-3 { .px-3 {
padding-inline: calc(var(--spacing) * 3); padding-inline: calc(var(--spacing) * 3);
} }
.px-4 { .px-4 {
padding-inline: calc(var(--spacing) * 4); padding-inline: calc(var(--spacing) * 4);
} }
.py-1 {
padding-block: calc(var(--spacing) * 1);
}
.py-1\.5 { .py-1\.5 {
padding-block: calc(var(--spacing) * 1.5); padding-block: calc(var(--spacing) * 1.5);
} }
.py-2 { .py-2 {
padding-block: calc(var(--spacing) * 2); padding-block: calc(var(--spacing) * 2);
} }
.py-4 {
padding-block: calc(var(--spacing) * 4);
}
.py-6 {
padding-block: calc(var(--spacing) * 6);
}
.ps-2 { .ps-2 {
padding-inline-start: calc(var(--spacing) * 2); padding-inline-start: calc(var(--spacing) * 2);
} }
@@ -7937,9 +7869,6 @@
.pe-2 { .pe-2 {
padding-inline-end: calc(var(--spacing) * 2); padding-inline-end: calc(var(--spacing) * 2);
} }
.pt-4 {
padding-top: calc(var(--spacing) * 4);
}
.pt-6 { .pt-6 {
padding-top: calc(var(--spacing) * 6); padding-top: calc(var(--spacing) * 6);
} }
@@ -7997,14 +7926,6 @@
font-size: var(--text-3xl); font-size: var(--text-3xl);
line-height: var(--tw-leading, var(--text-3xl--line-height)); line-height: var(--tw-leading, var(--text-3xl--line-height));
} }
.text-4xl {
font-size: var(--text-4xl);
line-height: var(--tw-leading, var(--text-4xl--line-height));
}
.text-base {
font-size: var(--text-base);
line-height: var(--tw-leading, var(--text-base--line-height));
}
.text-lg { .text-lg {
font-size: var(--text-lg); font-size: var(--text-lg);
line-height: var(--tw-leading, var(--text-lg--line-height)); line-height: var(--tw-leading, var(--text-lg--line-height));
@@ -8571,12 +8492,6 @@
color: var(--color-warning); color: var(--color-warning);
} }
} }
.text-base-100 {
color: var(--color-base-100);
}
.text-base-300 {
color: var(--color-base-300);
}
.text-base-content { .text-base-content {
color: var(--color-base-content); color: var(--color-base-content);
} }
@@ -8592,21 +8507,9 @@
.text-info { .text-info {
color: var(--color-info); color: var(--color-info);
} }
.text-neutral {
color: var(--color-neutral);
}
.text-neutral-content {
color: var(--color-neutral-content);
}
.text-primary { .text-primary {
color: var(--color-primary); color: var(--color-primary);
} }
.text-secondary {
color: var(--color-secondary);
}
.text-secondary-content {
color: var(--color-secondary-content);
}
.text-slate-900 { .text-slate-900 {
color: var(--color-slate-900); color: var(--color-slate-900);
} }

View File

@@ -19,7 +19,7 @@ public struct ModalForm<T: HTML>: HTML, Sendable where T: Sendable {
self.inner = inner() self.inner = inner()
} }
public var body: some HTML { public var body: some HTML<HTMLTag.dialog> {
dialog(.id(id), .class("modal")) { dialog(.id(id), .class("modal")) {
div(.class("modal-box")) { div(.class("modal-box")) {
if closeButton { if closeButton {

View File

@@ -546,7 +546,7 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute {
.filter({ $0.roomID == room.id }) .filter({ $0.roomID == room.id })
.first! .first!
} onSuccess: { container in } onSuccess: { container in
DuctSizingView.RoomRow(projectID: projectID, room: container) DuctSizingView.RoomRow(room: container)
} }
case .roomRectangularForm(let roomID, let form): case .roomRectangularForm(let roomID, let form):
@@ -564,7 +564,7 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute {
.filter({ $0.roomID == room.id }) .filter({ $0.roomID == room.id })
.first! .first!
} onSuccess: { container in } onSuccess: { container in
DuctSizingView.RoomRow(projectID: projectID, room: container) DuctSizingView.RoomRow(room: container)
} }
case .trunk(let route): case .trunk(let route):

View File

@@ -28,150 +28,33 @@ struct DuctSizingView: HTML, Sendable {
"Must complete all the previous sections to display duct sizing calculations." "Must complete all the previous sections to display duct sizing calculations."
} }
} else { } else {
RoomsTable(projectID: projectID, rooms: rooms) RoomsTable(rooms: rooms)
} }
Row { // Row {
h2(.class("text-2xl font-bold")) { "Trunk Sizes" } // h2(.class("text-2xl font-bold")) { "Trunk Sizes" }
//
PlusButton() // PlusButton()
.attributes( // .attributes(
.class("me-6"), // .class("me-6"),
.showModal(id: TrunkSizeForm.id()) // .showModal(id: TrunkSizeForm.id())
) // )
} // }
.attributes(.class("mt-6")) // .attributes(.class("mt-6"))
//
div(.class("divider -mt-2")) {} // div(.class("divider -mt-2")) {}
//
if supplyTrunks.count > 0 { // if supplyTrunks.count > 0 {
h2(.class("text-lg font-bold text-info")) { "Supply Trunks" } // h2(.class("text-lg font-bold text-info")) { "Supply Trunks" }
TrunkTable(trunks: supplyTrunks, rooms: rooms) // TrunkTable(trunks: supplyTrunks, rooms: rooms)
} // }
//
if returnTrunks.count > 0 { // if returnTrunks.count > 0 {
h2(.class("text-lg font-bold text-error")) { "Return Trunks" } // h2(.class("text-lg font-bold text-error")) { "Return Trunks" }
TrunkTable(trunks: returnTrunks, rooms: rooms) // TrunkTable(trunks: returnTrunks, rooms: rooms)
} // }
//
TrunkSizeForm(rooms: rooms, dismiss: true) // TrunkSizeForm(rooms: rooms, dismiss: true)
}
}
struct RoomsTable: HTML, Sendable {
let projectID: Project.ID
let rooms: [DuctSizing.RoomContainer]
var body: some HTML<HTMLTag.div> {
div(.class("overflow-x-auto")) {
table(.class("table table-zebra")) {
thead {
tr(.class("text-xl text-gray-400 font-bold")) {
th { "ID" }
th { "Name" }
th { "H-BTU" }
th { "C-BTU" }
th(.class("hidden 2xl:table-cell")) { "Htg CFM" }
th(.class("hidden 2xl:table-cell")) { "Clg CFM" }
th { "Dsn CFM" }
th(.class("hidden 2xl:table-cell")) { "Round Size" }
th { "Velocity" }
th { "Final Size" }
th { "Flex Size" }
th { "Width" }
th { "Height" }
}
}
tbody {
for room in rooms {
RoomRow(projectID: projectID, room: room)
}
}
}
}
}
}
struct RoomRow: HTML, Sendable {
let projectID: Project.ID
let room: DuctSizing.RoomContainer
var route: String {
SiteRoute.View.router.path(
for: .project(.detail(projectID, .ductSizing(.index)))
)
.appendingPath("room")
.appendingPath(room.roomID)
}
var body: some HTML<HTMLTag.tr> {
tr(.class("text-lg items-baseline"), .id(room.roomID.idString)) {
td { room.registerID }
td { room.roomName }
td { Number(room.heatingLoad, digits: 0) }
td { Number(room.coolingLoad, digits: 0) }
td(.class("hidden 2xl:table-cell")) { Number(room.heatingCFM, digits: 0) }
td(.class("hidden 2xl:table-cell")) { Number(room.coolingCFM, digits: 0) }
td {
Badge(number: room.designCFM.value, digits: 0)
.attributes(.class("badge-\(room.designCFM.color)"))
}
td(.class("hidden 2xl:table-cell")) { Number(room.roundSize, digits: 1) }
td { Number(room.velocity) }
td {
Badge(number: room.finalSize)
.attributes(.class("badge-secondary"))
}
td {
Badge(number: room.flexSize)
.attributes(.class("badge-primary"))
}
td {
if let width = room.rectangularWidth {
Number(width)
}
}
td {
div(.class("flex justify-between items-center space-x-4")) {
div(.id("height_\(room.roomID.idString)"), .class("h-full my-auto")) {
if let height = room.rectangularSize?.height {
Number(height)
}
}
div {
div(.class("join")) {
// FIX: Delete rectangular size from room.
TrashButton()
.attributes(.class("join-item btn-ghost"))
.attributes(
.hx.delete(
route: .project(
.detail(
projectID,
.ductSizing(
.deleteRectangularSize(
room.roomID,
room.rectangularSize?.id ?? .init())
)
)
)
),
.hx.target("closest tr"),
.hx.swap(.outerHTML),
when: room.rectangularSize != nil
)
EditButton()
.attributes(
.class("join-item btn-ghost"),
.showModal(id: RectangularSizeForm.id(room))
)
}
}
}
RectangularSizeForm(projectID: projectID, room: room)
}
}
} }
} }

View File

@@ -6,7 +6,7 @@ import Styleguide
struct RectangularSizeForm: HTML, Sendable { struct RectangularSizeForm: HTML, Sendable {
static func id(_ roomID: Room.ID? = nil) -> String { static func id(_ roomID: Room.ID? = nil) -> String {
let base = "rectangularSizeForm" let base = "rectangularSize"
guard let roomID else { return base } guard let roomID else { return base }
return "\(base)_\(roomID.idString)" return "\(base)_\(roomID.idString)"
} }
@@ -15,7 +15,9 @@ struct RectangularSizeForm: HTML, Sendable {
return id(room.roomID) return id(room.roomID)
} }
let projectID: Project.ID @Environment(ProjectViewValue.$projectID) var projectID
let id: String
let roomID: Room.ID let roomID: Room.ID
let rectangularSizeID: DuctSizing.RectangularDuct.ID? let rectangularSizeID: DuctSizing.RectangularDuct.ID?
let register: Int let register: Int
@@ -23,14 +25,14 @@ struct RectangularSizeForm: HTML, Sendable {
let dismiss: Bool let dismiss: Bool
init( init(
projectID: Project.ID, id: String? = nil,
roomID: Room.ID, roomID: Room.ID,
rectangularSizeID: DuctSizing.RectangularDuct.ID? = nil, rectangularSizeID: DuctSizing.RectangularDuct.ID? = nil,
register: Int, register: Int,
height: Int? = nil, height: Int? = nil,
dismiss: Bool = true dismiss: Bool = true
) { ) {
self.projectID = projectID self.id = id ?? Self.id(roomID)
self.roomID = roomID self.roomID = roomID
self.rectangularSizeID = rectangularSizeID self.rectangularSizeID = rectangularSizeID
self.register = register self.register = register
@@ -39,7 +41,7 @@ struct RectangularSizeForm: HTML, Sendable {
} }
init( init(
projectID: Project.ID, id: String? = nil,
room: DuctSizing.RoomContainer, room: DuctSizing.RoomContainer,
dismiss: Bool = true dismiss: Bool = true
) { ) {
@@ -48,7 +50,7 @@ struct RectangularSizeForm: HTML, Sendable {
?? (Int("\(room.roomName.last!)") ?? 1) ?? (Int("\(room.roomName.last!)") ?? 1)
self.init( self.init(
projectID: projectID, id: id,
roomID: room.roomID, roomID: room.roomID,
rectangularSizeID: room.rectangularSize?.id, rectangularSizeID: room.rectangularSize?.id,
register: register, register: register,
@@ -66,8 +68,8 @@ struct RectangularSizeForm: HTML, Sendable {
} }
var body: some HTML { var body: some HTML<HTMLTag.dialog> {
ModalForm(id: Self.id(roomID), dismiss: dismiss) { ModalForm(id: id, dismiss: dismiss) {
h1(.class("text-lg pb-6")) { "Rectangular Size" } h1(.class("text-lg pb-6")) { "Rectangular Size" }

View File

@@ -0,0 +1,158 @@
import Elementary
import ElementaryHTMX
import Foundation
import ManualDCore
import Styleguide
extension DuctSizingView {
struct RoomsTable: HTML, Sendable {
@Environment(ProjectViewValue.$projectID) var projectID
let rooms: [DuctSizing.RoomContainer]
var body: some HTML<HTMLTag.div> {
div(.class("overflow-x-auto")) {
table(.class("table table-zebra")) {
thead {
tr(.class("text-xl text-gray-400 font-bold")) {
th { "ID" }
th { "Name" }
th { "BTU" }
th { "CFM" }
th(.class("hidden 2xl:table-cell")) { "Round Size" }
th { "Velocity" }
th { "Size" }
th {}
}
}
tbody {
for room in rooms {
RoomRow(room: room)
}
}
}
}
}
}
struct RoomRow: HTML, Sendable {
@Environment(ProjectViewValue.$projectID) var projectID
let room: DuctSizing.RoomContainer
let formID = UUID().idString
var deleteRoute: String {
guard let id = room.rectangularSize?.id else { return "" }
return SiteRoute.View.router.path(
for: .project(
.detail(
projectID,
.ductSizing(.deleteRectangularSize(room.roomID, id))
)
)
)
}
var body: some HTML<HTMLTag.tr> {
tr(.class("text-lg items-baseline"), .id(room.roomID.idString)) {
td { room.registerID }
td { room.roomName }
td {
div(.class("grid grid-cols-2 gap-2")) {
span(.class("label")) { "Heating" }
Number(room.heatingLoad, digits: 0)
span(.class("label")) { "Cooling" }
Number(room.coolingLoad, digits: 0)
}
}
td {
div(.class("grid grid-cols-2 gap-2")) {
span(.class("label")) { "Design" }
Badge(number: room.designCFM.value, digits: 0)
span(.class("label")) { "Heating" }
Number(room.heatingCFM, digits: 0)
span(.class("label")) { "Cooling" }
Number(room.coolingCFM, digits: 0)
}
}
td(.class("hidden 2xl:table-cell")) { Number(room.roundSize, digits: 1) }
td { Number(room.velocity) }
td {
div(.class("grid grid-cols-2 gap-2")) {
span(.class("label")) { "Final" }
Badge(number: room.finalSize)
.attributes(.class("badge-secondary"))
span(.class("label")) { "Flex" }
Badge(number: room.flexSize)
.attributes(.class("badge-primary"))
if let width = room.rectangularWidth,
let height = room.rectangularSize?.height
{
span(.class("label")) { "Rectangular" }
Badge {
span { "\(width) x \(height)" }
}
}
}
}
td {
div(.class("flex justify-end space-x-4")) {
div(.class("join")) {
if room.rectangularSize != nil {
// FIX: Delete rectangular size from room.
TrashButton()
.attributes(.class("join-item btn-ghost"))
.attributes(
.hx.delete(deleteRoute),
.hx.target("closest tr"),
.hx.swap(.outerHTML),
when: room.rectangularSize != nil
)
}
EditButton()
.attributes(
.class("join-item btn-ghost"),
.showModal(id: formID)
// .showModal(id: RectangularSizeForm.id(room))
)
}
}
// FakeForm(id: formID)
RectangularSizeForm(id: formID, room: room)
// .attributes(.class("modal-open"))
}
}
}
}
struct FakeForm: HTML, Sendable {
let id: String
var body: some HTML<HTMLTag.dialog> {
ModalForm(id: id, dismiss: true) {
div { "Fake Form" }
}
}
}
}