Compare commits
3 Commits
65fc8565b6
...
146baa7815
| Author | SHA1 | Date | |
|---|---|---|---|
|
146baa7815
|
|||
|
b5436c2073
|
|||
|
59c1c9ec4a
|
@@ -74,7 +74,7 @@ extension DatabaseClient.Migrations: DependencyKey {
|
|||||||
EquipmentInfo.Migrate(),
|
EquipmentInfo.Migrate(),
|
||||||
Room.Migrate(),
|
Room.Migrate(),
|
||||||
EffectiveLength.Migrate(),
|
EffectiveLength.Migrate(),
|
||||||
DuctSizing.TrunkSize.Migrate(),
|
TrunkSize.Migrate(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,12 +10,11 @@ extension DatabaseClient {
|
|||||||
public var create: @Sendable (Room.Create) async throws -> Room
|
public var create: @Sendable (Room.Create) async throws -> Room
|
||||||
public var delete: @Sendable (Room.ID) async throws -> Void
|
public var delete: @Sendable (Room.ID) async throws -> Void
|
||||||
public var deleteRectangularSize:
|
public var deleteRectangularSize:
|
||||||
@Sendable (Room.ID, DuctSizing.RectangularDuct.ID) async throws -> Room
|
@Sendable (Room.ID, Room.RectangularSize.ID) async throws -> Room
|
||||||
public var get: @Sendable (Room.ID) async throws -> Room?
|
public var get: @Sendable (Room.ID) async throws -> Room?
|
||||||
public var fetch: @Sendable (Project.ID) async throws -> [Room]
|
public var fetch: @Sendable (Project.ID) async throws -> [Room]
|
||||||
public var update: @Sendable (Room.ID, Room.Update) async throws -> Room
|
public var update: @Sendable (Room.ID, Room.Update) async throws -> Room
|
||||||
public var updateRectangularSize:
|
public var updateRectangularSize: @Sendable (Room.ID, Room.RectangularSize) async throws -> Room
|
||||||
@Sendable (Room.ID, DuctSizing.RectangularDuct) async throws -> Room
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +203,7 @@ final class RoomModel: Model, @unchecked Sendable {
|
|||||||
var registerCount: Int
|
var registerCount: Int
|
||||||
|
|
||||||
@Field(key: "rectangularSizes")
|
@Field(key: "rectangularSizes")
|
||||||
var rectangularSizes: [DuctSizing.RectangularDuct]?
|
var rectangularSizes: [Room.RectangularSize]?
|
||||||
|
|
||||||
@Timestamp(key: "createdAt", on: .create, format: .iso8601)
|
@Timestamp(key: "createdAt", on: .create, format: .iso8601)
|
||||||
var createdAt: Date?
|
var createdAt: Date?
|
||||||
@@ -224,7 +223,7 @@ final class RoomModel: Model, @unchecked Sendable {
|
|||||||
coolingTotal: Double,
|
coolingTotal: Double,
|
||||||
coolingSensible: Double? = nil,
|
coolingSensible: Double? = nil,
|
||||||
registerCount: Int,
|
registerCount: Int,
|
||||||
rectangularSizes: [DuctSizing.RectangularDuct]? = nil,
|
rectangularSizes: [Room.RectangularSize]? = nil,
|
||||||
createdAt: Date? = nil,
|
createdAt: Date? = nil,
|
||||||
updatedAt: Date? = nil,
|
updatedAt: Date? = nil,
|
||||||
projectID: Project.ID
|
projectID: Project.ID
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import ManualDCore
|
|||||||
extension DatabaseClient {
|
extension DatabaseClient {
|
||||||
@DependencyClient
|
@DependencyClient
|
||||||
public struct TrunkSizes: Sendable {
|
public struct TrunkSizes: Sendable {
|
||||||
public var create: @Sendable (DuctSizing.TrunkSize.Create) async throws -> DuctSizing.TrunkSize
|
public var create: @Sendable (TrunkSize.Create) async throws -> TrunkSize
|
||||||
public var delete: @Sendable (DuctSizing.TrunkSize.ID) async throws -> Void
|
public var delete: @Sendable (TrunkSize.ID) async throws -> Void
|
||||||
public var fetch: @Sendable (Project.ID) async throws -> [DuctSizing.TrunkSize]
|
public var fetch: @Sendable (Project.ID) async throws -> [TrunkSize]
|
||||||
public var get: @Sendable (DuctSizing.TrunkSize.ID) async throws -> DuctSizing.TrunkSize?
|
public var get: @Sendable (TrunkSize.ID) async throws -> TrunkSize?
|
||||||
public var update:
|
public var update:
|
||||||
@Sendable (DuctSizing.TrunkSize.ID, DuctSizing.TrunkSize.Update) async throws ->
|
@Sendable (TrunkSize.ID, TrunkSize.Update) async throws ->
|
||||||
DuctSizing.TrunkSize
|
TrunkSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ extension DatabaseClient.TrunkSizes: TestDependencyKey {
|
|||||||
try request.validate()
|
try request.validate()
|
||||||
|
|
||||||
let trunk = request.toModel()
|
let trunk = request.toModel()
|
||||||
var roomProxies = [DuctSizing.TrunkSize.RoomProxy]()
|
var roomProxies = [TrunkSize.RoomProxy]()
|
||||||
|
|
||||||
try await trunk.save(on: database)
|
try await trunk.save(on: database)
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ extension DatabaseClient.TrunkSizes: TestDependencyKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize.Create {
|
extension TrunkSize.Create {
|
||||||
|
|
||||||
func validate() throws(ValidationError) {
|
func validate() throws(ValidationError) {
|
||||||
guard rooms.count > 0 else {
|
guard rooms.count > 0 else {
|
||||||
@@ -113,7 +113,7 @@ extension DuctSizing.TrunkSize.Create {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize.Update {
|
extension TrunkSize.Update {
|
||||||
func validate() throws(ValidationError) {
|
func validate() throws(ValidationError) {
|
||||||
if let rooms {
|
if let rooms {
|
||||||
guard rooms.count > 0 else {
|
guard rooms.count > 0 else {
|
||||||
@@ -128,7 +128,7 @@ extension DuctSizing.TrunkSize.Update {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize {
|
extension TrunkSize {
|
||||||
|
|
||||||
struct Migrate: AsyncMigration {
|
struct Migrate: AsyncMigration {
|
||||||
let name = "CreateTrunkSize"
|
let name = "CreateTrunkSize"
|
||||||
@@ -192,7 +192,7 @@ final class TrunkRoomModel: Model, @unchecked Sendable {
|
|||||||
trunkID: TrunkModel.IDValue,
|
trunkID: TrunkModel.IDValue,
|
||||||
roomID: RoomModel.IDValue,
|
roomID: RoomModel.IDValue,
|
||||||
registers: [Int],
|
registers: [Int],
|
||||||
type: DuctSizing.TrunkSize.TrunkType
|
type: TrunkSize.TrunkType
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
$trunk.id = trunkID
|
$trunk.id = trunkID
|
||||||
@@ -201,7 +201,7 @@ final class TrunkRoomModel: Model, @unchecked Sendable {
|
|||||||
self.type = type.rawValue
|
self.type = type.rawValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func toDTO(on database: any Database) async throws -> DuctSizing.TrunkSize.RoomProxy {
|
func toDTO(on database: any Database) async throws -> TrunkSize.RoomProxy {
|
||||||
guard let room = try await RoomModel.find($room.id, on: database) else {
|
guard let room = try await RoomModel.find($room.id, on: database) else {
|
||||||
throw NotFoundError()
|
throw NotFoundError()
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ final class TrunkModel: Model, @unchecked Sendable {
|
|||||||
init(
|
init(
|
||||||
id: UUID? = nil,
|
id: UUID? = nil,
|
||||||
projectID: Project.ID,
|
projectID: Project.ID,
|
||||||
type: DuctSizing.TrunkSize.TrunkType,
|
type: TrunkSize.TrunkType,
|
||||||
height: Int? = nil,
|
height: Int? = nil,
|
||||||
name: String? = nil
|
name: String? = nil
|
||||||
) {
|
) {
|
||||||
@@ -251,15 +251,15 @@ final class TrunkModel: Model, @unchecked Sendable {
|
|||||||
self.name = name
|
self.name = name
|
||||||
}
|
}
|
||||||
|
|
||||||
func toDTO(on database: any Database) async throws -> DuctSizing.TrunkSize {
|
func toDTO(on database: any Database) async throws -> TrunkSize {
|
||||||
let rooms = try await withThrowingTaskGroup(of: DuctSizing.TrunkSize.RoomProxy.self) { group in
|
let rooms = try await withThrowingTaskGroup(of: TrunkSize.RoomProxy.self) { group in
|
||||||
for room in self.rooms {
|
for room in self.rooms {
|
||||||
group.addTask {
|
group.addTask {
|
||||||
try await room.toDTO(on: database)
|
try await room.toDTO(on: database)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return try await group.reduce(into: [DuctSizing.TrunkSize.RoomProxy]()) {
|
return try await group.reduce(into: [TrunkSize.RoomProxy]()) {
|
||||||
$0.append($1)
|
$0.append($1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ final class TrunkModel: Model, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func applyUpdates(
|
func applyUpdates(
|
||||||
_ updates: DuctSizing.TrunkSize.Update,
|
_ updates: TrunkSize.Update,
|
||||||
on database: any Database
|
on database: any Database
|
||||||
) async throws {
|
) async throws {
|
||||||
if let type = updates.type, type.rawValue != self.type {
|
if let type = updates.type, type.rawValue != self.type {
|
||||||
@@ -340,15 +340,15 @@ final class TrunkModel: Model, @unchecked Sendable {
|
|||||||
|
|
||||||
extension Array where Element == TrunkModel {
|
extension Array where Element == TrunkModel {
|
||||||
|
|
||||||
func toDTO(on database: any Database) async throws -> [DuctSizing.TrunkSize] {
|
func toDTO(on database: any Database) async throws -> [TrunkSize] {
|
||||||
try await withThrowingTaskGroup(of: DuctSizing.TrunkSize.self) { group in
|
try await withThrowingTaskGroup(of: TrunkSize.self) { group in
|
||||||
for model in self {
|
for model in self {
|
||||||
group.addTask {
|
group.addTask {
|
||||||
try await model.toDTO(on: database)
|
try await model.toDTO(on: database)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return try await group.reduce(into: [DuctSizing.TrunkSize]()) {
|
return try await group.reduce(into: [TrunkSize]()) {
|
||||||
$0.append($1)
|
$0.append($1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ extension Room {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize.RoomProxy {
|
extension TrunkSize.RoomProxy {
|
||||||
|
|
||||||
// We need to make sure if registers got removed after a trunk
|
// We need to make sure if registers got removed after a trunk
|
||||||
// was already made / saved that we do not include registers that
|
// was already made / saved that we do not include registers that
|
||||||
@@ -35,7 +35,7 @@ extension DuctSizing.TrunkSize.RoomProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize {
|
extension TrunkSize {
|
||||||
|
|
||||||
var totalHeatingLoad: Double {
|
var totalHeatingLoad: Double {
|
||||||
rooms.reduce(into: 0) { $0 += $1.totalHeatingLoad }
|
rooms.reduce(into: 0) { $0 += $1.totalHeatingLoad }
|
||||||
|
|||||||
@@ -3,26 +3,9 @@ import Foundation
|
|||||||
|
|
||||||
public enum DuctSizing {
|
public enum DuctSizing {
|
||||||
|
|
||||||
public struct RectangularDuct: Codable, Equatable, Identifiable, Sendable {
|
|
||||||
|
|
||||||
public let id: UUID
|
|
||||||
public let register: Int?
|
|
||||||
public let height: Int
|
|
||||||
|
|
||||||
public init(
|
|
||||||
id: UUID = .init(),
|
|
||||||
register: Int? = nil,
|
|
||||||
height: Int,
|
|
||||||
) {
|
|
||||||
self.id = id
|
|
||||||
self.register = register
|
|
||||||
self.height = height
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SizeContainer: Codable, Equatable, Sendable {
|
public struct SizeContainer: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
public let rectangularID: Room.RectangularSize.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 +15,7 @@ public enum DuctSizing {
|
|||||||
public let width: Int?
|
public let width: Int?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
|
rectangularID: Room.RectangularSize.ID? = nil,
|
||||||
designCFM: DuctSizing.DesignCFM,
|
designCFM: DuctSizing.DesignCFM,
|
||||||
roundSize: Double,
|
roundSize: Double,
|
||||||
finalSize: Int,
|
finalSize: Int,
|
||||||
@@ -40,6 +24,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 +37,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 +47,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 +57,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 +66,11 @@ 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 subscript<T>(dynamicMember keyPath: KeyPath<DuctSizing.SizeContainer, T>) -> T {
|
||||||
self.flexSize = flexSize
|
ductSize[keyPath: keyPath]
|
||||||
self.rectangularSize = rectangularSize
|
|
||||||
self.rectangularWidth = rectangularWidth
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +114,7 @@ extension DuctSizing {
|
|||||||
self.ductSize = ductSize
|
self.ductSize = ductSize
|
||||||
}
|
}
|
||||||
|
|
||||||
public subscript<T>(dynamicMember keyPath: KeyPath<DuctSizing.TrunkSize, T>) -> T {
|
public subscript<T>(dynamicMember keyPath: KeyPath<TrunkSize, T>) -> T {
|
||||||
trunk[keyPath: keyPath]
|
trunk[keyPath: keyPath]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,99 +122,4 @@ extension DuctSizing {
|
|||||||
ductSize[keyPath: keyPath]
|
ductSize[keyPath: keyPath]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add an optional label that the user can set.
|
|
||||||
|
|
||||||
// Represents the database model.
|
|
||||||
public struct TrunkSize: Codable, Equatable, Identifiable, Sendable {
|
|
||||||
|
|
||||||
public let id: UUID
|
|
||||||
public let projectID: Project.ID
|
|
||||||
public let type: TrunkType
|
|
||||||
public let rooms: [RoomProxy]
|
|
||||||
public let height: Int?
|
|
||||||
public let name: String?
|
|
||||||
|
|
||||||
public init(
|
|
||||||
id: UUID,
|
|
||||||
projectID: Project.ID,
|
|
||||||
type: DuctSizing.TrunkSize.TrunkType,
|
|
||||||
rooms: [DuctSizing.TrunkSize.RoomProxy],
|
|
||||||
height: Int? = nil,
|
|
||||||
name: String? = nil
|
|
||||||
) {
|
|
||||||
self.id = id
|
|
||||||
self.projectID = projectID
|
|
||||||
self.type = type
|
|
||||||
self.rooms = rooms
|
|
||||||
self.height = height
|
|
||||||
self.name = name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize {
|
|
||||||
public struct Create: Codable, Equatable, Sendable {
|
|
||||||
|
|
||||||
public let projectID: Project.ID
|
|
||||||
public let type: TrunkType
|
|
||||||
public let rooms: [Room.ID: [Int]]
|
|
||||||
public let height: Int?
|
|
||||||
public let name: String?
|
|
||||||
|
|
||||||
public init(
|
|
||||||
projectID: Project.ID,
|
|
||||||
type: DuctSizing.TrunkSize.TrunkType,
|
|
||||||
rooms: [Room.ID: [Int]],
|
|
||||||
height: Int? = nil,
|
|
||||||
name: String? = nil
|
|
||||||
) {
|
|
||||||
self.projectID = projectID
|
|
||||||
self.type = type
|
|
||||||
self.rooms = rooms
|
|
||||||
self.height = height
|
|
||||||
self.name = name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct Update: Codable, Equatable, Sendable {
|
|
||||||
|
|
||||||
public let type: TrunkType?
|
|
||||||
public let rooms: [Room.ID: [Int]]?
|
|
||||||
public let height: Int?
|
|
||||||
public let name: String?
|
|
||||||
|
|
||||||
public init(
|
|
||||||
type: DuctSizing.TrunkSize.TrunkType? = nil,
|
|
||||||
rooms: [Room.ID: [Int]]? = nil,
|
|
||||||
height: Int? = nil,
|
|
||||||
name: String? = nil
|
|
||||||
) {
|
|
||||||
self.type = type
|
|
||||||
self.rooms = rooms
|
|
||||||
self.height = height
|
|
||||||
self.name = name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make registers non-optional
|
|
||||||
public struct RoomProxy: Codable, Equatable, Identifiable, Sendable {
|
|
||||||
|
|
||||||
public var id: Room.ID { room.id }
|
|
||||||
public let room: Room
|
|
||||||
public let registers: [Int]
|
|
||||||
|
|
||||||
public init(room: Room, registers: [Int]) {
|
|
||||||
self.room = room
|
|
||||||
self.registers = registers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TrunkType: String, CaseIterable, Codable, Equatable, Sendable {
|
|
||||||
case `return`
|
|
||||||
case supply
|
|
||||||
|
|
||||||
public static let allCases = [Self.supply, .return]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public struct Room: Codable, Equatable, Identifiable, Sendable {
|
|||||||
public let coolingTotal: Double
|
public let coolingTotal: Double
|
||||||
public let coolingSensible: Double?
|
public let coolingSensible: Double?
|
||||||
public let registerCount: Int
|
public let registerCount: Int
|
||||||
public let rectangularSizes: [DuctSizing.RectangularDuct]?
|
public let rectangularSizes: [RectangularSize]?
|
||||||
public let createdAt: Date
|
public let createdAt: Date
|
||||||
public let updatedAt: Date
|
public let updatedAt: Date
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ public struct Room: Codable, Equatable, Identifiable, Sendable {
|
|||||||
coolingTotal: Double,
|
coolingTotal: Double,
|
||||||
coolingSensible: Double? = nil,
|
coolingSensible: Double? = nil,
|
||||||
registerCount: Int = 1,
|
registerCount: Int = 1,
|
||||||
rectangularSizes: [DuctSizing.RectangularDuct]? = nil,
|
rectangularSizes: [RectangularSize]? = nil,
|
||||||
createdAt: Date,
|
createdAt: Date,
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
) {
|
) {
|
||||||
@@ -65,13 +65,30 @@ extension Room {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct RectangularSize: Codable, Equatable, Identifiable, Sendable {
|
||||||
|
|
||||||
|
public let id: UUID
|
||||||
|
public let register: Int?
|
||||||
|
public let height: Int
|
||||||
|
|
||||||
|
public init(
|
||||||
|
id: UUID = .init(),
|
||||||
|
register: Int? = nil,
|
||||||
|
height: Int,
|
||||||
|
) {
|
||||||
|
self.id = id
|
||||||
|
self.register = register
|
||||||
|
self.height = height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public struct Update: Codable, Equatable, Sendable {
|
public struct Update: Codable, Equatable, Sendable {
|
||||||
public let name: String?
|
public let name: String?
|
||||||
public let heatingLoad: Double?
|
public let heatingLoad: Double?
|
||||||
public let coolingTotal: Double?
|
public let coolingTotal: Double?
|
||||||
public let coolingSensible: Double?
|
public let coolingSensible: Double?
|
||||||
public let registerCount: Int?
|
public let registerCount: Int?
|
||||||
public let rectangularSizes: [DuctSizing.RectangularDuct]?
|
public let rectangularSizes: [RectangularSize]?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
name: String? = nil,
|
name: String? = nil,
|
||||||
@@ -89,7 +106,7 @@ extension Room {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
rectangularSizes: [DuctSizing.RectangularDuct]
|
rectangularSizes: [RectangularSize]
|
||||||
) {
|
) {
|
||||||
self.name = nil
|
self.name = nil
|
||||||
self.heatingLoad = nil
|
self.heatingLoad = nil
|
||||||
|
|||||||
@@ -627,7 +627,7 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
}
|
}
|
||||||
Method.delete
|
Method.delete
|
||||||
Query {
|
Query {
|
||||||
Field("rectangularSize") { DuctSizing.RectangularDuct.ID.parser() }
|
Field("rectangularSize") { Room.RectangularSize.ID.parser() }
|
||||||
Field("register") { Int.parser() }
|
Field("register") { Int.parser() }
|
||||||
}
|
}
|
||||||
.map(.memberwise(DeleteRectangularDuct.init))
|
.map(.memberwise(DeleteRectangularDuct.init))
|
||||||
@@ -642,7 +642,7 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Body {
|
Body {
|
||||||
FormData {
|
FormData {
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("id") { DuctSizing.RectangularDuct.ID.parser() }
|
Field("id") { Room.RectangularSize.ID.parser() }
|
||||||
}
|
}
|
||||||
Field("register") { Int.parser() }
|
Field("register") { Int.parser() }
|
||||||
Field("height") { Int.parser() }
|
Field("height") { Int.parser() }
|
||||||
@@ -658,19 +658,19 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
|
|
||||||
public struct DeleteRectangularDuct: Equatable, Sendable {
|
public struct DeleteRectangularDuct: Equatable, Sendable {
|
||||||
|
|
||||||
public let rectangularSizeID: DuctSizing.RectangularDuct.ID
|
public let rectangularSizeID: Room.RectangularSize.ID
|
||||||
public let register: Int
|
public let register: Int
|
||||||
|
|
||||||
public init(rectangularSizeID: DuctSizing.RectangularDuct.ID, register: Int) {
|
public init(rectangularSizeID: Room.RectangularSize.ID, register: Int) {
|
||||||
self.rectangularSizeID = rectangularSizeID
|
self.rectangularSizeID = rectangularSizeID
|
||||||
self.register = register
|
self.register = register
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum TrunkRoute: Equatable, Sendable {
|
public enum TrunkRoute: Equatable, Sendable {
|
||||||
case delete(DuctSizing.TrunkSize.ID)
|
case delete(TrunkSize.ID)
|
||||||
case submit(TrunkSizeForm)
|
case submit(TrunkSizeForm)
|
||||||
case update(DuctSizing.TrunkSize.ID, TrunkSizeForm)
|
case update(TrunkSize.ID, TrunkSizeForm)
|
||||||
|
|
||||||
public static let rootPath = "trunk"
|
public static let rootPath = "trunk"
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Route(.case(Self.delete)) {
|
Route(.case(Self.delete)) {
|
||||||
Path {
|
Path {
|
||||||
rootPath
|
rootPath
|
||||||
DuctSizing.TrunkSize.ID.parser()
|
TrunkSize.ID.parser()
|
||||||
}
|
}
|
||||||
Method.delete
|
Method.delete
|
||||||
}
|
}
|
||||||
@@ -690,7 +690,7 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Body {
|
Body {
|
||||||
FormData {
|
FormData {
|
||||||
Field("projectID") { Project.ID.parser() }
|
Field("projectID") { Project.ID.parser() }
|
||||||
Field("type") { DuctSizing.TrunkSize.TrunkType.parser() }
|
Field("type") { TrunkSize.TrunkType.parser() }
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("height") { Int.parser() }
|
Field("height") { Int.parser() }
|
||||||
|
|
||||||
@@ -708,13 +708,13 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Route(.case(Self.update)) {
|
Route(.case(Self.update)) {
|
||||||
Path {
|
Path {
|
||||||
rootPath
|
rootPath
|
||||||
DuctSizing.TrunkSize.ID.parser()
|
TrunkSize.ID.parser()
|
||||||
}
|
}
|
||||||
Method.patch
|
Method.patch
|
||||||
Body {
|
Body {
|
||||||
FormData {
|
FormData {
|
||||||
Field("projectID") { Project.ID.parser() }
|
Field("projectID") { Project.ID.parser() }
|
||||||
Field("type") { DuctSizing.TrunkSize.TrunkType.parser() }
|
Field("type") { TrunkSize.TrunkType.parser() }
|
||||||
Optionally {
|
Optionally {
|
||||||
Field("height") { Int.parser() }
|
Field("height") { Int.parser() }
|
||||||
}
|
}
|
||||||
@@ -732,17 +732,43 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct RoomRectangularForm: Equatable, Sendable {
|
public struct RoomRectangularForm: Equatable, Sendable {
|
||||||
public let id: DuctSizing.RectangularDuct.ID?
|
|
||||||
|
public let id: Room.RectangularSize.ID?
|
||||||
public let register: Int
|
public let register: Int
|
||||||
public let height: Int
|
public let height: Int
|
||||||
|
|
||||||
|
public init(
|
||||||
|
id: Room.RectangularSize.ID? = nil,
|
||||||
|
register: Int,
|
||||||
|
height: Int
|
||||||
|
) {
|
||||||
|
self.id = id
|
||||||
|
self.register = register
|
||||||
|
self.height = height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct TrunkSizeForm: Equatable, Sendable {
|
public struct TrunkSizeForm: Equatable, Sendable {
|
||||||
|
|
||||||
public let projectID: Project.ID
|
public let projectID: Project.ID
|
||||||
public let type: DuctSizing.TrunkSize.TrunkType
|
public let type: TrunkSize.TrunkType
|
||||||
public let height: Int?
|
public let height: Int?
|
||||||
public let name: String?
|
public let name: String?
|
||||||
public let rooms: [String]
|
public let rooms: [String]
|
||||||
|
|
||||||
|
public init(
|
||||||
|
projectID: Project.ID,
|
||||||
|
type: TrunkSize.TrunkType,
|
||||||
|
height: Int? = nil,
|
||||||
|
name: String? = nil,
|
||||||
|
rooms: [String]
|
||||||
|
) {
|
||||||
|
self.projectID = projectID
|
||||||
|
self.type = type
|
||||||
|
self.height = height
|
||||||
|
self.name = name
|
||||||
|
self.rooms = rooms
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
93
Sources/ManualDCore/TrunkSize.swift
Normal file
93
Sources/ManualDCore/TrunkSize.swift
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
// Represents the database model.
|
||||||
|
public struct TrunkSize: Codable, Equatable, Identifiable, Sendable {
|
||||||
|
|
||||||
|
public let id: UUID
|
||||||
|
public let projectID: Project.ID
|
||||||
|
public let type: TrunkType
|
||||||
|
public let rooms: [RoomProxy]
|
||||||
|
public let height: Int?
|
||||||
|
public let name: String?
|
||||||
|
|
||||||
|
public init(
|
||||||
|
id: UUID,
|
||||||
|
projectID: Project.ID,
|
||||||
|
type: TrunkType,
|
||||||
|
rooms: [RoomProxy],
|
||||||
|
height: Int? = nil,
|
||||||
|
name: String? = nil
|
||||||
|
) {
|
||||||
|
self.id = id
|
||||||
|
self.projectID = projectID
|
||||||
|
self.type = type
|
||||||
|
self.rooms = rooms
|
||||||
|
self.height = height
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TrunkSize {
|
||||||
|
public struct Create: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
public let projectID: Project.ID
|
||||||
|
public let type: TrunkType
|
||||||
|
public let rooms: [Room.ID: [Int]]
|
||||||
|
public let height: Int?
|
||||||
|
public let name: String?
|
||||||
|
|
||||||
|
public init(
|
||||||
|
projectID: Project.ID,
|
||||||
|
type: TrunkType,
|
||||||
|
rooms: [Room.ID: [Int]],
|
||||||
|
height: Int? = nil,
|
||||||
|
name: String? = nil
|
||||||
|
) {
|
||||||
|
self.projectID = projectID
|
||||||
|
self.type = type
|
||||||
|
self.rooms = rooms
|
||||||
|
self.height = height
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Update: Codable, Equatable, Sendable {
|
||||||
|
|
||||||
|
public let type: TrunkType?
|
||||||
|
public let rooms: [Room.ID: [Int]]?
|
||||||
|
public let height: Int?
|
||||||
|
public let name: String?
|
||||||
|
|
||||||
|
public init(
|
||||||
|
type: TrunkType? = nil,
|
||||||
|
rooms: [Room.ID: [Int]]? = nil,
|
||||||
|
height: Int? = nil,
|
||||||
|
name: String? = nil
|
||||||
|
) {
|
||||||
|
self.type = type
|
||||||
|
self.rooms = rooms
|
||||||
|
self.height = height
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make registers non-optional
|
||||||
|
public struct RoomProxy: Codable, Equatable, Identifiable, Sendable {
|
||||||
|
|
||||||
|
public var id: Room.ID { room.id }
|
||||||
|
public let room: Room
|
||||||
|
public let registers: [Int]
|
||||||
|
|
||||||
|
public init(room: Room, registers: [Int]) {
|
||||||
|
self.room = room
|
||||||
|
self.registers = registers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TrunkType: String, CaseIterable, Codable, Equatable, Sendable {
|
||||||
|
case `return`
|
||||||
|
case supply
|
||||||
|
|
||||||
|
public static let allCases = [Self.supply, .return]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ extension ManualDClient {
|
|||||||
|
|
||||||
func calculateDuctSizes(
|
func calculateDuctSizes(
|
||||||
rooms: [Room],
|
rooms: [Room],
|
||||||
trunks: [DuctSizing.TrunkSize],
|
trunks: [TrunkSize],
|
||||||
sharedRequest: DuctSizeSharedRequest,
|
sharedRequest: DuctSizeSharedRequest,
|
||||||
logger: Logger? = nil
|
logger: Logger? = nil
|
||||||
) async throws -> ProjectClient.DuctSizeResponse {
|
) async throws -> ProjectClient.DuctSizeResponse {
|
||||||
@@ -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
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -94,7 +93,7 @@ extension ManualDClient {
|
|||||||
|
|
||||||
func calculateTrunkSizes(
|
func calculateTrunkSizes(
|
||||||
rooms: [Room],
|
rooms: [Room],
|
||||||
trunks: [DuctSizing.TrunkSize],
|
trunks: [TrunkSize],
|
||||||
sharedRequest: DuctSizeSharedRequest,
|
sharedRequest: DuctSizeSharedRequest,
|
||||||
logger: Logger? = nil
|
logger: Logger? = nil
|
||||||
) async throws -> [DuctSizing.TrunkContainer] {
|
) async throws -> [DuctSizing.TrunkContainer] {
|
||||||
@@ -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: Room.RectangularSize?,
|
||||||
|
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 {
|
||||||
@@ -156,7 +190,7 @@ extension Room {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize.RoomProxy {
|
extension TrunkSize.RoomProxy {
|
||||||
|
|
||||||
// We need to make sure if registers got removed after a trunk
|
// We need to make sure if registers got removed after a trunk
|
||||||
// was already made / saved that we do not include registers that
|
// was already made / saved that we do not include registers that
|
||||||
@@ -177,7 +211,7 @@ extension DuctSizing.TrunkSize.RoomProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DuctSizing.TrunkSize {
|
extension TrunkSize {
|
||||||
|
|
||||||
var totalHeatingLoad: Double {
|
var totalHeatingLoad: Double {
|
||||||
rooms.reduce(into: 0) { $0 += $1.totalHeatingLoad }
|
rooms.reduce(into: 0) { $0 += $1.totalHeatingLoad }
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import ManualDCore
|
|||||||
|
|
||||||
extension SiteRoute.View.ProjectRoute.DuctSizingRoute.TrunkSizeForm {
|
extension SiteRoute.View.ProjectRoute.DuctSizingRoute.TrunkSizeForm {
|
||||||
|
|
||||||
func toCreate(logger: Logger? = nil) throws -> DuctSizing.TrunkSize.Create {
|
func toCreate(logger: Logger? = nil) throws -> TrunkSize.Create {
|
||||||
try .init(
|
try .init(
|
||||||
projectID: projectID,
|
projectID: projectID,
|
||||||
type: type,
|
type: type,
|
||||||
@@ -14,7 +14,7 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute.TrunkSizeForm {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toUpdate(logger: Logger? = nil) throws -> DuctSizing.TrunkSize.Update {
|
func toUpdate(logger: Logger? = nil) throws -> TrunkSize.Update {
|
||||||
try .init(
|
try .init(
|
||||||
type: type,
|
type: type,
|
||||||
rooms: makeRooms(logger: logger),
|
rooms: makeRooms(logger: logger),
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ struct TrunkSizeForm: HTML, Sendable {
|
|||||||
let rooms: [DuctSizing.RoomContainer]
|
let rooms: [DuctSizing.RoomContainer]
|
||||||
let dismiss: Bool
|
let dismiss: Bool
|
||||||
|
|
||||||
var trunk: DuctSizing.TrunkSize? {
|
var trunk: TrunkSize? {
|
||||||
container?.trunk
|
container?.trunk
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ struct TrunkSizeForm: HTML, Sendable {
|
|||||||
label(.class("select w-full")) {
|
label(.class("select w-full")) {
|
||||||
span(.class("label")) { "Type" }
|
span(.class("label")) { "Type" }
|
||||||
select(.name("type")) {
|
select(.name("type")) {
|
||||||
for type in DuctSizing.TrunkSize.TrunkType.allCases {
|
for type in TrunkSize.TrunkType.allCases {
|
||||||
option(.value(type.rawValue)) { type.rawValue.capitalized }
|
option(.value(type.rawValue)) { type.rawValue.capitalized }
|
||||||
.attributes(.selected, when: trunk?.type == type)
|
.attributes(.selected, when: trunk?.type == type)
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ struct TrunkSizeForm: HTML, Sendable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Array where Element == DuctSizing.TrunkSize.RoomProxy {
|
extension Array where Element == TrunkSize.RoomProxy {
|
||||||
func hasRoom(_ room: DuctSizing.RoomContainer) -> Bool {
|
func hasRoom(_ room: DuctSizing.RoomContainer) -> Bool {
|
||||||
first {
|
first {
|
||||||
$0.id == room.roomID
|
$0.id == room.roomID
|
||||||
|
|||||||
Reference in New Issue
Block a user