feat: Initial filter pressure drop views, calculations need implemented.

This commit is contained in:
2025-03-02 21:51:52 -05:00
parent a8022ec80a
commit 67488e06a9
17 changed files with 610 additions and 97 deletions

View File

@@ -1,4 +1,5 @@
import Elementary
import Routes
public struct PrimaryButton: HTML, Sendable {
let label: String
@@ -75,3 +76,70 @@ public struct ResetButton: HTML, Sendable {
}
}
}
public struct Toggle: HTML {
let isOn: Bool
// Left hand side / 'on' label.
let onLabel: String
// Applied to the rhs when the toggle is consider 'off'.
let onAttributes: [HTMLAttribute<HTMLTag.button>]
// Right hand side / 'off' label.
let offLabel: String
// Applied to the left hand side when the toggle is consider 'on'.
let offAttributes: [HTMLAttribute<HTMLTag.button>]
public init(
isOn: Bool,
onLabel: String,
onAttributes: [HTMLAttribute<HTMLTag.button>],
offLabel: String,
offAttributes: [HTMLAttribute<HTMLTag.button>]
) {
self.isOn = isOn
self.onLabel = onLabel
self.onAttributes = onAttributes
self.offLabel = offLabel
self.offAttributes = offAttributes
}
public var content: some HTML<HTMLTag.div> {
div(.class("flex items-center gap-x-0")) {
switch isOn {
case true:
SecondaryButton(label: onLabel)
.attributes(.class("rounded-s-lg"), .disabled)
PrimaryButton(label: offLabel)
.attributes(contentsOf: offAttributes + [.class("rounded-e-lg")])
case false:
PrimaryButton(label: onLabel)
.attributes(contentsOf: onAttributes + [.class("rounded-s-lg")])
SecondaryButton(label: offLabel)
.attributes(.class("rounded-e-lg"), .disabled)
}
}
}
}
public extension Array where Element == HTMLAttribute<HTMLTag.button> {
static func hxDefaults(
_ attributes: HTMLAttribute<HTMLTag.button>...
) -> Self {
[
.hx.target("#content"),
.hx.pushURL(true)
] + attributes
}
static func hxDefaults(
get route: SiteRoute.View
) -> Self {
.hxDefaults(.hx.get(route: route))
}
}

View File

@@ -50,7 +50,7 @@ public struct Input: HTML, Sendable {
input(
.id(id), .placeholder(placeholder), .name(name ?? id),
.class("""
w-full px-4 py-2 border rounded-md
w-full px-4 py-2 border rounded-md min-h-11
focus:ring-2 focus:ring-yellow-800 focus:border-yellow-800
placeholder-shown:!border-gray-400
invalid:border-red-500 out-of-range:border-red-500
@@ -84,3 +84,57 @@ public struct InputLabel<InputLabel: HTML>: HTML {
}
extension InputLabel: Sendable where InputLabel: Sendable {}
public struct Select<T>: HTML {
let id: String
let name: String?
let values: [T]
let label: @Sendable (T) -> String
let value: @Sendable (T) -> String
public init(
id: String,
name: String? = nil,
values: [T],
label: @escaping @Sendable (T) -> String,
value: @escaping @Sendable (T) -> String
) {
self.id = id
self.name = name
self.values = values
self.label = label
self.value = value
}
public var content: some HTML<HTMLTag.select> {
select(
.id(id),
.name(name ?? id),
.class("w-full rounded-md border px-4 py-2 min-h-11")
) {
for value in values {
option(.value(self.value(value))) { label(value) }
}
}
}
}
extension Select: Sendable where T: Sendable {}
public extension Select where T: CaseIterable, T: RawRepresentable, T.RawValue: CustomStringConvertible {
init(
for type: T.Type,
id: String,
name: String? = nil,
label: @escaping @Sendable (T) -> String
) {
self.init(
id: id,
name: name,
values: Array(T.allCases),
label: label,
value: { $0.rawValue.description }
)
}
}

View File

@@ -10,11 +10,16 @@ public struct Note: HTML, Sendable {
}
public var content: some HTML {
div(.class("mt-8 p-4 bg-gray-100 dark:bg-gray-700 rounded-md shadow-md border border-blue-500")) {
p(.class("text-sm text-blue-500")) {
span(.class("font-extrabold pe-2")) { label }
text
}
div(
.class(
"""
mt-8 p-4 bg-gray-100 dark:bg-gray-700 rounded-md shadow-md
border border-blue-500 text-blue-500 text-sm
"""
)
) {
p(.class("font-extrabold mb-3")) { label }
p(.class("px-6")) { text }
}
}
}

View File

@@ -0,0 +1,34 @@
import Elementary
public struct Row<Body: HTML>: HTML {
let body: Body
public init(
@HTMLBuilder body: () -> Body
) {
self.body = body()
}
public var content: some HTML<HTMLTag.div> {
div(.class("flex justify-between")) {
body
}
}
}
public extension Row
where Body == _HTMLTuple2<HTMLElement<HTMLTag.span, HTMLText>, HTMLElement<HTMLTag.span, HTMLText>>
{
init(
label: String,
value: String
) {
self.init {
span(.class("font-bold")) { label }
span { value }
}
}
}
extension Row: Sendable where Body: Sendable {}

View File

@@ -0,0 +1,25 @@
import Elementary
public struct VerticalGroup: HTML, Sendable {
let label: String
let value: String
let valueLabel: String?
public init(label: String, value: String, valueLabel: String? = nil) {
self.label = label
self.value = value
self.valueLabel = valueLabel
}
public var content: some HTML<HTMLTag.div> {
div(.class("grid grid-cols-1 justify-items-center")) {
p(.class("font-medium")) { label }
h3(.class("text-3xl font-extrabold")) {
value
if let valueLabel {
span(.class("text-lg ms-2")) { valueLabel }
}
}
}
}
}