feat: Adds quick calculation views, need to add buttons / links in navbar / home page.
This commit is contained in:
@@ -53,6 +53,13 @@ extension ViewController: DependencyKey {
|
||||
|
||||
extension ViewController.Request {
|
||||
|
||||
var isLoggedIn: Bool {
|
||||
if (try? currentUser()) != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func currentUser() throws -> User {
|
||||
@Dependency(\.auth.currentUser) var currentUser
|
||||
return try currentUser()
|
||||
|
||||
@@ -3,6 +3,7 @@ import DatabaseClient
|
||||
import Dependencies
|
||||
import Elementary
|
||||
import Foundation
|
||||
import ManualDClient
|
||||
import ManualDCore
|
||||
import PdfClient
|
||||
import ProjectClient
|
||||
@@ -38,7 +39,9 @@ extension ViewController.Request {
|
||||
// }
|
||||
// }
|
||||
// return try! await pdfClient.html(.mock())
|
||||
return EmptyHTML()
|
||||
return await view {
|
||||
TestPage()
|
||||
}
|
||||
case .login(let route):
|
||||
switch route {
|
||||
case .index(let next):
|
||||
@@ -93,6 +96,9 @@ extension ViewController.Request {
|
||||
case .project(let route):
|
||||
return await route.renderView(on: self)
|
||||
|
||||
case .quickCalc(let route):
|
||||
return await route.renderView(on: self)
|
||||
|
||||
case .user(let route):
|
||||
return await route.renderView(on: self)
|
||||
}
|
||||
@@ -705,3 +711,33 @@ extension SiteRoute.View.UserRoute.Profile {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SiteRoute.View.QuickCalcRoute {
|
||||
|
||||
func renderView(
|
||||
on request: ViewController.Request
|
||||
) async -> AnySendableHTML {
|
||||
@Dependency(\.manualD) var manualD
|
||||
|
||||
switch self {
|
||||
case .index:
|
||||
return await request.view {
|
||||
QuickCalcView(
|
||||
isLoggedIn: request.isLoggedIn
|
||||
)
|
||||
}
|
||||
case .submit(let form):
|
||||
return await ResultView {
|
||||
let ductSize = try await manualD.ductSize(cfm: form.cfm, frictionRate: form.frictionRate)
|
||||
var rectangularSize: ManualDClient.RectangularSize? = nil
|
||||
if let height = form.height {
|
||||
rectangularSize = try await manualD.rectangularSize(
|
||||
round: ductSize.finalSize, height: height)
|
||||
}
|
||||
return (ductSize, rectangularSize)
|
||||
} onSuccess: { (ductSize, rectangularSize) in
|
||||
QuickCalcView.Result(ductSize: ductSize, rectangularSize: rectangularSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import Elementary
|
||||
import ManualDCore
|
||||
import Styleguide
|
||||
|
||||
// TODO: Have form hold onto equipment info model to edit.
|
||||
struct EquipmentInfoForm: HTML, Sendable {
|
||||
|
||||
static let id = "equipmentForm"
|
||||
|
||||
@@ -14,6 +14,13 @@ struct Navbar: HTML, Sendable {
|
||||
self.userProfile = userProfile
|
||||
}
|
||||
|
||||
var homeRoute: SiteRoute.View {
|
||||
if userProfile {
|
||||
return .project(.index)
|
||||
}
|
||||
return .home
|
||||
}
|
||||
|
||||
var body: some HTML<HTMLTag.nav> {
|
||||
nav(
|
||||
.class(
|
||||
@@ -37,7 +44,7 @@ struct Navbar: HTML, Sendable {
|
||||
|
||||
a(
|
||||
.class("flex w-fit h-fit text-xl items-end px-4 py-2"),
|
||||
.href(route: .project(.index))
|
||||
.href(route: homeRoute)
|
||||
) {
|
||||
img(
|
||||
.src("/images/mand_logo_sm.webp"),
|
||||
@@ -48,11 +55,11 @@ struct Navbar: HTML, Sendable {
|
||||
.tooltip("Home", position: .right)
|
||||
}
|
||||
if userProfile {
|
||||
// TODO: Make dropdown
|
||||
div(.class("flex-none dropdown dropdown-end dropdown-hover")) {
|
||||
div(.class("btn m-1"), .tabindex(0), .role("button")) {
|
||||
SVG(.circleUser)
|
||||
}
|
||||
.navButton()
|
||||
ul(
|
||||
.tabindex(-1),
|
||||
.class("dropdown-content menu bg-base-200 rounded-box z-1 w-52 py-2 shadow-sm")
|
||||
|
||||
141
Sources/ViewController/Views/QuickCalc/Index.swift
Normal file
141
Sources/ViewController/Views/QuickCalc/Index.swift
Normal file
@@ -0,0 +1,141 @@
|
||||
import Dependencies
|
||||
import Elementary
|
||||
import ElementaryHTMX
|
||||
import Foundation
|
||||
import ManualDClient
|
||||
import ManualDCore
|
||||
import Styleguide
|
||||
|
||||
struct QuickCalcView: HTML, Sendable {
|
||||
|
||||
let isLoggedIn: Bool
|
||||
|
||||
init(isLoggedIn: Bool = false) {
|
||||
self.isLoggedIn = isLoggedIn
|
||||
}
|
||||
|
||||
var body: some HTML {
|
||||
div {
|
||||
Navbar(
|
||||
sidebarToggle: false,
|
||||
userProfile: isLoggedIn
|
||||
)
|
||||
div(.class("flex justify-center items-center px-10")) {
|
||||
div(
|
||||
.class(
|
||||
"""
|
||||
bg-base-300 rounded-3xl shadow-3xl
|
||||
p-6 w-full
|
||||
"""
|
||||
)
|
||||
) {
|
||||
div(.class("flex space-x-6 items-center text-4xl")) {
|
||||
SVG(.calculator)
|
||||
h1(.class("text-4xl font-bold me-10")) {
|
||||
"Duct Size"
|
||||
}
|
||||
}
|
||||
|
||||
p(.class("text-primary font-bold italic")) {
|
||||
"Calculate duct size for the given parameters"
|
||||
}
|
||||
|
||||
form(
|
||||
.class("space-y-4 mt-6"),
|
||||
.hx.post(route: .quickCalc(.index)),
|
||||
.hx.target("#\(Result.id)"),
|
||||
.hx.swap(.outerHTML)
|
||||
) {
|
||||
LabeledInput(
|
||||
"CFM",
|
||||
.name("cfm"),
|
||||
.type(.number),
|
||||
.placeholder("1000"),
|
||||
.required,
|
||||
.autofocus
|
||||
)
|
||||
|
||||
LabeledInput(
|
||||
"Friction Rate",
|
||||
.name("frictionRate"),
|
||||
.value("0.06"),
|
||||
.required,
|
||||
.type(.number),
|
||||
.min("0.01"),
|
||||
.step("0.01")
|
||||
)
|
||||
|
||||
LabeledInput(
|
||||
"Height",
|
||||
.name("height"),
|
||||
.type(.number),
|
||||
.placeholder("Height (Optional)"),
|
||||
)
|
||||
|
||||
SubmitButton()
|
||||
.attributes(.class("btn-block mt-6"))
|
||||
}
|
||||
|
||||
// Populate when submitted
|
||||
div(.id(Result.id)) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Result: HTML, Sendable {
|
||||
static let id = "resultView"
|
||||
|
||||
let ductSize: ManualDClient.DuctSize
|
||||
let rectangularSize: ManualDClient.RectangularSize?
|
||||
|
||||
var body: some HTML<HTMLTag.div> {
|
||||
div(
|
||||
.id(Self.id),
|
||||
.class(
|
||||
"""
|
||||
border-2 border-accent rounded-lg shadow-lg
|
||||
w-full p-6 my-6
|
||||
"""
|
||||
)
|
||||
) {
|
||||
div(.class("flex justify-between p-4")) {
|
||||
h2(.class("text-3xl font-bold")) { "Result" }
|
||||
button(
|
||||
.class("btn btn-primary"),
|
||||
.hx.get(route: .quickCalc(.index)),
|
||||
.hx.target("body"),
|
||||
.hx.swap(.outerHTML)
|
||||
) {
|
||||
"Reset"
|
||||
}
|
||||
.tooltip("Reset form", position: .left)
|
||||
}
|
||||
|
||||
table(.class("table table-zebra text-lg font-bold")) {
|
||||
tbody {
|
||||
tr {
|
||||
td { Label("Calculated Size") }
|
||||
td { Number(ductSize.calculatedSize, digits: 2) }
|
||||
}
|
||||
tr {
|
||||
td { Label("Final Size") }
|
||||
td { Number(ductSize.finalSize) }
|
||||
}
|
||||
tr {
|
||||
td { Label("Flex Size") }
|
||||
td { Number(ductSize.flexSize) }
|
||||
}
|
||||
if let rectangularSize {
|
||||
tr {
|
||||
td { Label("Rectangular Size") }
|
||||
td { "\(rectangularSize.width) x \(rectangularSize.height)" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import Dependencies
|
||||
import Elementary
|
||||
import Foundation
|
||||
import ManualDClient
|
||||
import ManualDCore
|
||||
import Styleguide
|
||||
|
||||
@@ -8,24 +9,77 @@ struct TestPage: HTML, Sendable {
|
||||
// let ductSizes: DuctSizes
|
||||
|
||||
var body: some HTML {
|
||||
div {}
|
||||
// div(.class("overflow-auto")) {
|
||||
// DuctSizingView.TrunkTable(ductSizes: ductSizes)
|
||||
//
|
||||
// Row {
|
||||
// h2(.class("text-2xl font-bold")) { "Trunk Sizes" }
|
||||
//
|
||||
// PlusButton()
|
||||
// .attributes(
|
||||
// .class("me-6"),
|
||||
// .showModal(id: TrunkSizeForm.id())
|
||||
// )
|
||||
// }
|
||||
// .attributes(.class("mt-6"))
|
||||
//
|
||||
// div(.class("divider -mt-2")) {}
|
||||
//
|
||||
// DuctSizingView.TrunkTable(ductSizes: ductSizes)
|
||||
// }
|
||||
div {
|
||||
Navbar(sidebarToggle: false, userProfile: false)
|
||||
div(.class("flex justify-center items-center px-10")) {
|
||||
div(
|
||||
.class(
|
||||
"""
|
||||
bg-base-300 rounded-3xl shadow-3xl
|
||||
p-6 w-full
|
||||
"""
|
||||
)
|
||||
) {
|
||||
div(.class("flex space-x-6 items-center text-4xl")) {
|
||||
SVG(.calculator)
|
||||
h1(.class("text-4xl font-bold me-10")) {
|
||||
"Duct Size"
|
||||
}
|
||||
}
|
||||
|
||||
p(.class("text-primary font-bold italic")) {
|
||||
"Calculate duct size for the given parameters"
|
||||
}
|
||||
|
||||
form(
|
||||
.class("space-y-4 mt-6"),
|
||||
.action("#")
|
||||
) {
|
||||
LabeledInput(
|
||||
"CFM",
|
||||
.required,
|
||||
.type(.number),
|
||||
.placeholder("1000"),
|
||||
.name("cfm")
|
||||
)
|
||||
|
||||
LabeledInput(
|
||||
"Friction Rate",
|
||||
.value("0.06"),
|
||||
.required,
|
||||
.type(.number),
|
||||
.name("frictionRate")
|
||||
)
|
||||
|
||||
LabeledInput(
|
||||
"Height",
|
||||
.required,
|
||||
.type(.number),
|
||||
.placeholder("Height (Optional)"),
|
||||
.name("frictionRate")
|
||||
)
|
||||
|
||||
SubmitButton()
|
||||
.attributes(.class("btn-block mt-6"))
|
||||
}
|
||||
}
|
||||
|
||||
// Populate when submitted
|
||||
div(.id(Result.id)) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Result: HTML, Sendable {
|
||||
static let id = "resultView"
|
||||
|
||||
let ductSize: ManualDClient.DuctSize
|
||||
let rectangularSize: ManualDClient.RectangularSize?
|
||||
|
||||
var body: some HTML<HTMLTag.div> {
|
||||
div(.id(Self.id)) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user