import CasePathsCore import Foundation @preconcurrency import URLRouting public extension SiteRoute { // swiftlint:disable type_body_length /// Represents view routes that can be interacted with. /// /// These routes return html and are used to generate the web interface. enum View: Sendable, Equatable { case employee(SiteRoute.View.EmployeeRoute) case login(SiteRoute.View.LoginRoute) case purchaseOrder(SiteRoute.View.PurchaseOrderRoute) case resetPassword(SiteRoute.View.ResetPasswordRoute) case user(SiteRoute.View.UserRoute) case vendor(SiteRoute.View.VendorRoute) case vendorBranch(SiteRoute.View.VendorBranchRoute) public static let router = OneOf { Route(.case(Self.employee)) { SiteRoute.View.EmployeeRoute.router } Route(.case(Self.login)) { SiteRoute.View.LoginRoute.router } Route(.case(Self.purchaseOrder)) { SiteRoute.View.PurchaseOrderRoute.router } Route(.case(Self.resetPassword)) { SiteRoute.View.ResetPasswordRoute.router } Route(.case(Self.user)) { SiteRoute.View.UserRoute.router } Route(.case(Self.vendor)) { SiteRoute.View.VendorRoute.router } Route(.case(Self.vendorBranch)) { SiteRoute.View.VendorBranchRoute.router } } public enum EmployeeRoute: Sendable, Equatable { case create(Employee.Create) case form case get(id: Employee.ID) case index case select(context: SiteRoute.View.SelectContext) case update(id: Employee.ID, updates: Employee.Update) static let rootPath = "employees" public static let router = OneOf { Route(.case(Self.create)) { Path { rootPath } Method.post Body { FormData { Field("firstName", .string) Field("lastName", .string) Optionally { Field("active") { Bool.parser() } } } .map(.memberwise(Employee.Create.init)) } } Route(.case(Self.get(id:))) { Path { rootPath; Employee.ID.parser() } Method.get } Route(.case(Self.form)) { Path { rootPath; "create" } Method.get } Route(.case(Self.index)) { Path { rootPath } Method.get } Route(.case(Self.update(id:updates:))) { Path { rootPath; Employee.ID.parser() } Method.put Body { FormData { Optionally { Field("firstName") { CharacterSet.alphanumerics.map(.string) } } Optionally { Field("lastName") { CharacterSet.alphanumerics.map(.string) } } Optionally { Field("active") { Bool.parser() } } } .map(.memberwise(Employee.Update.init)) } } Route(.case(Self.select(context:))) { Path { rootPath; "select" } Method.get Query { Field("context") { SelectContext.parser() } } } } } public enum LoginRoute: Sendable, Equatable { case index(next: String? = nil) case post(Request) static let rootPath = "login" public static let router = OneOf { Route(.case(Self.index)) { Method.get Path { rootPath } Query { Optionally { Field("next", default: nil) { CharacterSet.urlPathAllowed.map(.string) } } } } Route(.case(Self.post)) { Path { rootPath } Method.post Body { FormData { Field("username", .string) Field("password", .string) Optionally { Field("next", default: nil) { CharacterSet.urlPathAllowed.map(.string) } } } .map(.memberwise(Request.init)) } } } public struct Request: Codable, Equatable, Sendable { public let username: String public let password: String public let next: String? public init(username: String, password: String, next: String? = nil) { self.username = username self.password = password self.next = next } } } public enum PurchaseOrderRoute: Sendable, Equatable { case create(PurchaseOrder.CreateIntermediate) case form case get(id: PurchaseOrder.ID) case index case page(page: Int, limit: Int) case search(Search) static let rootPath = "purchase-orders" public static let router = OneOf { Route(.case(Self.create)) { Path { rootPath } Method.post Body { FormData { Optionally { Field("id") { PurchaseOrder.ID.parser() } } Optionally { Field("workOrder") { Int.parser() } } Field("materials", .string) Field("customer", .string) Optionally { Field("truckStock") { Bool.parser() } } Field("createdForID") { Employee.ID.parser() } Field("vendorBranchID") { VendorBranch.ID.parser() } } .map(.memberwise(PurchaseOrder.CreateIntermediate.init)) } } Route(.case(Self.form)) { Path { rootPath; "create" } Method.get } Route(.case(Self.get(id:))) { Path { rootPath; Digits() } Method.get } Route(.case(Self.index)) { Path { rootPath } Method.get } Route(.case(Self.page(page:limit:))) { Path { rootPath; "next" } Method.get Query { Field("page", default: 1) { Digits() } Field("limit", default: 25) { Digits() } } } Route(.case(Self.search)) { Search.router } } public enum Search: Sendable, Equatable { case index(context: Context? = nil, table: Bool? = nil) case request(Request) static let rootPath = Path { "purchase-orders"; "search" } static let router = OneOf { Route(.case(Search.index(context:table:))) { rootPath Method.get Query { Optionally { Field("context", default: .employee) { Search.Context.parser() } } Optionally { Field("table", default: nil) { Bool.parser() } } } } Route(.case(Search.request)) { rootPath Method.post Body { FormData { Field("context") { Context.parser() } Optionally { Field("createdForID") { Employee.ID.parser() } } Optionally { Field("customerSearch", .string) } Optionally { Field("vendorBranchID") { VendorBranch.ID.parser() } } } .map(.memberwise(Request.init)) } } } public enum Context: String, Codable, CaseIterable, Equatable, Sendable { case employee case customer case vendor } // TODO: Create a validation or potentially turn this into an enum with the valid states. public struct Request: Codable, Equatable, Sendable { public let context: Context public let createdForID: Employee.ID? public let customerSearch: String? public let vendorBranchID: VendorBranch.ID? public init( context: Context, createdForID: Employee.ID? = nil, customerSearch: String? = nil, vendorBranchID: VendorBranch.ID? = nil ) { self.context = context self.createdForID = createdForID self.customerSearch = customerSearch self.vendorBranchID = vendorBranchID } } } } public enum ResetPasswordRoute: Sendable, Equatable { case index(id: User.ID) case submit(id: User.ID, request: User.ResetPassword) static let rootPath = "reset-password" public static let router = OneOf { Route(.case(Self.index(id:))) { Path { rootPath; User.ID.parser() } Method.get } Route(.case(Self.submit(id:request:))) { Path { rootPath; User.ID.parser() } Method.patch Body { FormData { Field("password", .string) Field("confirmPassword", .string) } .map(.memberwise(User.ResetPassword.init)) } } } } public enum SelectContext: String, Codable, Equatable, Sendable, CaseIterable { case purchaseOrderForm case purchaseOrderSearch } public enum UserRoute: Sendable, Equatable { case create(User.Create) case form case get(id: User.ID) case index case update(id: User.ID, updates: User.Update) static let rootPath = "users" public static let router = OneOf { Route(.case(Self.create)) { Path { rootPath } Method.post Body { FormData { Field("username", .string) Field("email", .string) Field("password", .string) Field("confirmPassword", .string) } .map(.memberwise(User.Create.init)) } } Route(.case(Self.form)) { Path { rootPath; "create" } Method.get } Route(.case(Self.get(id:))) { Path { rootPath; User.ID.parser() } Method.get } Route(.case(Self.index)) { Path { rootPath } Method.get } Route(.case(Self.update(id:updates:))) { Path { rootPath; User.ID.parser() } Method.patch Body { FormData { Optionally { Field("username") { CharacterSet.alphanumerics.map(.string) } } Optionally { Field("email", .string) } } .map(.memberwise(User.Update.init)) } } } } public enum VendorRoute: Sendable, Equatable { case create(Vendor.Create) case form case get(id: Vendor.ID) case index case update(id: Vendor.ID, updates: Vendor.Update) static let rootPath = "vendors" public static let router = OneOf { Route(.case(Self.create)) { Path { rootPath } Method.post Body { FormData { Field("name", .string) } .map(.memberwise(Vendor.Create.init)) } } Route(.case(Self.get(id:))) { Path { rootPath; Vendor.ID.parser() } Method.get } Route(.case(Self.form)) { Path { rootPath; "create" } Method.get } Route(.case(Self.index)) { Path { rootPath } Method.get } Route(.case(Self.update(id:updates:))) { Path { rootPath; Vendor.ID.parser() } Method.put Body { FormData { Field("name", .string) } .map(.memberwise(Vendor.Update.init)) } } } } public enum VendorBranchRoute: Sendable, Equatable { case create(VendorBranch.Create) case index(for: Vendor.ID? = nil) case select(context: SiteRoute.View.SelectContext) public static let router = OneOf { Route(.case(Self.create)) { Path { "vendors"; "branches" } Method.post Body { FormData { Field("name", .string) Field("vendorID") { Vendor.ID.parser() } } .map(.memberwise(VendorBranch.Create.init)) } } Route(.case(Self.index(for:))) { Path { "vendors"; "branches" } Method.get Query { Optionally { Field("vendorID") { Vendor.ID.parser() } } } } Route(.case(Self.select(context:))) { Path { "vendors"; "branches"; "select" } Method.get Query { Field("context") { SiteRoute.View.SelectContext.parser() } } } } } } // swiftlint:enable type_body_length }