diff --git a/Sources/DatabaseClient/EffectiveLength.swift b/Sources/DatabaseClient/EffectiveLength.swift index cf72d10..1f11cd5 100644 --- a/Sources/DatabaseClient/EffectiveLength.swift +++ b/Sources/DatabaseClient/EffectiveLength.swift @@ -93,6 +93,8 @@ extension EffectiveLength { } } +// TODO: Add total effective length field so that we can lookup / compare which one is +// the longest for a given project. final class EffectiveLengthModel: Model, @unchecked Sendable { static let schema = "effective_length" diff --git a/Sources/ManualDCore/Routes/ViewRoute.swift b/Sources/ManualDCore/Routes/ViewRoute.swift index 1d947c6..e36de9a 100644 --- a/Sources/ManualDCore/Routes/ViewRoute.swift +++ b/Sources/ManualDCore/Routes/ViewRoute.swift @@ -132,6 +132,7 @@ extension SiteRoute.View.FrictionRateRoute { extension SiteRoute.View { public enum EffectiveLengthRoute: Equatable, Sendable { + case field(FieldType) case form(dismiss: Bool = false) case index @@ -152,6 +153,23 @@ extension SiteRoute.View { Field("dismiss", default: false) { Bool.parser() } } } + Route(.case(Self.field)) { + Path { + rootPath + "field" + } + Method.get + Query { + Field("type") { FieldType.parser() } + } + } } } } + +extension SiteRoute.View.EffectiveLengthRoute { + public enum FieldType: String, CaseIterable, Equatable, Sendable { + case straightLength + case group + } +} diff --git a/Sources/Styleguide/Input.swift b/Sources/Styleguide/Input.swift index c28fee0..4be20ba 100644 --- a/Sources/Styleguide/Input.swift +++ b/Sources/Styleguide/Input.swift @@ -1,10 +1,28 @@ import Elementary public struct Input: HTML, Sendable { - let id: String + + let id: String? let name: String? let placeholder: String + private var _name: String { + guard let name else { + return id ?? "" + } + return name + } + + init( + id: String? = nil, + name: String? = nil, + placeholder: String + ) { + self.id = id + self.name = name + self.placeholder = placeholder + } + public init( id: String, name: String? = nil, @@ -15,9 +33,16 @@ public struct Input: HTML, Sendable { self.placeholder = placeholder } + public init( + name: String, + placeholder: String + ) { + self.init(id: nil, name: name, placeholder: placeholder) + } + public var body: some HTML { input( - .id(id), .name(name ?? id), .placeholder(placeholder), + .id(id ?? ""), .name(_name), .placeholder(placeholder), .class( """ w-full rounded-md bg-white px-3 py-1.5 text-slate-900 outline-1 diff --git a/Sources/Styleguide/SVG.swift b/Sources/Styleguide/SVG.swift index 373d586..22ff7f6 100644 --- a/Sources/Styleguide/SVG.swift +++ b/Sources/Styleguide/SVG.swift @@ -15,11 +15,16 @@ public struct SVG: HTML, Sendable { extension SVG { public enum Key: Sendable { + case circlePlus case close case squarePen var svg: String { switch self { + case .circlePlus: + return """ + + """ case .close: return """ diff --git a/Sources/ViewController/Live.swift b/Sources/ViewController/Live.swift index 23ec423..17b6e6f 100644 --- a/Sources/ViewController/Live.swift +++ b/Sources/ViewController/Live.swift @@ -101,6 +101,14 @@ extension SiteRoute.View.EffectiveLengthRoute { return div(.id("effectiveLengthForm")) {} } return EffectiveLengthForm() + + case .field(let type): + switch type { + case .straightLength: + return StraightLengthField() + case .group: + return GroupField() + } } } } diff --git a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift index 28dffca..ae0146a 100644 --- a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift +++ b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthForm.swift @@ -18,11 +18,55 @@ struct EffectiveLengthForm: HTML, Sendable { ) { h1(.class("text-2xl font-bold")) { "Effective Length" } form(.class("space-y-4 p-4")) { - // FIX: Add fields + div { + label(.for("name")) { "Name" } + Input(id: "name", placeholder: "Name") + .attributes(.type(.text), .required, .autofocus) + } + div { + label(.for("type")) { "Type" } + // FIX: Add select field. + select( + .id("type"), .name("type"), + .class("w-full border rounded-md") + ) { + option(.value("supply")) { "Supply" } + option(.value("return")) { "Return" } + } + } + Row { + Label { "Straigth Lengths" } + button( + .type(.button), + .hx.get(route: .effectiveLength(.field(.straightLength))), + .hx.target("#straightLengths"), + .hx.swap(.beforeEnd) + ) { + SVG(.circlePlus) + } + } + div(.id("straightLengths")) { + StraightLengthField() + } + + Row { + Label { "Groups" } + button( + .type(.button), + .hx.get(route: .effectiveLength(.field(.group))), + .hx.target("#groups"), + .hx.swap(.beforeEnd) + ) { + SVG(.circlePlus) + } + } + div(.id("groups"), .class("space-y-4")) { + GroupField() + } Row { div {} - div { + div(.class("space-x-4")) { CancelButton() .attributes( .hx.get(route: .effectiveLength(.form(dismiss: true))), @@ -36,3 +80,38 @@ struct EffectiveLengthForm: HTML, Sendable { } } } + +struct StraightLengthField: HTML, Sendable { + let value: Int? + + init(value: Int? = nil) { + self.value = value + } + + var body: some HTML { + div(.class("pb-4")) { + Input( + name: "straightLengths[]", + placeholder: "Length" + ) + .attributes(.type(.number), .min("0")) + } + } +} + +struct GroupField: HTML, Sendable { + + var body: some HTML { + Row { + Input(name: "group[][group]", placeholder: "Group") + .attributes(.type(.number), .min("0")) + Input(name: "group[][letter]", placeholder: "Letter") + .attributes(.type(.text)) + Input(name: "group[][length]", placeholder: "Length") + .attributes(.type(.number), .min("0")) + Input(name: "group[][quantity]", placeholder: "Quantity") + .attributes(.type(.number), .min("1"), .value("1")) + } + .attributes(.class("space-x-2")) + } +} diff --git a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift index 9102ef0..b92beef 100644 --- a/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift +++ b/Sources/ViewController/Views/EffectiveLength/EffectiveLengthsView.swift @@ -9,11 +9,7 @@ struct EffectiveLengthsView: HTML, Sendable { var body: some HTML { div( - .class( - """ - m-4 - """ - ) + .class("m-4") ) { Row { h1(.class("text-2xl font-bold")) { "Effective Lengths" } @@ -29,11 +25,7 @@ struct EffectiveLengthsView: HTML, Sendable { div( .id("effectiveLengths"), - .class( - """ - border border-gray-200 rounded-lg shadow-lg - """ - ) + .class("space-y-6") ) { for row in effectiveLengths { EffectiveLengthView(effectiveLength: row) @@ -63,7 +55,7 @@ struct EffectiveLengthsView: HTML, Sendable { div( .class( """ - pb-6 + border border-gray-200 rounded-lg shadow-lg p-4 """ ) ) { @@ -99,7 +91,7 @@ struct EffectiveLengthsView: HTML, Sendable { Number(Double(straightLengthsTotal) + groupsTotal, digits: 0) .attributes(.class("text-xl font-bold")) } - .attributes(.class("border border-gray-200")) + .attributes(.class("border-b border-t border-gray-200")) } } }