From a76d523541fe3e79c328c802dc67b30ec8cc29b0 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Tue, 28 Jan 2025 17:27:00 +0000 Subject: [PATCH] feat: Adds ability to toggle an employee's active status (#3) Reviewed-on: https://git.housh.dev/hhe/vapor-po/pulls/3 --- .../DatabaseClientLive/Employees+live.swift | 7 +++-- Sources/SharedModels/PurchaseOrder.swift | 2 +- Sources/ViewControllerLive/Routes+view.swift | 2 +- .../Views/Employees/EmployeeForm.swift | 26 +++++++++++++++++++ .../PurchaseOrders/PurchaseOrderFilter.swift | 14 ++++++++++ .../ViewControllerTests.swift | 2 +- .../ViewControllerTests/employeeViews.3.html | 6 +++++ 7 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 Sources/ViewControllerLive/Views/PurchaseOrders/PurchaseOrderFilter.swift diff --git a/Sources/DatabaseClientLive/Employees+live.swift b/Sources/DatabaseClientLive/Employees+live.swift index a3c6d46..7014dd5 100644 --- a/Sources/DatabaseClientLive/Employees+live.swift +++ b/Sources/DatabaseClientLive/Employees+live.swift @@ -37,6 +37,7 @@ public extension DatabaseClient.Employees { guard let model = try await EmployeeModel.find(id, on: database) else { throw NotFoundError() } + database.logger.debug("Applying updates to employee: \(updates)") try model.applyUpdate(updates) try await model.save(on: database) return try model.toDTO() @@ -170,8 +171,10 @@ final class EmployeeModel: Model, @unchecked Sendable { if let lastName = updates.lastName { self.lastName = lastName } - if let active = updates.active { - self.active = active + // NB: When html forms are submitted with a checkbox then active is nil + // in the update context. + if active, updates.active == nil || updates.active == false { + active = false } } } diff --git a/Sources/SharedModels/PurchaseOrder.swift b/Sources/SharedModels/PurchaseOrder.swift index 7adcea7..878ac37 100644 --- a/Sources/SharedModels/PurchaseOrder.swift +++ b/Sources/SharedModels/PurchaseOrder.swift @@ -128,8 +128,8 @@ public extension PurchaseOrder { /// given parameters. enum SearchContext: Sendable, Equatable { case customer(String) - case vendor(VendorBranch.ID) case employee(Employee.ID) + case vendor(VendorBranch.ID) } } diff --git a/Sources/ViewControllerLive/Routes+view.swift b/Sources/ViewControllerLive/Routes+view.swift index bf8d19e..981996e 100644 --- a/Sources/ViewControllerLive/Routes+view.swift +++ b/Sources/ViewControllerLive/Routes+view.swift @@ -77,7 +77,7 @@ extension SiteRoute.View.EmployeeRoute { return try await render(mainPage, isHtmxRequest, EmployeeForm(shouldShow: true)) case let .select(context: context): - return try await context.toHTML(employees: employees.fetchAll()) + return try await context.toHTML(employees: employees.fetchAll(.active)) case .index: return try await mainPage(EmployeeForm()) diff --git a/Sources/ViewControllerLive/Views/Employees/EmployeeForm.swift b/Sources/ViewControllerLive/Views/Employees/EmployeeForm.swift index e934360..5c7c913 100644 --- a/Sources/ViewControllerLive/Views/Employees/EmployeeForm.swift +++ b/Sources/ViewControllerLive/Views/Employees/EmployeeForm.swift @@ -42,6 +42,20 @@ struct EmployeeForm: HTML { .placeholder("Last Name"), .required ) } + if let employee { + div(.class("row"), .style("margin: 20px; float: left;")) { + label(.for("active"), .style("margin-right: 15px;")) { h2 { "Active" } } + if employee.active { + input( + .type(.checkbox), .id("active"), .name("active"), .checked + ) + } else { + input( + .type(.checkbox), .id("active"), .name("active") + ) + } + } + } div(.class("btn-row")) { button(.type(.submit), .class("btn-primary")) { buttonLabel @@ -59,6 +73,18 @@ struct EmployeeForm: HTML { } } } + if employee != nil { + h3 { + i { + span(.class("primary"), .style("padding-right: 15px;")) { + "Note:" + } + span(.class("secondary")) { + "It is better to mark an employee as in-active instead of deleting them." + } + } + } + } } } diff --git a/Sources/ViewControllerLive/Views/PurchaseOrders/PurchaseOrderFilter.swift b/Sources/ViewControllerLive/Views/PurchaseOrders/PurchaseOrderFilter.swift new file mode 100644 index 0000000..1495d5c --- /dev/null +++ b/Sources/ViewControllerLive/Views/PurchaseOrders/PurchaseOrderFilter.swift @@ -0,0 +1,14 @@ +import Elementary +import ElementaryHTMX +import SharedModels + +struct PurchaseOrderFilter: HTML, Sendable { + + var content: some HTML { + form( + .id("filter-form") + ) { + input(.type(.text), .name("id"), .placeholder("Filter: (12345)"), .required) + } + } +} diff --git a/Tests/ViewControllerTests/ViewControllerTests.swift b/Tests/ViewControllerTests/ViewControllerTests.swift index 8a029c8..2baa7c1 100644 --- a/Tests/ViewControllerTests/ViewControllerTests.swift +++ b/Tests/ViewControllerTests/ViewControllerTests.swift @@ -20,7 +20,7 @@ struct ViewControllerTests { @Test func employeeViews() async throws { - try await withSnapshotTesting(record: record) { + try await withSnapshotTesting(record: .missing) { try await withDependencies { $0.viewController = .liveValue $0.database.employees = .mock diff --git a/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/employeeViews.3.html b/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/employeeViews.3.html index c7fd027..bef2e5c 100644 --- a/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/employeeViews.3.html +++ b/Tests/ViewControllerTests/__Snapshots__/ViewControllerTests/employeeViews.3.html @@ -8,9 +8,15 @@
+
+ + +
+

Note:It is better to mark an employee as in-active instead of deleting them.

\ No newline at end of file