feat: Uses shared duct size container for both room and trunk duct sizing containers.

This commit is contained in:
2026-01-16 10:16:31 -05:00
parent 65fc8565b6
commit 59c1c9ec4a
4 changed files with 102 additions and 43 deletions

View File

@@ -23,6 +23,7 @@ public enum DuctSizing {
public struct SizeContainer: Codable, Equatable, Sendable { public struct SizeContainer: Codable, Equatable, Sendable {
public let rectangularID: RectangularDuct.ID?
public let designCFM: DesignCFM public let designCFM: DesignCFM
public let roundSize: Double public let roundSize: Double
public let finalSize: Int public let finalSize: Int
@@ -32,6 +33,7 @@ public enum DuctSizing {
public let width: Int? public let width: Int?
public init( public init(
rectangularID: RectangularDuct.ID? = nil,
designCFM: DuctSizing.DesignCFM, designCFM: DuctSizing.DesignCFM,
roundSize: Double, roundSize: Double,
finalSize: Int, finalSize: Int,
@@ -40,6 +42,7 @@ public enum DuctSizing {
height: Int? = nil, height: Int? = nil,
width: Int? = nil width: Int? = nil
) { ) {
self.rectangularID = rectangularID
self.designCFM = designCFM self.designCFM = designCFM
self.roundSize = roundSize self.roundSize = roundSize
self.finalSize = finalSize self.finalSize = finalSize
@@ -52,6 +55,7 @@ public enum DuctSizing {
// TODO: Uses SizeContainer // TODO: Uses SizeContainer
@dynamicMemberLookup
public struct RoomContainer: Codable, Equatable, Sendable { public struct RoomContainer: Codable, Equatable, Sendable {
public let roomID: Room.ID public let roomID: Room.ID
@@ -61,13 +65,7 @@ public enum DuctSizing {
public let coolingLoad: Double public let coolingLoad: Double
public let heatingCFM: Double public let heatingCFM: Double
public let coolingCFM: Double public let coolingCFM: Double
public let designCFM: DesignCFM public let ductSize: SizeContainer
public let roundSize: Double
public let finalSize: Int
public let velocity: Int
public let flexSize: Int
public let rectangularSize: RectangularDuct?
public let rectangularWidth: Int?
public init( public init(
roomID: Room.ID, roomID: Room.ID,
@@ -77,13 +75,7 @@ public enum DuctSizing {
coolingLoad: Double, coolingLoad: Double,
heatingCFM: Double, heatingCFM: Double,
coolingCFM: Double, coolingCFM: Double,
designCFM: DesignCFM, ductSize: SizeContainer
roundSize: Double,
finalSize: Int,
velocity: Int,
flexSize: Int,
rectangularSize: RectangularDuct? = nil,
rectangularWidth: Int? = nil
) { ) {
self.roomID = roomID self.roomID = roomID
self.roomName = roomName self.roomName = roomName
@@ -92,13 +84,46 @@ public enum DuctSizing {
self.coolingLoad = coolingLoad self.coolingLoad = coolingLoad
self.heatingCFM = heatingCFM self.heatingCFM = heatingCFM
self.coolingCFM = coolingCFM self.coolingCFM = coolingCFM
self.designCFM = designCFM self.ductSize = ductSize
self.roundSize = roundSize }
self.finalSize = finalSize
self.velocity = velocity // public init(
self.flexSize = flexSize // roomID: Room.ID,
self.rectangularSize = rectangularSize // roomName: String,
self.rectangularWidth = rectangularWidth // roomRegister: Int,
// heatingLoad: Double,
// coolingLoad: Double,
// heatingCFM: Double,
// coolingCFM: Double,
// designCFM: DesignCFM,
// roundSize: Double,
// finalSize: Int,
// velocity: Int,
// flexSize: Int,
// rectangularSize: RectangularDuct? = nil,
// rectangularWidth: Int? = nil
// ) {
// self.roomID = roomID
// self.roomName = roomName
// self.roomRegister = roomRegister
// self.heatingLoad = heatingLoad
// self.coolingLoad = coolingLoad
// self.heatingCFM = heatingCFM
// self.coolingCFM = coolingCFM
// self.ductSize = .init(
// rectangularID: rectangularSize?.id,
// designCFM: designCFM,
// roundSize: roundSize,
// finalSize: finalSize,
// velocity: velocity,
// flexSize: flexSize,
// height: rectangularSize?.height,
// width: rectangularWidth
// )
// }
public subscript<T>(dynamicMember keyPath: KeyPath<DuctSizing.SizeContainer, T>) -> T {
ductSize[keyPath: keyPath]
} }
} }

View File

@@ -77,13 +77,12 @@ extension ManualDClient {
coolingLoad: coolingLoad, coolingLoad: coolingLoad,
heatingCFM: heatingCFM, heatingCFM: heatingCFM,
coolingCFM: coolingCFM, coolingCFM: coolingCFM,
ductSize: .init(
designCFM: designCFM, designCFM: designCFM,
roundSize: sizes.ductulatorSize, sizes: sizes,
finalSize: sizes.finalSize,
velocity: sizes.velocity,
flexSize: sizes.flexSize,
rectangularSize: rectangularSize, rectangularSize: rectangularSize,
rectangularWidth: rectangularWidth width: rectangularWidth
)
) )
) )
} }
@@ -127,10 +126,7 @@ extension ManualDClient {
trunk: trunk, trunk: trunk,
ductSize: .init( ductSize: .init(
designCFM: designCFM, designCFM: designCFM,
roundSize: sizes.ductulatorSize, sizes: sizes,
finalSize: sizes.finalSize,
velocity: sizes.velocity,
flexSize: sizes.flexSize,
height: trunk.height, height: trunk.height,
width: width width: width
) )
@@ -143,6 +139,44 @@ extension ManualDClient {
} }
extension DuctSizing.SizeContainer {
init(
designCFM: DuctSizing.DesignCFM,
sizes: ManualDClient.DuctSizeResponse,
height: Int?,
width: Int?
) {
self.init(
rectangularID: nil,
designCFM: designCFM,
roundSize: sizes.ductulatorSize,
finalSize: sizes.finalSize,
velocity: sizes.velocity,
flexSize: sizes.flexSize,
height: height,
width: width
)
}
init(
designCFM: DuctSizing.DesignCFM,
sizes: ManualDClient.DuctSizeResponse,
rectangularSize: DuctSizing.RectangularDuct?,
width: Int?
) {
self.init(
rectangularID: rectangularSize?.id,
designCFM: designCFM,
roundSize: sizes.ductulatorSize,
finalSize: sizes.finalSize,
velocity: sizes.velocity,
flexSize: sizes.flexSize,
height: rectangularSize?.height,
width: width
)
}
}
extension Room { extension Room {
var heatingLoadPerRegister: Double { var heatingLoadPerRegister: Double {

View File

@@ -40,7 +40,7 @@ struct RectangularSizeForm: HTML, Sendable {
} }
var height: Int? { var height: Int? {
room.rectangularSize?.height room.ductSize.height
} }
var body: some HTML<HTMLTag.dialog> { var body: some HTML<HTMLTag.dialog> {
@@ -54,7 +54,7 @@ struct RectangularSizeForm: HTML, Sendable {
.hx.swap(.outerHTML) .hx.swap(.outerHTML)
) { ) {
input(.class("hidden"), .name("register"), .value(room.roomRegister)) input(.class("hidden"), .name("register"), .value(room.roomRegister))
input(.class("hidden"), .name("id"), .value(room.rectangularSize?.id)) input(.class("hidden"), .name("id"), .value(room.ductSize.rectangularID))
LabeledInput( LabeledInput(
"Height", "Height",

View File

@@ -44,7 +44,7 @@ extension DuctSizingView {
let formID = UUID().idString let formID = UUID().idString
var deleteRoute: String { var deleteRoute: String {
guard let id = room.rectangularSize?.id else { return "" } guard let id = room.rectangularID else { return "" }
return SiteRoute.View.router.path( return SiteRoute.View.router.path(
for: .project( for: .project(
@@ -80,7 +80,7 @@ extension DuctSizingView {
span(.class("label")) { "Design" } span(.class("label")) { "Design" }
div(.class("flex justify-center")) { div(.class("flex justify-center")) {
Badge(number: room.designCFM.value, digits: 0) Badge(number: room.ductSize.designCFM.value, digits: 0)
} }
span(.class("label")) { "Heating" } span(.class("label")) { "Heating" }
@@ -103,28 +103,28 @@ extension DuctSizingView {
div(.class("label")) { "Calculated" } div(.class("label")) { "Calculated" }
div(.class("flex justify-center")) { div(.class("flex justify-center")) {
Badge(number: room.roundSize, digits: 2) Badge(number: room.ductSize.roundSize, digits: 2)
} }
div {} div {}
div(.class("label")) { "Final" } div(.class("label")) { "Final" }
div(.class("flex justify-center")) { div(.class("flex justify-center")) {
Badge(number: room.finalSize) Badge(number: room.ductSize.finalSize)
.attributes(.class("badge-secondary")) .attributes(.class("badge-secondary"))
} }
div {} div {}
div(.class("label")) { "Flex" } div(.class("label")) { "Flex" }
div(.class("flex justify-center")) { div(.class("flex justify-center")) {
Badge(number: room.flexSize) Badge(number: room.ductSize.flexSize)
.attributes(.class("badge-primary")) .attributes(.class("badge-primary"))
} }
div {} div {}
div(.class("label")) { "Rectangular" } div(.class("label")) { "Rectangular" }
div(.class("flex justify-center")) { div(.class("flex justify-center")) {
if let width = room.rectangularWidth, if let width = room.ductSize.width,
let height = room.rectangularSize?.height let height = room.ductSize.height
{ {
Badge { Badge {
span { "\(width) x \(height)" } span { "\(width) x \(height)" }
@@ -134,7 +134,7 @@ extension DuctSizingView {
} }
div(.class("flex justify-end")) { div(.class("flex justify-end")) {
div(.class("join")) { div(.class("join")) {
if room.rectangularSize != nil { if room.ductSize.width != nil {
Tooltip("Delete Size", position: .bottom) { Tooltip("Delete Size", position: .bottom) {
TrashButton() TrashButton()
.attributes(.class("join-item btn-ghost")) .attributes(.class("join-item btn-ghost"))
@@ -142,7 +142,7 @@ extension DuctSizingView {
.hx.delete(deleteRoute), .hx.delete(deleteRoute),
.hx.target("#\(rowID)"), .hx.target("#\(rowID)"),
.hx.swap(.outerHTML), .hx.swap(.outerHTML),
when: room.rectangularSize != nil when: room.ductSize.width != nil
) )
} }
} }