feat: Some style updates, form improvements on project-room view.
This commit is contained in:
@@ -9,8 +9,6 @@
|
|||||||
monospace;
|
monospace;
|
||||||
--color-red-500: oklch(63.7% 0.237 25.331);
|
--color-red-500: oklch(63.7% 0.237 25.331);
|
||||||
--color-red-600: oklch(57.7% 0.245 27.325);
|
--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-indigo-600: oklch(51.1% 0.262 276.966);
|
||||||
--color-slate-300: oklch(86.9% 0.022 252.894);
|
--color-slate-300: oklch(86.9% 0.022 252.894);
|
||||||
--color-slate-900: oklch(20.8% 0.042 265.755);
|
--color-slate-900: oklch(20.8% 0.042 265.755);
|
||||||
@@ -21,6 +19,8 @@
|
|||||||
--color-black: #000;
|
--color-black: #000;
|
||||||
--color-white: #fff;
|
--color-white: #fff;
|
||||||
--spacing: 0.25rem;
|
--spacing: 0.25rem;
|
||||||
|
--breakpoint-lg: 64rem;
|
||||||
|
--container-lg: 32rem;
|
||||||
--container-xl: 36rem;
|
--container-xl: 36rem;
|
||||||
--text-sm: 0.875rem;
|
--text-sm: 0.875rem;
|
||||||
--text-sm--line-height: calc(1.25 / 0.875);
|
--text-sm--line-height: calc(1.25 / 0.875);
|
||||||
@@ -5222,6 +5222,9 @@
|
|||||||
.m-4 {
|
.m-4 {
|
||||||
margin: calc(var(--spacing) * 4);
|
margin: calc(var(--spacing) * 4);
|
||||||
}
|
}
|
||||||
|
.m-6 {
|
||||||
|
margin: calc(var(--spacing) * 6);
|
||||||
|
}
|
||||||
.filter {
|
.filter {
|
||||||
@layer daisyui.l1.l2.l3 {
|
@layer daisyui.l1.l2.l3 {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -5353,6 +5356,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.my-2 {
|
||||||
|
margin-block: calc(var(--spacing) * 2);
|
||||||
|
}
|
||||||
.label {
|
.label {
|
||||||
@layer daisyui.l1.l2.l3 {
|
@layer daisyui.l1.l2.l3 {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -6525,9 +6531,6 @@
|
|||||||
width: calc(var(--size-selector, 0.25rem) * 4);
|
width: calc(var(--size-selector, 0.25rem) * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.w-\[40px\] {
|
|
||||||
width: 40px;
|
|
||||||
}
|
|
||||||
.w-full {
|
.w-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -7776,9 +7779,6 @@
|
|||||||
.pe-2 {
|
.pe-2 {
|
||||||
padding-inline-end: calc(var(--spacing) * 2);
|
padding-inline-end: calc(var(--spacing) * 2);
|
||||||
}
|
}
|
||||||
.pe-4 {
|
|
||||||
padding-inline-end: calc(var(--spacing) * 4);
|
|
||||||
}
|
|
||||||
.pb-4 {
|
.pb-4 {
|
||||||
padding-bottom: calc(var(--spacing) * 4);
|
padding-bottom: calc(var(--spacing) * 4);
|
||||||
}
|
}
|
||||||
@@ -8401,6 +8401,9 @@
|
|||||||
.text-gray-400 {
|
.text-gray-400 {
|
||||||
color: var(--color-gray-400);
|
color: var(--color-gray-400);
|
||||||
}
|
}
|
||||||
|
.text-info {
|
||||||
|
color: var(--color-info);
|
||||||
|
}
|
||||||
.text-slate-900 {
|
.text-slate-900 {
|
||||||
color: var(--color-slate-900);
|
color: var(--color-slate-900);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public struct EditButton: HTML, Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var body: some HTML<HTMLTag.button> {
|
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")) {
|
div(.class("flex")) {
|
||||||
if let title {
|
if let title {
|
||||||
span(.class("pe-2")) { title }
|
span(.class("pe-2")) { title }
|
||||||
@@ -83,7 +83,7 @@ public struct PlusButton: HTML, Sendable {
|
|||||||
public var body: some HTML<HTMLTag.button> {
|
public var body: some HTML<HTMLTag.button> {
|
||||||
button(
|
button(
|
||||||
.type(.button),
|
.type(.button),
|
||||||
.class("btn btn-primary")
|
.class("btn btn-primary btn-circle text-xl")
|
||||||
) { SVG(.circlePlus) }
|
) { SVG(.circlePlus) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ public struct TrashButton: HTML, Sendable {
|
|||||||
public var body: some HTML<HTMLTag.button> {
|
public var body: some HTML<HTMLTag.button> {
|
||||||
button(
|
button(
|
||||||
.type(.button),
|
.type(.button),
|
||||||
.class("btn btn-error dark:text-white")
|
.class("btn btn-error btn-circle dark:text-white")
|
||||||
) {
|
) {
|
||||||
SVG(.trash)
|
SVG(.trash)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public struct SVG: HTML, Sendable {
|
|||||||
|
|
||||||
extension SVG {
|
extension SVG {
|
||||||
public enum Key: Sendable {
|
public enum Key: Sendable {
|
||||||
|
case chevronRight
|
||||||
case circlePlus
|
case circlePlus
|
||||||
case close
|
case close
|
||||||
case email
|
case email
|
||||||
@@ -25,6 +26,10 @@ extension SVG {
|
|||||||
|
|
||||||
var svg: String {
|
var svg: String {
|
||||||
switch self {
|
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:
|
case .circlePlus:
|
||||||
return """
|
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>
|
<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>
|
||||||
|
|||||||
@@ -179,13 +179,14 @@ extension SiteRoute.View.ProjectRoute.RoomRoute {
|
|||||||
|
|
||||||
case .submit(let form):
|
case .submit(let form):
|
||||||
request.logger.debug("New room form submitted.")
|
request.logger.debug("New room form submitted.")
|
||||||
|
// FIX: Just return a room row??
|
||||||
let _ = try await database.rooms.create(form)
|
let _ = try await database.rooms.create(form)
|
||||||
return request.view {
|
return request.view {
|
||||||
ProjectView(projectID: projectID, activeTab: .rooms)
|
ProjectView(projectID: projectID, activeTab: .rooms)
|
||||||
}
|
}
|
||||||
|
|
||||||
case .update(let form):
|
case .update(let form):
|
||||||
_ = try await database.rooms.update(form)
|
let _ = try await database.rooms.update(form)
|
||||||
return ProjectView(projectID: projectID, activeTab: .rooms)
|
return ProjectView(projectID: projectID, activeTab: .rooms)
|
||||||
|
|
||||||
case .updateSensibleHeatRatio(let form):
|
case .updateSensibleHeatRatio(let form):
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import Styleguide
|
|||||||
|
|
||||||
struct ProjectForm: HTML, Sendable {
|
struct ProjectForm: HTML, Sendable {
|
||||||
|
|
||||||
|
static let id = "projectForm"
|
||||||
|
|
||||||
let project: Project?
|
let project: Project?
|
||||||
let dismiss: Bool
|
let dismiss: Bool
|
||||||
|
|
||||||
@@ -17,7 +19,7 @@ struct ProjectForm: HTML, Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some HTML {
|
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" }
|
h1(.class("text-3xl font-bold pb-6 ps-2")) { "Project" }
|
||||||
form(
|
form(
|
||||||
.class("space-y-4 p-4"),
|
.class("space-y-4 p-4"),
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ struct Sidebar: HTML {
|
|||||||
div(.class("flex")) {
|
div(.class("flex")) {
|
||||||
// TODO: Move somewhere outside of the sidebar.
|
// TODO: Move somewhere outside of the sidebar.
|
||||||
button(
|
button(
|
||||||
.class("w-full btn btn-secondary"),
|
.class("btn btn-secondary btn-block"),
|
||||||
.hx.get(route: .project(.index)),
|
.hx.get(route: .project(.index)),
|
||||||
.hx.target("body"),
|
.hx.target("body"),
|
||||||
.hx.pushURL(true),
|
.hx.pushURL(true),
|
||||||
|
|||||||
@@ -16,21 +16,17 @@ struct ProjectsTable: HTML, Sendable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some HTML {
|
var body: some HTML {
|
||||||
div {
|
div(.class("m-6")) {
|
||||||
Row {
|
Row {
|
||||||
h1(.class("text-2xl font-bold")) { "Projects" }
|
h1(.class("text-2xl font-bold")) { "Projects" }
|
||||||
div(
|
div(
|
||||||
.class("tooltip tooltip-left"),
|
.class("tooltip tooltip-left"),
|
||||||
.data("tip", value: "Add project")
|
.data("tip", value: "Add project")
|
||||||
) {
|
) {
|
||||||
button(
|
PlusButton()
|
||||||
.class("btn btn-primary w-[40px] text-2xl"),
|
.attributes(
|
||||||
.hx.get(route: .project(.form(dismiss: false))),
|
.showModal(id: ProjectForm.id)
|
||||||
.hx.target("#projectForm"),
|
)
|
||||||
.hx.swap(.outerHTML)
|
|
||||||
) {
|
|
||||||
"+"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.attributes(.class("pb-6"))
|
.attributes(.class("pb-6"))
|
||||||
@@ -75,9 +71,11 @@ extension ProjectsTable {
|
|||||||
.hx.target("closest tr")
|
.hx.target("closest tr")
|
||||||
)
|
)
|
||||||
a(
|
a(
|
||||||
.class("btn btn-success dark:text-white"),
|
.class("btn btn-success btn-circle dark:text-white"),
|
||||||
.href(route: .project(.detail(project.id, .index())))
|
.href(route: .project(.detail(project.id, .index())))
|
||||||
) { ">" }
|
) {
|
||||||
|
SVG(.chevronRight)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,26 @@ struct RoomForm: HTML, Sendable {
|
|||||||
|
|
||||||
static let id = "roomForm"
|
static let id = "roomForm"
|
||||||
|
|
||||||
|
let id: String
|
||||||
let dismiss: Bool
|
let dismiss: Bool
|
||||||
let projectID: Project.ID
|
let projectID: Project.ID
|
||||||
let room: Room?
|
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 {
|
var body: some HTML {
|
||||||
ModalForm(id: Self.id, dismiss: dismiss) {
|
ModalForm(id: id, dismiss: dismiss) {
|
||||||
h1(.class("text-3xl font-bold pb-6")) { "Room" }
|
h1(.class("text-3xl font-bold pb-6")) { "Room" }
|
||||||
// TODO: Use htmx here.
|
|
||||||
form(
|
form(
|
||||||
.class("modal-backdrop"),
|
.class("modal-backdrop"),
|
||||||
.init(name: "method", value: "dialog"),
|
.init(name: "method", value: "dialog"),
|
||||||
@@ -62,9 +74,8 @@ struct RoomForm: HTML, Sendable {
|
|||||||
.value("\(room != nil ? room!.registerCount : 1)"),
|
.value("\(room != nil ? room!.registerCount : 1)"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
div(.class("flex justify-end space-x-4")) {
|
SubmitButton()
|
||||||
SubmitButton()
|
.attributes(.class("btn-block"))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ struct RoomsView: HTML, Sendable {
|
|||||||
.class("tooltip tooltip-left"),
|
.class("tooltip tooltip-left"),
|
||||||
.data("tip", value: "Add room")
|
.data("tip", value: "Add room")
|
||||||
) {
|
) {
|
||||||
button(
|
div(.class("flex me-4")) {
|
||||||
.showModal(id: RoomForm.id),
|
PlusButton()
|
||||||
.class("btn btn-primary w-[40px] text-2xl")
|
.attributes(.showModal(id: RoomForm.id))
|
||||||
) {
|
|
||||||
"+"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,7 +30,7 @@ struct RoomsView: HTML, Sendable {
|
|||||||
|
|
||||||
div(.class("border rounded-lg mb-6")) {
|
div(.class("border rounded-lg mb-6")) {
|
||||||
Row {
|
Row {
|
||||||
div(.class("space-x-6")) {
|
div(.class("space-x-6 my-2")) {
|
||||||
Label("Sensible Heat Ratio")
|
Label("Sensible Heat Ratio")
|
||||||
if let sensibleHeatRatio {
|
if let sensibleHeatRatio {
|
||||||
Number(sensibleHeatRatio)
|
Number(sensibleHeatRatio)
|
||||||
@@ -54,27 +52,29 @@ struct RoomsView: HTML, Sendable {
|
|||||||
th { Label("Name") }
|
th { Label("Name") }
|
||||||
th { Label("Heating Load") }
|
th { Label("Heating Load") }
|
||||||
th { Label("Cooling Total") }
|
th { Label("Cooling Total") }
|
||||||
|
th { Label("Cooling Sensible") }
|
||||||
th { Label("Register Count") }
|
th { Label("Register Count") }
|
||||||
th {}
|
th {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbody {
|
tbody {
|
||||||
div(.id("rooms")) {
|
for room in rooms {
|
||||||
for room in rooms {
|
RoomRow(room: room, shr: sensibleHeatRatio)
|
||||||
RoomRow(room: room)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// TOTALS
|
// TOTALS
|
||||||
tr(.class("font-bold text-xl")) {
|
tr(.class("font-bold text-xl")) {
|
||||||
td { Label("Total") }
|
td { Label("Total") }
|
||||||
td {
|
td {
|
||||||
Number(rooms.heatingTotal)
|
Number(rooms.heatingTotal, digits: 0)
|
||||||
.attributes(.class("badge badge-outline badge-error badge-xl"))
|
.attributes(.class("badge badge-outline badge-error badge-xl"))
|
||||||
}
|
}
|
||||||
td {
|
td {
|
||||||
Number(rooms.coolingTotal)
|
Number(rooms.coolingTotal, digits: 0)
|
||||||
.attributes(
|
.attributes(.class("badge badge-outline badge-success badge-xl"))
|
||||||
.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 {}
|
||||||
td {}
|
td {}
|
||||||
@@ -88,19 +88,35 @@ struct RoomsView: HTML, Sendable {
|
|||||||
|
|
||||||
public struct RoomRow: HTML, Sendable {
|
public struct RoomRow: HTML, Sendable {
|
||||||
let room: Room
|
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 {
|
public var body: some HTML {
|
||||||
tr(.id("\(room.id)")) {
|
tr(.id("roomRow_\(room.name)")) {
|
||||||
td { room.name }
|
td { room.name }
|
||||||
td {
|
td {
|
||||||
Number(room.heatingLoad)
|
Number(room.heatingLoad, digits: 0)
|
||||||
.attributes(.class("text-error"))
|
.attributes(.class("text-error"))
|
||||||
}
|
}
|
||||||
td {
|
td {
|
||||||
Number(room.coolingTotal)
|
Number(room.coolingTotal, digits: 0)
|
||||||
.attributes(.class("text-success"))
|
.attributes(.class("text-success"))
|
||||||
}
|
}
|
||||||
// FIX: Add cooling sensible.
|
td {
|
||||||
|
Number(coolingSensible, digits: 0)
|
||||||
|
.attributes(.class("text-info"))
|
||||||
|
}
|
||||||
td {
|
td {
|
||||||
Number(room.registerCount)
|
Number(room.registerCount)
|
||||||
}
|
}
|
||||||
@@ -115,15 +131,15 @@ struct RoomsView: HTML, Sendable {
|
|||||||
)
|
)
|
||||||
EditButton()
|
EditButton()
|
||||||
.attributes(
|
.attributes(
|
||||||
.hx.get(
|
.showModal(id: "roomForm_\(room.name)")
|
||||||
route: .project(
|
|
||||||
.detail(room.projectID, .rooms(.form(id: room.id, dismiss: false)))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
.hx.target("#roomForm"),
|
|
||||||
.hx.swap(.outerHTML)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
RoomForm(
|
||||||
|
id: "roomForm_\(room.name)",
|
||||||
|
dismiss: true,
|
||||||
|
projectID: room.projectID,
|
||||||
|
room: room
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,4 +183,13 @@ extension Array where Element == Room {
|
|||||||
var coolingTotal: Double {
|
var coolingTotal: Double {
|
||||||
reduce(into: 0) { $0 += $1.coolingTotal }
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ struct LoginForm: HTML, Sendable {
|
|||||||
input(
|
input(
|
||||||
.type(.text), .required, .placeholder("Username"),
|
.type(.text), .required, .placeholder("Username"),
|
||||||
.name("username"), .id("username"),
|
.name("username"), .id("username"),
|
||||||
.minlength("3"), .pattern(.username)
|
.minlength("3"), .pattern(.username),
|
||||||
|
.autofocus
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
div(.class("validator-hint hidden")) {
|
div(.class("validator-hint hidden")) {
|
||||||
@@ -48,7 +49,7 @@ struct LoginForm: HTML, Sendable {
|
|||||||
SVG(.email)
|
SVG(.email)
|
||||||
input(
|
input(
|
||||||
.type(.email), .placeholder("Email"), .required,
|
.type(.email), .placeholder("Email"), .required,
|
||||||
.name("email"), .id("email"),
|
.name("email"), .id("email"), .autofocus
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
div(.class("validator-hint hidden")) { "Enter valid email address." }
|
div(.class("validator-hint hidden")) { "Enter valid email address." }
|
||||||
|
|||||||
Reference in New Issue
Block a user