feat: Better modal form using dialog, some forms still need updated to use it effectively.
This commit is contained in:
@@ -179,7 +179,7 @@ extension SiteRoute.View.ProjectRoute.RoomRoute {
|
||||
|
||||
case .submit(let form):
|
||||
request.logger.debug("New room form submitted.")
|
||||
let _ = try await database.rooms.create(.init(form: form, projectID: projectID))
|
||||
let _ = try await database.rooms.create(form)
|
||||
return request.view {
|
||||
ProjectView(projectID: projectID, activeTab: .rooms)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public struct MainPage<Inner: HTML>: SendableHTMLDocument where Inner: Sendable
|
||||
}
|
||||
|
||||
public var body: some HTML {
|
||||
div {
|
||||
div(.class("h-screen w-full")) {
|
||||
inner
|
||||
}
|
||||
script(.src("https://unpkg.com/lucide@latest")) {}
|
||||
|
||||
@@ -18,9 +18,7 @@ struct ProjectDetail: HTML, Sendable {
|
||||
h1(.class("text-2xl font-bold")) { "Project" }
|
||||
EditButton()
|
||||
.attributes(
|
||||
.hx.get(route: .project(.form(id: project.id, dismiss: false))),
|
||||
.hx.target("#projectForm"),
|
||||
.hx.swap(.outerHTML)
|
||||
.on(.click, "projectForm.showModal()")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -54,6 +52,6 @@ struct ProjectDetail: HTML, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
ProjectForm(dismiss: true)
|
||||
ProjectForm(dismiss: true, project: project)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ struct ProjectForm: HTML, Sendable {
|
||||
div {
|
||||
label(.for("name")) { "Name" }
|
||||
Input(id: "name", placeholder: "Name")
|
||||
.attributes(.type(.text), .required, .autofocus)
|
||||
.attributes(.type(.text), .required, .autofocus, .value(project?.name))
|
||||
}
|
||||
div {
|
||||
label(.for("streetAddress")) { "Address" }
|
||||
@@ -57,14 +57,9 @@ struct ProjectForm: HTML, Sendable {
|
||||
.attributes(.type(.text), .required, .value(project?.zipCode))
|
||||
}
|
||||
|
||||
div(.class("flex justify-end space-x-6")) {
|
||||
CancelButton()
|
||||
.attributes(
|
||||
.hx.get(route: .project(.form(dismiss: true))),
|
||||
.hx.target("#projectForm"),
|
||||
.hx.swap(.outerHTML)
|
||||
)
|
||||
div(.class("flex mt-6")) {
|
||||
SubmitButton()
|
||||
.attributes(.class("btn-block"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +67,7 @@ extension ProjectsTable {
|
||||
td { "\(project.name)" }
|
||||
td { "\(project.streetAddress)" }
|
||||
td {
|
||||
Row {
|
||||
div {}
|
||||
div(.class("flex justify-end space-x-6")) {
|
||||
TrashButton()
|
||||
.attributes(
|
||||
.hx.delete(route: .project(.delete(id: project.id))),
|
||||
|
||||
@@ -17,6 +17,8 @@ struct RoomForm: HTML, Sendable {
|
||||
h1(.class("text-3xl font-bold pb-6")) { "Room" }
|
||||
// TODO: Use htmx here.
|
||||
form(
|
||||
.class("modal-backdrop"),
|
||||
.init(name: "method", value: "dialog"),
|
||||
room == nil
|
||||
? .hx.post(route: .project(.detail(projectID, .rooms(.index))))
|
||||
: .hx.patch(route: .project(.detail(projectID, .rooms(.index)))),
|
||||
@@ -41,11 +43,16 @@ struct RoomForm: HTML, Sendable {
|
||||
.attributes(.type(.number), .required, .min("0"), .value(room?.heatingLoad))
|
||||
}
|
||||
div {
|
||||
label(.for("coolingLoad")) { "Cooling Load:" }
|
||||
Input(id: "coolingLoad", placeholder: "Cooling Load")
|
||||
.attributes(.type(.number), .required, .min("0"), .value(room?.coolingLoad))
|
||||
label(.for("coolingTotal")) { "Cooling Total:" }
|
||||
Input(id: "coolingTotal", placeholder: "Cooling Total")
|
||||
.attributes(.type(.number), .required, .min("0"), .value(room?.coolingTotal))
|
||||
}
|
||||
div {
|
||||
label(.for("coolingSensible")) { "Cooling Sensible:" }
|
||||
Input(id: "coolingSensible", placeholder: "Cooling Sensible (Optional)")
|
||||
.attributes(.type(.number), .min("0"), .value(room?.coolingSensible))
|
||||
}
|
||||
div(.class("pb-6")) {
|
||||
label(.for("registerCount")) { "Registers:" }
|
||||
Input(id: "registerCount", placeholder: "Register Count")
|
||||
.attributes(
|
||||
@@ -53,20 +60,9 @@ struct RoomForm: HTML, Sendable {
|
||||
.value("\(room != nil ? room!.registerCount : 1)"),
|
||||
)
|
||||
}
|
||||
Row {
|
||||
// Force button to the right, probably a better way.
|
||||
div {}
|
||||
div(.class("space-x-4")) {
|
||||
CancelButton()
|
||||
.attributes(
|
||||
.hx.get(route: .project(.detail(projectID, .rooms(.form(dismiss: true))))),
|
||||
.hx.target("#roomForm"),
|
||||
.hx.swap(.outerHTML)
|
||||
)
|
||||
SubmitButton()
|
||||
}
|
||||
div(.class("flex justify-end space-x-4")) {
|
||||
SubmitButton()
|
||||
}
|
||||
.attributes(.class("py-4"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,10 @@ struct RoomsView: HTML, Sendable {
|
||||
.data("tip", value: "Add room")
|
||||
) {
|
||||
button(
|
||||
.hx.get(route: .project(.detail(projectID, .rooms(.form(dismiss: false))))),
|
||||
.hx.target("#roomForm"),
|
||||
.hx.swap(.outerHTML),
|
||||
// .hx.get(route: .project(.detail(projectID, .rooms(.form(dismiss: false))))),
|
||||
// .hx.target("#roomForm"),
|
||||
// .hx.swap(.outerHTML),
|
||||
.on(.click, "roomForm.showModal()"),
|
||||
.class("btn btn-primary w-[40px] text-2xl")
|
||||
) {
|
||||
"+"
|
||||
@@ -81,9 +82,10 @@ struct RoomsView: HTML, Sendable {
|
||||
.attributes(.class("text-error"))
|
||||
}
|
||||
td {
|
||||
Number(room.coolingLoad)
|
||||
Number(room.coolingTotal)
|
||||
.attributes(.class("text-success"))
|
||||
}
|
||||
// FIX: Add cooling sensible.
|
||||
td {
|
||||
Number(room.registerCount)
|
||||
}
|
||||
@@ -120,6 +122,6 @@ extension Array where Element == Room {
|
||||
}
|
||||
|
||||
var coolingTotal: Double {
|
||||
reduce(into: 0) { $0 += $1.coolingLoad }
|
||||
reduce(into: 0) { $0 += $1.coolingTotal }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,22 +13,20 @@ struct LoginForm: HTML, Sendable {
|
||||
}
|
||||
|
||||
var body: some HTML {
|
||||
div(
|
||||
.id("loginForm"),
|
||||
.class("flex items-center justify-center")
|
||||
) {
|
||||
ModalForm(id: "loginForm", closeButton: false, dismiss: false) {
|
||||
h1(.class("text-2xl font-bold mb-6")) { style.title }
|
||||
|
||||
form(
|
||||
.method(.post)
|
||||
.method(.post),
|
||||
.class("space-y-4")
|
||||
) {
|
||||
|
||||
if let next {
|
||||
input(.class("hidden"), .name("next"), .value(next))
|
||||
}
|
||||
|
||||
fieldset(.class("fieldset bg-base-200 border-base-300 rounded-box w-xl border p-4")) {
|
||||
legend(.class("fieldset-legend")) { style.title }
|
||||
|
||||
if style == .signup {
|
||||
if style == .signup {
|
||||
div {
|
||||
label(.class("input validator w-full")) {
|
||||
SVG(.user)
|
||||
input(
|
||||
@@ -43,7 +41,9 @@ struct LoginForm: HTML, Sendable {
|
||||
"Must be at least 3 characters"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
label(.class("input validator w-full")) {
|
||||
SVG(.email)
|
||||
input(
|
||||
@@ -52,7 +52,9 @@ struct LoginForm: HTML, Sendable {
|
||||
)
|
||||
}
|
||||
div(.class("validator-hint hidden")) { "Enter valid email address." }
|
||||
}
|
||||
|
||||
div {
|
||||
label(.class("input validator w-full")) {
|
||||
SVG(.key)
|
||||
input(
|
||||
@@ -61,8 +63,10 @@ struct LoginForm: HTML, Sendable {
|
||||
.name("password"), .id("password"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if style == .signup {
|
||||
if style == .signup {
|
||||
div {
|
||||
label(.class("input validator w-full")) {
|
||||
SVG(.key)
|
||||
input(
|
||||
@@ -84,10 +88,15 @@ struct LoginForm: HTML, Sendable {
|
||||
"At least one uppercase letter"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button(.class("btn btn-secondary mt-4")) { style.title }
|
||||
div(.class("flex")) {
|
||||
button(.class("btn btn-secondary mt-4 w-full")) { style.title }
|
||||
}
|
||||
|
||||
div(.class("flex justify-center")) {
|
||||
a(
|
||||
.class("btn btn-link mt-4"),
|
||||
.class("btn btn-link"),
|
||||
.href(route: style == .signup ? .login(.index(next: next)) : .signup(.index))
|
||||
) {
|
||||
style == .login ? "Sign Up" : "Login"
|
||||
|
||||
Reference in New Issue
Block a user