fix: Fixes duct sizing rooms table not showing forms correctly, updates the table styles.
This commit is contained in:
@@ -14,6 +14,8 @@ extension DatabaseClient {
|
|||||||
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:
|
||||||
|
@Sendable (Room.ID, DuctSizing.RectangularDuct) async throws -> Room
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +69,19 @@ extension DatabaseClient.Rooms: TestDependencyKey {
|
|||||||
try await model.save(on: database)
|
try await model.save(on: database)
|
||||||
}
|
}
|
||||||
return try model.toDTO()
|
return try model.toDTO()
|
||||||
|
},
|
||||||
|
updateRectangularSize: { id, size in
|
||||||
|
guard let model = try await RoomModel.find(id, on: database) else {
|
||||||
|
throw NotFoundError()
|
||||||
|
}
|
||||||
|
var rectangularSizes = model.rectangularSizes ?? []
|
||||||
|
rectangularSizes.removeAll {
|
||||||
|
$0.id == size.id
|
||||||
|
}
|
||||||
|
rectangularSizes.append(size)
|
||||||
|
model.rectangularSizes = rectangularSizes
|
||||||
|
try await model.save(on: database)
|
||||||
|
return try model.toDTO()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -607,7 +607,7 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
|
|
||||||
public enum DuctSizingRoute: Equatable, Sendable {
|
public enum DuctSizingRoute: Equatable, Sendable {
|
||||||
case index
|
case index
|
||||||
case deleteRectangularSize(Room.ID, DuctSizing.RectangularDuct.ID)
|
case deleteRectangularSize(Room.ID, DeleteRectangularDuct)
|
||||||
case roomRectangularForm(Room.ID, RoomRectangularForm)
|
case roomRectangularForm(Room.ID, RoomRectangularForm)
|
||||||
case trunk(TrunkRoute)
|
case trunk(TrunkRoute)
|
||||||
|
|
||||||
@@ -628,7 +628,9 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
Method.delete
|
Method.delete
|
||||||
Query {
|
Query {
|
||||||
Field("rectangularSize") { DuctSizing.RectangularDuct.ID.parser() }
|
Field("rectangularSize") { DuctSizing.RectangularDuct.ID.parser() }
|
||||||
|
Field("register") { Int.parser() }
|
||||||
}
|
}
|
||||||
|
.map(.memberwise(DeleteRectangularDuct.init))
|
||||||
}
|
}
|
||||||
Route(.case(Self.roomRectangularForm)) {
|
Route(.case(Self.roomRectangularForm)) {
|
||||||
Path {
|
Path {
|
||||||
@@ -654,6 +656,17 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct DeleteRectangularDuct: Equatable, Sendable {
|
||||||
|
|
||||||
|
public let rectangularSizeID: DuctSizing.RectangularDuct.ID
|
||||||
|
public let register: Int
|
||||||
|
|
||||||
|
public init(rectangularSizeID: DuctSizing.RectangularDuct.ID, register: Int) {
|
||||||
|
self.rectangularSizeID = rectangularSizeID
|
||||||
|
self.register = register
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum TrunkRoute: Equatable, Sendable {
|
public enum TrunkRoute: Equatable, Sendable {
|
||||||
case delete(DuctSizing.TrunkSize.ID)
|
case delete(DuctSizing.TrunkSize.ID)
|
||||||
case submit(TrunkSizeForm)
|
case submit(TrunkSizeForm)
|
||||||
|
|||||||
@@ -17,4 +17,8 @@ extension String {
|
|||||||
func appendingPath(_ id: UUID) -> Self {
|
func appendingPath(_ id: UUID) -> Self {
|
||||||
return appendingPath(id.uuidString)
|
return appendingPath(id.uuidString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var idString: Self {
|
||||||
|
replacing("-", with: "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,6 @@ import Foundation
|
|||||||
|
|
||||||
extension UUID {
|
extension UUID {
|
||||||
var idString: String {
|
var idString: String {
|
||||||
uuidString.replacing("-", with: "")
|
uuidString.idString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -538,33 +538,29 @@ extension SiteRoute.View.ProjectRoute.DuctSizingRoute {
|
|||||||
case .index:
|
case .index:
|
||||||
return await view(on: request, projectID: projectID)
|
return await view(on: request, projectID: projectID)
|
||||||
|
|
||||||
case .deleteRectangularSize(let roomID, let rectangularSizeID):
|
case .deleteRectangularSize(let roomID, let request):
|
||||||
return await ResultView {
|
return await ResultView {
|
||||||
let room = try await database.rooms.deleteRectangularSize(roomID, rectangularSizeID)
|
let room = try await database.rooms.deleteRectangularSize(roomID, request.rectangularSizeID)
|
||||||
return try await database.calculateDuctSizes(projectID: projectID)
|
return try await database.calculateDuctSizes(projectID: projectID)
|
||||||
.rooms
|
.rooms
|
||||||
.filter({ $0.roomID == room.id })
|
.filter({ $0.roomID == room.id && $0.roomRegister == request.register })
|
||||||
.first!
|
.first!
|
||||||
} onSuccess: { container in
|
} onSuccess: { room in
|
||||||
DuctSizingView.RoomRow(room: container)
|
DuctSizingView.RoomRow(room: room)
|
||||||
}
|
}
|
||||||
|
|
||||||
case .roomRectangularForm(let roomID, let form):
|
case .roomRectangularForm(let roomID, let form):
|
||||||
return await ResultView {
|
return await ResultView {
|
||||||
let room = try await database.rooms.update(
|
let room = try await database.rooms.updateRectangularSize(
|
||||||
roomID,
|
roomID,
|
||||||
.init(
|
.init(id: form.id ?? .init(), register: form.register, height: form.height)
|
||||||
rectangularSizes: [
|
|
||||||
.init(id: form.id ?? .init(), register: form.register, height: form.height)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return try await database.calculateDuctSizes(projectID: projectID)
|
return try await database.calculateDuctSizes(projectID: projectID)
|
||||||
.rooms
|
.rooms
|
||||||
.filter({ $0.roomID == room.id })
|
.filter({ $0.roomID == room.id && $0.roomRegister == form.register })
|
||||||
.first!
|
.first!
|
||||||
} onSuccess: { container in
|
} onSuccess: { room in
|
||||||
DuctSizingView.RoomRow(room: container)
|
DuctSizingView.RoomRow(room: room)
|
||||||
}
|
}
|
||||||
|
|
||||||
case .trunk(let route):
|
case .trunk(let route):
|
||||||
|
|||||||
@@ -31,30 +31,30 @@ struct DuctSizingView: HTML, Sendable {
|
|||||||
RoomsTable(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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,58 +5,25 @@ import Styleguide
|
|||||||
|
|
||||||
struct RectangularSizeForm: HTML, Sendable {
|
struct RectangularSizeForm: HTML, Sendable {
|
||||||
|
|
||||||
static func id(_ roomID: Room.ID? = nil) -> String {
|
|
||||||
let base = "rectangularSize"
|
|
||||||
guard let roomID else { return base }
|
|
||||||
return "\(base)_\(roomID.idString)"
|
|
||||||
}
|
|
||||||
|
|
||||||
static func id(_ room: DuctSizing.RoomContainer) -> String {
|
static func id(_ room: DuctSizing.RoomContainer) -> String {
|
||||||
return id(room.roomID)
|
let base = "rectangularSize"
|
||||||
|
return "\(base)_\(room.registerID.idString)"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Environment(ProjectViewValue.$projectID) var projectID
|
@Environment(ProjectViewValue.$projectID) var projectID
|
||||||
|
|
||||||
let id: String
|
let id: String
|
||||||
let roomID: Room.ID
|
let room: DuctSizing.RoomContainer
|
||||||
let rectangularSizeID: DuctSizing.RectangularDuct.ID?
|
|
||||||
let register: Int
|
|
||||||
let height: Int?
|
|
||||||
let dismiss: Bool
|
let dismiss: Bool
|
||||||
|
|
||||||
init(
|
|
||||||
id: String? = nil,
|
|
||||||
roomID: Room.ID,
|
|
||||||
rectangularSizeID: DuctSizing.RectangularDuct.ID? = nil,
|
|
||||||
register: Int,
|
|
||||||
height: Int? = nil,
|
|
||||||
dismiss: Bool = true
|
|
||||||
) {
|
|
||||||
self.id = id ?? Self.id(roomID)
|
|
||||||
self.roomID = roomID
|
|
||||||
self.rectangularSizeID = rectangularSizeID
|
|
||||||
self.register = register
|
|
||||||
self.height = height
|
|
||||||
self.dismiss = dismiss
|
|
||||||
}
|
|
||||||
|
|
||||||
init(
|
init(
|
||||||
id: String? = nil,
|
id: String? = nil,
|
||||||
room: DuctSizing.RoomContainer,
|
room: DuctSizing.RoomContainer,
|
||||||
dismiss: Bool = true
|
dismiss: Bool = true
|
||||||
) {
|
) {
|
||||||
let register =
|
self.id = Self.id(room)
|
||||||
room.rectangularSize?.register
|
self.room = room
|
||||||
?? (Int("\(room.roomName.last!)") ?? 1)
|
self.dismiss = dismiss
|
||||||
|
|
||||||
self.init(
|
|
||||||
id: id,
|
|
||||||
roomID: room.roomID,
|
|
||||||
rectangularSizeID: room.rectangularSize?.id,
|
|
||||||
register: register,
|
|
||||||
height: room.rectangularSize?.height,
|
|
||||||
dismiss: dismiss
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var route: String {
|
var route: String {
|
||||||
@@ -64,23 +31,30 @@ struct RectangularSizeForm: HTML, Sendable {
|
|||||||
for: .project(.detail(projectID, .ductSizing(.index)))
|
for: .project(.detail(projectID, .ductSizing(.index)))
|
||||||
)
|
)
|
||||||
.appendingPath("room")
|
.appendingPath("room")
|
||||||
.appendingPath(roomID)
|
.appendingPath(room.roomID)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rowID: String {
|
||||||
|
DuctSizingView.RoomRow.id(room)
|
||||||
|
}
|
||||||
|
|
||||||
|
var height: Int? {
|
||||||
|
room.rectangularSize?.height
|
||||||
|
}
|
||||||
|
|
||||||
var body: some HTML<HTMLTag.dialog> {
|
var body: some HTML<HTMLTag.dialog> {
|
||||||
ModalForm(id: id, dismiss: dismiss) {
|
ModalForm(id: id, dismiss: dismiss) {
|
||||||
|
|
||||||
h1(.class("text-lg pb-6")) { "Rectangular Size" }
|
h1(.class("text-lg pb-6")) { "Rectangular Size" }
|
||||||
|
|
||||||
form(
|
form(
|
||||||
.class("space-y-4"),
|
.class("space-y-4"),
|
||||||
.hx.post(route),
|
.hx.post(route),
|
||||||
.hx.target("closest tr"),
|
.hx.target("#\(rowID)"),
|
||||||
.hx.swap(.outerHTML)
|
.hx.swap(.outerHTML)
|
||||||
) {
|
) {
|
||||||
input(.class("hidden"), .name("register"), .value(register))
|
input(.class("hidden"), .name("register"), .value(room.roomRegister))
|
||||||
input(.class("hidden"), .name("id"), .value(rectangularSizeID))
|
input(.class("hidden"), .name("id"), .value(room.rectangularSize?.id))
|
||||||
|
|
||||||
LabeledInput(
|
LabeledInput(
|
||||||
"Height",
|
"Height",
|
||||||
|
|||||||
@@ -21,10 +21,8 @@ extension DuctSizingView {
|
|||||||
th { "Name" }
|
th { "Name" }
|
||||||
th { "BTU" }
|
th { "BTU" }
|
||||||
th { "CFM" }
|
th { "CFM" }
|
||||||
th(.class("hidden 2xl:table-cell")) { "Round Size" }
|
|
||||||
th { "Velocity" }
|
th { "Velocity" }
|
||||||
th { "Size" }
|
th { "Size" }
|
||||||
th {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbody {
|
tbody {
|
||||||
@@ -39,6 +37,10 @@ extension DuctSizingView {
|
|||||||
|
|
||||||
struct RoomRow: HTML, Sendable {
|
struct RoomRow: HTML, Sendable {
|
||||||
|
|
||||||
|
static func id(_ room: DuctSizing.RoomContainer) -> String {
|
||||||
|
"roomRow_\(room.registerID.idString)"
|
||||||
|
}
|
||||||
|
|
||||||
@Environment(ProjectViewValue.$projectID) var projectID
|
@Environment(ProjectViewValue.$projectID) var projectID
|
||||||
|
|
||||||
let room: DuctSizing.RoomContainer
|
let room: DuctSizing.RoomContainer
|
||||||
@@ -51,14 +53,20 @@ extension DuctSizingView {
|
|||||||
for: .project(
|
for: .project(
|
||||||
.detail(
|
.detail(
|
||||||
projectID,
|
projectID,
|
||||||
.ductSizing(.deleteRectangularSize(room.roomID, id))
|
.ductSizing(
|
||||||
|
.deleteRectangularSize(
|
||||||
|
room.roomID,
|
||||||
|
.init(rectangularSizeID: id, register: room.roomRegister)
|
||||||
|
))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rowID: String { Self.id(room) }
|
||||||
|
|
||||||
var body: some HTML<HTMLTag.tr> {
|
var body: some HTML<HTMLTag.tr> {
|
||||||
tr(.class("text-lg items-baseline"), .id(room.roomID.idString)) {
|
tr(.class("text-lg items-baseline"), .id(rowID)) {
|
||||||
td { room.registerID }
|
td { room.registerID }
|
||||||
td { room.roomName }
|
td { room.roomName }
|
||||||
td {
|
td {
|
||||||
@@ -75,84 +83,89 @@ extension DuctSizingView {
|
|||||||
div(.class("grid grid-cols-2 gap-2")) {
|
div(.class("grid grid-cols-2 gap-2")) {
|
||||||
|
|
||||||
span(.class("label")) { "Design" }
|
span(.class("label")) { "Design" }
|
||||||
Badge(number: room.designCFM.value, digits: 0)
|
div(.class("flex justify-center")) {
|
||||||
|
Badge(number: room.designCFM.value, digits: 0)
|
||||||
|
}
|
||||||
|
|
||||||
span(.class("label")) { "Heating" }
|
span(.class("label")) { "Heating" }
|
||||||
Number(room.heatingCFM, digits: 0)
|
div(.class("flex justify-center")) {
|
||||||
|
Number(room.heatingCFM, digits: 0)
|
||||||
|
}
|
||||||
|
|
||||||
span(.class("label")) { "Cooling" }
|
span(.class("label")) { "Cooling" }
|
||||||
Number(room.coolingCFM, digits: 0)
|
div(.class("flex justify-center")) {
|
||||||
|
Number(room.coolingCFM, digits: 0)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td(.class("hidden 2xl:table-cell")) { Number(room.roundSize, digits: 1) }
|
|
||||||
td { Number(room.velocity) }
|
td { Number(room.velocity) }
|
||||||
|
|
||||||
td {
|
td {
|
||||||
div(.class("grid grid-cols-2 gap-2")) {
|
div(.class("grid grid-cols-3 gap-2")) {
|
||||||
|
|
||||||
span(.class("label")) { "Final" }
|
div(.class("label")) { "Calculated" }
|
||||||
Badge(number: room.finalSize)
|
div(.class("flex justify-center")) {
|
||||||
.attributes(.class("badge-secondary"))
|
Badge(number: room.roundSize, digits: 1)
|
||||||
|
}
|
||||||
|
div {}
|
||||||
|
|
||||||
span(.class("label")) { "Flex" }
|
div(.class("label")) { "Final" }
|
||||||
Badge(number: room.flexSize)
|
div(.class("flex justify-center")) {
|
||||||
.attributes(.class("badge-primary"))
|
Badge(number: room.finalSize)
|
||||||
|
.attributes(.class("badge-secondary"))
|
||||||
|
}
|
||||||
|
div {}
|
||||||
|
|
||||||
if let width = room.rectangularWidth,
|
div(.class("label")) { "Flex" }
|
||||||
let height = room.rectangularSize?.height
|
div(.class("flex justify-center")) {
|
||||||
{
|
Badge(number: room.flexSize)
|
||||||
span(.class("label")) { "Rectangular" }
|
.attributes(.class("badge-primary"))
|
||||||
Badge {
|
}
|
||||||
span { "\(width) x \(height)" }
|
div {}
|
||||||
|
|
||||||
|
div(.class("label")) { "Rectangular" }
|
||||||
|
div(.class("flex justify-center")) {
|
||||||
|
if let width = room.rectangularWidth,
|
||||||
|
let height = room.rectangularSize?.height
|
||||||
|
{
|
||||||
|
Badge {
|
||||||
|
span { "\(width) x \(height)" }
|
||||||
|
}
|
||||||
|
.attributes(.class("badge-info"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
div(.class("flex justify-end")) {
|
||||||
}
|
div(.class("join")) {
|
||||||
|
if room.rectangularSize != nil {
|
||||||
|
Tooltip("Delete Size", position: .bottom) {
|
||||||
|
TrashButton()
|
||||||
|
.attributes(.class("join-item btn-ghost"))
|
||||||
|
.attributes(
|
||||||
|
.hx.delete(deleteRoute),
|
||||||
|
.hx.target("#\(rowID)"),
|
||||||
|
.hx.swap(.outerHTML),
|
||||||
|
when: room.rectangularSize != nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tooltip("Edit Size", position: .bottom) {
|
||||||
|
EditButton()
|
||||||
|
.attributes(
|
||||||
|
.class("join-item btn-ghost"),
|
||||||
|
.showModal(id: RectangularSizeForm.id(room))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
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))
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
RectangularSizeForm(room: 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" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user