WIP: Adds a modal form view and integrates into current forms.
This commit is contained in:
37
Sources/Styleguide/ModalForm.swift
Normal file
37
Sources/Styleguide/ModalForm.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
import Elementary
|
||||
|
||||
public struct ModalForm<T: HTML>: HTML, Sendable where T: Sendable {
|
||||
|
||||
let dismiss: Bool
|
||||
let id: String
|
||||
let inner: T
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
dismiss: Bool,
|
||||
@HTMLBuilder inner: () -> T
|
||||
) {
|
||||
self.dismiss = dismiss
|
||||
self.id = id
|
||||
self.inner = inner()
|
||||
}
|
||||
|
||||
public var body: some HTML {
|
||||
if dismiss {
|
||||
div(.id(id)) {}
|
||||
} else {
|
||||
div(
|
||||
.id(id),
|
||||
.class(
|
||||
"""
|
||||
fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800
|
||||
bg-gray-200 border border-gray-400
|
||||
rounded-lg shadow-lg mx-10
|
||||
"""
|
||||
)
|
||||
) {
|
||||
inner
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,14 +24,11 @@ extension SiteRoute.View.ProjectRoute {
|
||||
func renderView(isHtmxRequest: Bool) async throws -> AnySendableHTML {
|
||||
switch self {
|
||||
case .index:
|
||||
return MainPage {
|
||||
return MainPage(active: .projects) {
|
||||
ProjectView(project: .mock)
|
||||
}
|
||||
case .form(let dismiss):
|
||||
guard !dismiss else {
|
||||
return div(.id("projectForm")) {}
|
||||
}
|
||||
return ProjectForm()
|
||||
return ProjectForm(dismiss: dismiss)
|
||||
|
||||
case .create:
|
||||
return mainPage
|
||||
@@ -48,7 +45,7 @@ extension SiteRoute.View.RoomRoute {
|
||||
}
|
||||
return RoomForm()
|
||||
case .index:
|
||||
return MainPage {
|
||||
return MainPage(active: .rooms) {
|
||||
RoomsView(rooms: Room.mocks)
|
||||
}
|
||||
}
|
||||
@@ -59,19 +56,16 @@ extension SiteRoute.View.FrictionRateRoute {
|
||||
func renderView(isHtmxRequest: Bool) async throws -> AnySendableHTML {
|
||||
switch self {
|
||||
case .index:
|
||||
return MainPage {
|
||||
return MainPage(active: .frictionRate) {
|
||||
FrictionRateView()
|
||||
}
|
||||
case .form(let type, let dismiss):
|
||||
guard !dismiss else {
|
||||
return div(.id(type.id)) {}
|
||||
}
|
||||
// FIX: Forms need to reference existing items.
|
||||
switch type {
|
||||
case .equipmentInfo:
|
||||
return EquipmentForm()
|
||||
return EquipmentForm(dismiss: dismiss)
|
||||
case .componentPressureLoss:
|
||||
return ComponentLossForm()
|
||||
return ComponentLossForm(dismiss: dismiss)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,14 +87,11 @@ extension SiteRoute.View.EffectiveLengthRoute {
|
||||
func renderView(isHtmxRequest: Bool) async throws -> AnySendableHTML {
|
||||
switch self {
|
||||
case .index:
|
||||
return MainPage {
|
||||
return MainPage(active: .effectiveLength) {
|
||||
EffectiveLengthsView(effectiveLengths: EffectiveLength.mocks)
|
||||
}
|
||||
case .form(let dismiss):
|
||||
guard !dismiss else {
|
||||
return div(.id("effectiveLengthForm")) {}
|
||||
}
|
||||
return EffectiveLengthForm()
|
||||
return EffectiveLengthForm(dismiss: dismiss)
|
||||
|
||||
case .field(let type):
|
||||
switch type {
|
||||
@@ -114,7 +105,7 @@ extension SiteRoute.View.EffectiveLengthRoute {
|
||||
}
|
||||
|
||||
private let mainPage: AnySendableHTML = {
|
||||
MainPage {
|
||||
MainPage(active: .projects) {
|
||||
div {
|
||||
h1 { "It works!" }
|
||||
}
|
||||
|
||||
@@ -4,18 +4,20 @@ import ManualDCore
|
||||
import Styleguide
|
||||
|
||||
struct EffectiveLengthForm: HTML, Sendable {
|
||||
let dismiss: Bool
|
||||
|
||||
var body: some HTML {
|
||||
div(
|
||||
.id("effectiveLengthForm"),
|
||||
.class(
|
||||
"""
|
||||
fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800
|
||||
bg-gray-200 border border-gray-400
|
||||
rounded-lg shadow-lg mx-10
|
||||
"""
|
||||
)
|
||||
) {
|
||||
// div(
|
||||
// .id("effectiveLengthForm"),
|
||||
// .class(
|
||||
// """
|
||||
// fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800
|
||||
// bg-gray-200 border border-gray-400
|
||||
// rounded-lg shadow-lg mx-10
|
||||
// """
|
||||
// )
|
||||
// ) {
|
||||
ModalForm(id: "effectiveLengthForm", dismiss: dismiss) {
|
||||
h1(.class("text-2xl font-bold")) { "Effective Length" }
|
||||
form(.class("space-y-4 p-4")) {
|
||||
div {
|
||||
@@ -25,7 +27,6 @@ struct EffectiveLengthForm: HTML, Sendable {
|
||||
}
|
||||
div {
|
||||
label(.for("type")) { "Type" }
|
||||
// FIX: Add select field.
|
||||
select(
|
||||
.id("type"), .name("type"),
|
||||
.class("w-full border rounded-md")
|
||||
|
||||
@@ -4,17 +4,10 @@ import ManualDCore
|
||||
import Styleguide
|
||||
|
||||
struct ComponentLossForm: HTML, Sendable {
|
||||
let dismiss: Bool
|
||||
|
||||
var body: some HTML {
|
||||
div(
|
||||
.id("componentLossForm"),
|
||||
.class(
|
||||
"""
|
||||
fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800
|
||||
bg-gray-200 border border-gray-400
|
||||
rounded-lg shadow-lg mx-10
|
||||
"""
|
||||
)
|
||||
) {
|
||||
ModalForm(id: "componentLossForm", dismiss: dismiss) {
|
||||
h1(.class("text-2xl font-bold")) { "Component Loss" }
|
||||
form(.class("space-y-4 p-4")) {
|
||||
div {
|
||||
|
||||
@@ -5,17 +5,10 @@ import Styleguide
|
||||
// TODO: Have form hold onto equipment info model to edit.
|
||||
struct EquipmentForm: HTML, Sendable {
|
||||
|
||||
let dismiss: Bool
|
||||
|
||||
var body: some HTML {
|
||||
div(
|
||||
.id("equipmentForm"),
|
||||
.class(
|
||||
"""
|
||||
fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800
|
||||
bg-gray-200 border border-gray-400
|
||||
rounded-lg shadow-lg mx-10
|
||||
"""
|
||||
)
|
||||
) {
|
||||
ModalForm(id: "equipmentForm", dismiss: dismiss) {
|
||||
h1(.class("text-3xl font-bold pb-6 ps-2")) { "Equipment Info" }
|
||||
form(.class("space-y-4 p-4")) {
|
||||
div {
|
||||
|
||||
@@ -4,8 +4,10 @@ public struct MainPage<Inner: HTML>: SendableHTMLDocument where Inner: Sendable
|
||||
public var title: String { "Manual-D" }
|
||||
public var lang: String { "en" }
|
||||
let inner: Inner
|
||||
let activeTab: Sidebar.ActiveTab
|
||||
|
||||
init(_ inner: () -> Inner) {
|
||||
init(active activeTab: Sidebar.ActiveTab, _ inner: () -> Inner) {
|
||||
self.activeTab = activeTab
|
||||
self.inner = inner()
|
||||
}
|
||||
|
||||
@@ -22,7 +24,7 @@ public struct MainPage<Inner: HTML>: SendableHTMLDocument where Inner: Sendable
|
||||
public var body: some HTML {
|
||||
div(.class("bg-white dark:bg-gray-800 dark:text-white")) {
|
||||
div(.class("flex flex-row")) {
|
||||
Sidebar()
|
||||
Sidebar(active: activeTab)
|
||||
main(.class("flex flex-col h-screen w-full")) {
|
||||
inner
|
||||
}
|
||||
|
||||
@@ -6,24 +6,18 @@ import Styleguide
|
||||
struct ProjectForm: HTML, Sendable {
|
||||
|
||||
let project: Project?
|
||||
let dismiss: Bool
|
||||
|
||||
init(
|
||||
dismiss: Bool,
|
||||
project: Project? = nil
|
||||
) {
|
||||
self.dismiss = dismiss
|
||||
self.project = project
|
||||
}
|
||||
|
||||
var body: some HTML {
|
||||
div(
|
||||
.id("projectForm"),
|
||||
.class(
|
||||
"""
|
||||
fixed top-40 left-[25vw] w-1/2 z-50 text-gray-800
|
||||
bg-gray-200 border border-gray-400
|
||||
rounded-lg shadow-lg mx-10
|
||||
"""
|
||||
)
|
||||
) {
|
||||
ModalForm(id: "projectForm", dismiss: dismiss) {
|
||||
h1(.class("text-3xl font-bold pb-6 ps-2")) { "Project" }
|
||||
form(.class("space-y-4 p-4")) {
|
||||
div {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import Elementary
|
||||
import ManualDCore
|
||||
import Styleguide
|
||||
|
||||
// TODO: Need to add active to sidebar links.
|
||||
struct Sidebar: HTML {
|
||||
|
||||
let active: ActiveTab
|
||||
|
||||
var body: some HTML {
|
||||
aside(
|
||||
.class(
|
||||
@@ -14,12 +17,20 @@ struct Sidebar: HTML {
|
||||
"""
|
||||
)
|
||||
) {
|
||||
row(title: "Project", icon: .mapPin, href: "/projects")
|
||||
row(title: "Rooms", icon: .doorClosed, href: "/rooms")
|
||||
row(title: "Equivalent Lengths", icon: .rulerDimensionLine, href: "/effective-lengths")
|
||||
row(title: "Friction Rate", icon: .squareFunction, href: "/friction-rate")
|
||||
.attributes(.data("active", value: "true"))
|
||||
row(title: "Project", icon: .mapPin, route: .project(.index))
|
||||
.attributes(.data("active", value: active == .projects ? "true" : "false"))
|
||||
|
||||
row(title: "Rooms", icon: .doorClosed, route: .room(.index))
|
||||
.attributes(.data("active", value: active == .rooms ? "true" : "false"))
|
||||
|
||||
row(title: "Equivalent Lengths", icon: .rulerDimensionLine, route: .effectiveLength(.index))
|
||||
.attributes(.data("active", value: active == .effectiveLength ? "true" : "false"))
|
||||
|
||||
row(title: "Friction Rate", icon: .squareFunction, route: .frictionRate(.index))
|
||||
.attributes(.data("active", value: active == .frictionRate ? "true" : "false"))
|
||||
|
||||
row(title: "Duct Sizes", icon: .wind, href: "#")
|
||||
.attributes(.data("active", value: active == .ductSizing ? "true" : "false"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +57,22 @@ struct Sidebar: HTML {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func row(
|
||||
title: String,
|
||||
icon: Icon.Key,
|
||||
route: SiteRoute.View
|
||||
) -> some HTML<HTMLTag.a> {
|
||||
row(title: title, icon: icon, href: SiteRoute.View.router.path(for: route))
|
||||
}
|
||||
}
|
||||
|
||||
extension Sidebar {
|
||||
enum ActiveTab: Equatable, Sendable {
|
||||
case projects
|
||||
case rooms
|
||||
case effectiveLength
|
||||
case frictionRate
|
||||
case ductSizing
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user