feat: Some style updates, form improvements on project-room view.

This commit is contained in:
2026-01-06 16:58:42 -05:00
parent 8fb313fddc
commit dbf7e3b1b4
10 changed files with 103 additions and 57 deletions

View File

@@ -9,8 +9,6 @@
monospace;
--color-red-500: oklch(63.7% 0.237 25.331);
--color-red-600: oklch(57.7% 0.245 27.325);
--color-blue-500: oklch(62.3% 0.214 259.815);
--color-blue-600: oklch(54.6% 0.245 262.881);
--color-indigo-600: oklch(51.1% 0.262 276.966);
--color-slate-300: oklch(86.9% 0.022 252.894);
--color-slate-900: oklch(20.8% 0.042 265.755);
@@ -21,6 +19,8 @@
--color-black: #000;
--color-white: #fff;
--spacing: 0.25rem;
--breakpoint-lg: 64rem;
--container-lg: 32rem;
--container-xl: 36rem;
--text-sm: 0.875rem;
--text-sm--line-height: calc(1.25 / 0.875);
@@ -5222,6 +5222,9 @@
.m-4 {
margin: calc(var(--spacing) * 4);
}
.m-6 {
margin: calc(var(--spacing) * 6);
}
.filter {
@layer daisyui.l1.l2.l3 {
display: flex;
@@ -5353,6 +5356,9 @@
}
}
}
.my-2 {
margin-block: calc(var(--spacing) * 2);
}
.label {
@layer daisyui.l1.l2.l3 {
display: inline-flex;
@@ -6525,9 +6531,6 @@
width: calc(var(--size-selector, 0.25rem) * 4);
}
}
.w-\[40px\] {
width: 40px;
}
.w-full {
width: 100%;
}
@@ -7776,9 +7779,6 @@
.pe-2 {
padding-inline-end: calc(var(--spacing) * 2);
}
.pe-4 {
padding-inline-end: calc(var(--spacing) * 4);
}
.pb-4 {
padding-bottom: calc(var(--spacing) * 4);
}
@@ -8401,6 +8401,9 @@
.text-gray-400 {
color: var(--color-gray-400);
}
.text-info {
color: var(--color-info);
}
.text-slate-900 {
color: var(--color-slate-900);
}

View File

