WIP: Updates test html snapshots, working on validation when delegating airflow to a different room.
Some checks failed
CI / Linux Tests (push) Has been cancelled

This commit is contained in:
2026-02-06 17:01:43 -05:00
parent f2c79ad56f
commit 0775474f57
6 changed files with 179 additions and 47 deletions

View File

@@ -84,6 +84,14 @@ extension DatabaseClient.Rooms: TestDependencyKey {
extension Room.Create {
func toModel(projectID: Project.ID) throws -> RoomModel {
var registerCount = registerCount
// Set register count appropriately when delegatedTo is set / changes.
if delegatedTo != nil {
registerCount = 0
} else if registerCount == 0 {
registerCount = 1
}
return .init(
name: name,
heatingLoad: heatingLoad,
@@ -229,13 +237,28 @@ final class RoomModel: Model, @unchecked Sendable, Validatable {
Validator.validate(\.coolingLoad)
.errorLabel("Cooling Load", inline: true)
Validator.validate(\.registerCount, with: .greaterThanOrEquals(1))
Validator.validate(\.registerCount, with: .greaterThanOrEquals($room.id == nil ? 1 : 0))
.errorLabel("Register Count", inline: true)
Validator.validate(\.rectangularSizes)
}
}
func validateAndSave(on database: Database) async throws {
try self.validate()
if let delegateTo = $room.id {
guard let parent = try await RoomModel.find(delegateTo, on: database) else {
throw ValidationError("Can not find room: \(delegateTo), to delegate airflow to.")
}
guard parent.$room.id == nil else {
throw ValidationError(
"Can not delegate airflow to a room that also delegates it's own airflow."
)
}
}
try await save(on: database)
}
}
extension Room.CoolingLoad: Validatable {

View File

@@ -59,3 +59,24 @@ extension Select where Element: Identifiable, Element.ID == UUID, Element: Senda
}
}
extension Select
where Element: Identifiable, Element.ID == UUID, Element: Sendable, Label == HTMLText {
public init(
_ items: [Element],
label keyPath: KeyPath<Element, String>,
placeholder: String? = nil,
selected: @escaping @Sendable (Element) -> Bool = { _ in false }
) {
self.init(
items,
placeholder: placeholder,
value: { $0.id.uuidString },
selected: selected,
label: { HTMLText($0[keyPath: keyPath]) }
)
}
}

View File

@@ -30,13 +30,17 @@ struct RoomForm: HTML, Sendable {
self.room = room
}
var route: String {
private var route: String {
SiteRoute.View.router.path(
for: .project(.detail(projectID, .rooms(.index)))
)
.appendingPath(room?.id)
}
private var selectableRooms: [Room] {
rooms.filter { $0.delegatedTo == nil }
}
var body: some HTML {
ModalForm(id: Self.id(room), dismiss: dismiss) {
h1(.class("text-3xl font-bold pb-6")) { "Room" }
@@ -104,28 +108,15 @@ struct RoomForm: HTML, Sendable {
.id("registerCount")
)
label(.class("select w-full"), .id("delegateToSelect")) {
label(.class("select w-full")) {
span(.class("label")) { "Room" }
Select(rooms, placeholder: "Delegate Airflow") {
$0.name
}
.attributes(.name("delegatedTo"))
Select(selectableRooms, label: \.name, placeholder: "Delegate Airflow")
.attributes(.name("delegatedTo"))
}
SubmitButton()
.attributes(.class("btn-block"))
}
}
script {
"""
function myClick() {
console.log('clicked');
const simple = document.getElementById('simple');
console.log(simple.style.display);
simple.style.display = 'block';
console.log(simple.style.display);
}
"""
}
}
}

View File

@@ -17,11 +17,6 @@ struct RoomsView: HTML, Sendable {
var body: some HTML {
div(.class("flex w-full flex-col")) {
input(.type(.checkbox), .name("delegateToCheckbox"), .on(.click, "showElement('simple');"))
div(.style("display: none;"), .id("simple"), .class("hidden")) {
"This is hidden"
}
PageTitleRow {
div(.class("flex grid grid-cols-3 w-full gap-y-4")) {
@@ -107,6 +102,11 @@ struct RoomsView: HTML, Sendable {
"Register Count"
}
}
th {
div(.class("flex justify-center")) {
"Delegated To"
}
}
th {
div(.class("flex justify-end me-2 space-x-4")) {
@@ -151,10 +151,11 @@ struct RoomsView: HTML, Sendable {
var coolingSensible: Double {
try! room.coolingLoad.ensured(shr: shr).sensible
// guard let value = room.coolingSensible else {
// return room.coolingTotal * shr
// }
// return value
}
var delegatedToRoomName: String? {
guard let delegatedToID = room.delegatedTo else { return nil }
return rooms.first(where: { $0.id == delegatedToID })?.name
}
init(room: Room, shr: Double?, rooms: [Room]) {
@@ -186,7 +187,14 @@ struct RoomsView: HTML, Sendable {
}
td {
div(.class("flex justify-center")) {
Number(room.registerCount)
Number(delegatedToRoomName != nil ? 0 : room.registerCount)
}
}
td {
if let name = delegatedToRoomName {
div(.class("flex justify-center")) {
name
}
}
}
td {