diff --git a/Resources/Views/employees/table-row.leaf b/Resources/Views/employees/table-row.leaf
new file mode 100644
index 0000000..e7c8d4d
--- /dev/null
+++ b/Resources/Views/employees/table-row.leaf
@@ -0,0 +1,40 @@
+
+ | #capitalized(firstName) #capitalized(lastName) |
+
+ #if(active):
+
+
+
+ #else:
+
+
+
+ #endif
+ |
+
+
+ #extend("img/trash-can")
+
+
+ #extend("img/pencil")
+
+ |
+
+
diff --git a/Resources/Views/employees/table.leaf b/Resources/Views/employees/table.leaf
index 8960d98..14e014b 100644
--- a/Resources/Views/employees/table.leaf
+++ b/Resources/Views/employees/table.leaf
@@ -17,46 +17,7 @@
#for(employee in employees):
-
- | #capitalized(employee.firstName) #capitalized(employee.lastName) |
-
- #if(employee.active):
-
-
-
- #else:
-
-
-
- #endif
- |
-
-
- #extend("img/trash-can")
-
-
- #extend("img/pencil")
-
- |
-
-
+ #extend("employees/table-row", employee)
#endfor
diff --git a/Sources/App/Controllers/DB/EmployeeDB.swift b/Sources/App/Controllers/DB/EmployeeDB.swift
index 930038d..1f445b9 100644
--- a/Sources/App/Controllers/DB/EmployeeDB.swift
+++ b/Sources/App/Controllers/DB/EmployeeDB.swift
@@ -19,10 +19,18 @@ struct EmployeeDB: Sendable {
var get: @Sendable (Employee.IDValue) async throws -> Employee.DTO?
var update: @Sendable (Employee.IDValue, Employee.Update) async throws -> Employee.DTO
var delete: @Sendable (Employee.IDValue) async throws -> Void
+ var toggleActive: @Sendable (Employee.IDValue) async throws -> Employee.DTO
func fetchAll() async throws -> [Employee.DTO] {
try await fetchAll(false)
}
+
+ func get(_ id: String?) async throws -> Employee.DTO? {
+ guard let idString = id, let id = UUID(uuidString: idString) else {
+ throw Abort(.badRequest, reason: "Employee id not valid.")
+ }
+ return try await get(id)
+ }
}
extension EmployeeDB: TestDependencyKey {
@@ -61,54 +69,15 @@ extension EmployeeDB: TestDependencyKey {
throw Abort(.badRequest, reason: "Employee id not found.")
}
try await employee.delete(on: database)
+ },
+ toggleActive: { id in
+ guard let employee = try await Employee.find(id, on: database) else {
+ throw Abort(.notFound)
+ }
+ employee.active.toggle()
+ try await employee.save(on: database)
+ return employee.toDTO()
}
)
}
}
-
-// An intermediate layer between our api and view controllers that interacts with the
-// database model.
-// struct EmployeeDB {
-//
-// func create(_ model: Employee.Create, on db: any Database) async throws -> Employee.DTO {
-// let model = model.toModel()
-// try await model.save(on: db)
-// return model.toDTO()
-// }
-//
-// func fetchAll(active: Bool? = nil, on db: any Database) async throws -> [Employee.DTO] {
-// var query = Employee.query(on: db)
-// .sort(\.$lastName)
-//
-// if let active {
-// query = query.filter(\.$active == active)
-// }
-//
-// return try await query.all().map { $0.toDTO() }
-// }
-//
-// func get(id: Employee.IDValue, on db: any Database) async throws -> Employee.DTO? {
-// try await Employee.find(id, on: db).map { $0.toDTO() }
-// }
-//
-// func update(
-// id: Employee.IDValue,
-// with updates: Employee.Update,
-// on db: any Database
-// ) async throws -> Employee.DTO {
-// guard let employee = try await Employee.find(id, on: db) else {
-// throw Abort(.badRequest, reason: "Employee id not found.")
-// }
-// employee.applyUpdates(updates)
-// try await employee.save(on: db)
-// return employee.toDTO()
-// }
-//
-// func delete(id: Employee.IDValue, on db: any Database) async throws {
-// guard let employee = try await Employee.find(id, on: db) else {
-// throw Abort(.badRequest, reason: "Employee id not found.")
-// }
-// try await employee.delete(on: db)
-// }
-//
-// }
diff --git a/Sources/App/Controllers/View/EmployeeViewController.swift b/Sources/App/Controllers/View/EmployeeViewController.swift
index 9b7b3fe..492cb1b 100644
--- a/Sources/App/Controllers/View/EmployeeViewController.swift
+++ b/Sources/App/Controllers/View/EmployeeViewController.swift
@@ -6,7 +6,6 @@ import Vapor
struct EmployeeViewController: RouteCollection {
@Dependency(\.employees) var employees
- private let api = EmployeeApiController()
func boot(routes: any RoutesBuilder) throws {
let protected = routes.protected.grouped("employees")
@@ -17,7 +16,7 @@ struct EmployeeViewController: RouteCollection {
$0.get(use: edit(req:))
$0.delete(use: delete(req:))
$0.put(use: update(req:))
- $0.post("toggle-active", use: toggleActive(req:))
+ $0.patch("toggle-active", use: toggleActive(req:))
}
}
@@ -36,33 +35,35 @@ struct EmployeeViewController: RouteCollection {
@Sendable
func toggleActive(req: Request) async throws -> View {
- guard let employee = try await Employee.find(req.parameters.get("employeeID"), on: req.db) else {
- throw Abort(.notFound)
+ guard let id = req.parameters.get("employeeID", as: Employee.IDValue.self) else {
+ throw Abort(.badRequest, reason: "Employee id not supplied.")
}
- employee.active.toggle()
- try await employee.save(on: req.db)
- let employees = try await employees.fetchAll()
- return try await req.view.render("employees/table", ["employees": employees])
+ let employee = try await employees.toggleActive(id)
+ return try await req.view.render("employees/table-row", employee)
}
@Sendable
func delete(req: Request) async throws -> View {
- _ = try await api.delete(req: req)
+ let id = try req.requireEmployeeID()
+ _ = try await employees.delete(id)
let employees = try await employees.fetchAll()
return try await req.view.render("employees/table", ["employees": employees])
}
@Sendable
func edit(req: Request) async throws -> View {
- guard let employee = try await Employee.find(req.parameters.get("employeeID"), on: req.db) else {
+ guard let employee = try await employees.get(req.parameters.get("employeeID")) else {
throw Abort(.notFound)
}
- return try await req.view.render("employees/form", EmployeeFormCTX(employee: employee.toDTO()))
+ return try await req.view.render("employees/form", EmployeeFormCTX(employee: employee))
}
@Sendable
func update(req: Request) async throws -> View {
- _ = try await api.update(req: req)
+ let id = try req.requireEmployeeID()
+ try Employee.Update.validate(content: req)
+ let updates = try req.content.decode(Employee.Update.self)
+ _ = try await employees.update(id, updates)
return try await req.view.render("employees/index", EmployeesCTX(oob: true, db: employees))
}
@@ -73,6 +74,15 @@ struct EmployeeViewController: RouteCollection {
}
+private extension Request {
+ func requireEmployeeID() throws -> Employee.IDValue {
+ guard let id = parameters.get("employeeID", as: Employee.IDValue.self) else {
+ throw Abort(.badRequest, reason: "Employee id not supplied")
+ }
+ return id
+ }
+}
+
private struct EmployeesCTX: Content {
let oob: Bool
let employees: [Employee.DTO]