@@ -65,7 +65,7 @@ public struct EditButton: HTML, Sendable {
}
public var body: some HTML<HTMLTag.button> {
button(.class("btn btn-success dark:text-white"), .type(type)) {
button(.class("btn btn-success btn-circle dark:text-white"), .type(type)) {
div(.class("flex")) {
if let title {
span(.class("pe-2")) { title }
@@ -83,7 +83,7 @@ public struct PlusButton: HTML, Sendable {
public var body: some HTML<HTMLTag.button> {
button(
.type(.button),
.class("btn btn-primary")
.class("btn btn-primary btn-circle text-xl")
) { SVG(.circlePlus) }
}
}
@@ -94,7 +94,7 @@ public struct TrashButton: HTML, Sendable {
public var body: some HTML<HTMLTag.button> {
button(
.type(.button),
.class("btn btn-error dark:text-white")
.class("btn btn-error btn-circle dark:text-white")
) {
SVG(.trash)
}

View File

@@ -15,6 +15,7 @@ public struct SVG: HTML, Sendable {
extension SVG {
public enum Key: Sendable {
case chevronRight
case circlePlus
case close
case email
@@ -25,6 +26,10 @@ extension SVG {
var svg: String {
switch self {
case .chevronRight:
return """
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right-icon lucide-chevron-right"><path d="m9 18 6-6-6-6"/></svg>
"""
case .circlePlus:
return """
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-plus-icon lucide-circle-plus"><circle cx="12" cy="12" r="10"/><path d="M8 12h8"/><path d="M12 8v8"/></svg>

View File

@@ -179,13 +179,14 @@ extension SiteRoute.View.ProjectRoute.RoomRoute {
case .submit(let form):
request.logger.debug("New room form submitted.")
// FIX: Just return a room row??
let _ = try await database.rooms.create(form)
return request.view {
ProjectView(projectID: projectID, activeTab: .rooms)
}
case .update(let form):
_ = try await database.rooms.update(form)
let _ = try await database.rooms.update(form)
return ProjectView(projectID: projectID, activeTab: .rooms)
case .updateSensibleHeatRatio(let form):

View File

@@ -5,6 +5,8 @@ import Styleguide
struct ProjectForm: HTML, Sendable {
static let id = "projectForm"
let project: Project?
let dismiss: Bool
@@ -17,7 +19,7 @@ struct ProjectForm: HTML, Sendable {
}
var body: some HTML {
ModalForm(id: "projectForm", dismiss: dismiss) {
ModalForm(id: Self.id, dismiss: dismiss) {
h1(.class("text-3xl font-bold pb-6 ps-2")) { "Project" }
form(
.class("space-y-4 p-4"),

View File

@@ -80,7 +80,7 @@ struct Sidebar: HTML {
div(.class("flex")) {
// TODO: Move somewhere outside of the sidebar.
button(
.class("w-full btn btn-secondary"),
.class("btn btn-secondary btn-block"),
.hx.get(route: .project(.index)),
.hx.target("body"),
.hx.pushURL(true),

View File

@@ -16,21 +16,17 @@ struct ProjectsTable: HTML, Sendable {
}
var body: some HTML {
div {
div(.class("m-6")) {
Row {
h1(.class("text-2xl font-bold")) { "Projects" }
div(
.class("tooltip tooltip-left"),
.data("tip", value: "Add project")
) {
button(
.class("btn btn-primary w-[40px] text-2xl"),
.hx.get(route: .project(.form(dismiss: false))),
.hx.target("#projectForm"),
.hx.swap(.outerHTML)
) {
"+"
}
PlusButton()
.attributes(
.showModal(id: ProjectForm.id)
)
}
}
.attributes(.class("pb-6"))
@@ -75,9 +71,11 @@ extension ProjectsTable {
.hx.target("closest tr")
)
a(
.class("btn btn-success dark:text-white"),
.class("btn btn-success btn-circle dark:text-white"),
.href(route: .project(.detail(project.id, .index())))
) { ">" }
) {
SVG(.chevronRight)
}
}
}
}

View File

@@ -10,14 +10,26 @@ struct RoomForm: HTML, Sendable {
static let id = "roomForm"
let id: String
let dismiss: Bool
let projectID: Project.ID
let room: Room?
init(
id: String = Self.id,
dismiss: Bool,
projectID: Project.ID,
room: Room? = nil
) {
self.id = id
self.dismiss = dismiss
self.projectID = projectID
self.room = room
}
var body: some HTML {
ModalForm(id: Self.id, dismiss: dismiss) {
ModalForm(id: id, dismiss: dismiss) {
h1(.class("text-3xl font-bold pb-6")) { "Room" }
// TODO: Use htmx here.
form(
.class("modal-backdrop"),
.init(name: "method", value: "dialog"),
@@ -62,9 +74,8 @@ struct RoomForm: HTML, Sendable {
.value("\(room != nil ? room!.registerCount : 1)"),
)
}
div(.class("flex justify-end space-x-4")) {
SubmitButton()
}
SubmitButton()
.attributes(.class("btn-block"))
}
}
}

View File

@@ -20,11 +20,9 @@ struct RoomsView: HTML, Sendable {
.class("tooltip tooltip-left"),
.data("tip", value: "Add room")
) {
button(
.showModal(id: RoomForm.id),
.class("btn btn-primary w-[40px] text-2xl")
) {
"+"
div(.class("flex me-4")) {
PlusButton()
.attributes(.showModal(id: RoomForm.id))
}
}
}
@@ -32,7 +30,7 @@ struct RoomsView: HTML, Sendable {
div(.class("border rounded-lg mb-6")) {
Row {
div(.class("space-x-6")) {
div(.class("space-x-6 my-2")) {
Label("Sensible Heat Ratio")
if let sensibleHeatRatio {
Number(sensibleHeatRatio)
@@ -54,27 +52,29 @@ struct RoomsView: HTML, Sendable {
th { Label("Name") }
th { Label("Heating Load") }
th { Label("Cooling Total") }
th { Label("Cooling Sensible") }
th { Label("Register Count") }
th {}
}
}
tbody {
div(.id("rooms")) {
for room in rooms {
RoomRow(room: room)
}
for room in rooms {
RoomRow(room: room, shr: sensibleHeatRatio)
}
// TOTALS
tr(.class("font-bold text-xl")) {
td { Label("Total") }
td {
Number(rooms.heatingTotal)
Number(rooms.heatingTotal, digits: 0)
.attributes(.class("badge badge-outline badge-error badge-xl"))
}
td {
Number(rooms.coolingTotal)
.attributes(
.class("badge badge-outline badge-success badge-xl"))
Number(rooms.coolingTotal, digits: 0)
.attributes(.class("badge badge-outline badge-success badge-xl"))
}
td {
Number(rooms.coolingSensible(shr: sensibleHeatRatio), digits: 0)
.attributes(.class("badge badge-outline badge-info badge-xl"))
}
td {}
td {}
@@ -88,19 +88,35 @@ struct RoomsView: HTML, Sendable {
public struct RoomRow: HTML, Sendable {
let room: Room
let shr: Double
var coolingSensible: Double {
guard let value = room.coolingSensible else {
return room.coolingTotal * shr
}
return value
}
init(room: Room, shr: Double?) {
self.room = room
self.shr = shr ?? 1.0
}
public var body: some HTML {
tr(.id("\(room.id)")) {
tr(.id("roomRow_\(room.name)")) {
td { room.name }
td {
Number(room.heatingLoad)
Number(room.heatingLoad, digits: 0)
.attributes(.class("text-error"))
}
td {
Number(room.coolingTotal)
Number(room.coolingTotal, digits: 0)
.attributes(.class("text-success"))
}
// FIX: Add cooling sensible.
td {
Number(coolingSensible, digits: 0)
.attributes(.class("text-info"))
}
td {
Number(room.registerCount)
}
@@ -115,15 +131,15 @@ struct RoomsView: HTML, Sendable {
)
EditButton()
.attributes(
.hx.get(
route: .project(
.detail(room.projectID, .rooms(.form(id: room.id, dismiss: false)))
)
),
.hx.target("#roomForm"),
.hx.swap(.outerHTML)
.showModal(id: "roomForm_\(room.name)")
)
}
RoomForm(
id: "roomForm_\(room.name)",
dismiss: true,
projectID: room.projectID,
room: room
)
}
}
}
@@ -167,4 +183,13 @@ extension Array where Element == Room {
var coolingTotal: Double {
reduce(into: 0) { $0 += $1.coolingTotal }
}
func coolingSensible(shr: Double?) -> Double {
let shr = shr ?? 1.0
return reduce(into: 0) {
let sensible = $1.coolingSensible ?? ($1.coolingTotal * shr)
$0 += sensible
}
}
}

View File

@@ -32,7 +32,8 @@ struct LoginForm: HTML, Sendable {
input(
.type(.text), .required, .placeholder("Username"),
.name("username"), .id("username"),
.minlength("3"), .pattern(.username)
.minlength("3"), .pattern(.username),
.autofocus
)
}
div(.class("validator-hint hidden")) {
@@ -48,7 +49,7 @@ struct LoginForm: HTML, Sendable {
SVG(.email)
input(
.type(.email), .placeholder("Email"), .required,
.name("email"), .id("email"),
.name("email"), .id("email"), .autofocus
)
}
div(.class("validator-hint hidden")) { "Enter valid email address." }