import Elementary import ElementaryHTMX import Fluent import SharedModels extension HTMLAttribute.hx { static func get(route: RouteKey) -> HTMLAttribute { get(route.url) } static func post(route: RouteKey) -> HTMLAttribute { post(route.url) } static func put(route: RouteKey) -> HTMLAttribute { put(route.url) } static func delete(route: RouteKey) -> HTMLAttribute { delete(route.url) } } extension HTMLAttribute.hx { static func target(_ target: HXTarget) -> HTMLAttribute { Self.target(target.selector) } } extension HTMLAttribute where Tag: HTMLTrait.Attributes.Global { static func id(_ target: HXTarget) -> Self { id(target.id) } } enum RouteKey { case employees(EmployeeRoute? = nil) case purchaseOrders(PurchaseOrderRoute? = nil) case users(UserRoute? = nil) var url: String { switch self { case let .employees(employees): let path = "/employees" guard let employees else { return path } return "\(path)/\(employees.path)" case let .purchaseOrders(route): let path = "/purchase-orders" guard let route else { return path } return "\(path)/\(route.path)" case let .users(route): let path = "/users" guard let route else { return path } return "\(path)/\(route.path)" } } enum EmployeeRoute { case create case id(Employee.ID) var path: String { switch self { case .create: return "create" case let .id(id): return id.uuidString } } } enum PurchaseOrderRoute { case create case nextPage(PageMetadata) case search(SearchQuery? = nil) var path: String { switch self { case .create: return "create" case let .nextPage(currentPage): return "next?page=\(currentPage.page + 1)&limit\(currentPage.per)" case let .search(query): guard let query else { return "search" } return "search?\(query.query)" } } enum SearchQuery { case context(PurchaseOrderSearchContext, table: Bool? = nil) var query: String { switch self { case let .context(context, table): let query = "context=\(context.rawValue)" guard let table else { return query } return "\(query)&table=\(table)" } } } } enum UserRoute { case create case id(User.ID) var path: String { switch self { case .create: return "create" case let .id(id): return id.uuidString } } } } enum HXTarget { case body case employee(EmployeeKey) case float case purchaseOrders(PurchaseOrdersKey? = nil) case search case this case user(UserKey) var selector: String { switch self { case .body: return "body" case .this: return "this" default: return "#\(id)" } } var id: String { switch self { case let .employee(key): return key.key case .float: return "float" case let .purchaseOrders(key): guard let key else { return "purchase-orders" } return key.key case .search: return "search" case let .user(key): return key.key case .this, .body: fatalError("'\(selector)' can not be used as an id.") } } enum PurchaseOrdersKey { case table case row(id: PurchaseOrder.ID) var key: String { switch self { case .table: return "purchase-orders-table" case let .row(id): return "purchase_order_\(id)" } } } enum EmployeeKey { case table case row(id: Employee.ID) var key: String { switch self { case .table: return "employee-table" case let .row(id): return "employee_\(id.uuidString)" } } } enum UserKey { case form case row(id: User.ID) case table(Table? = nil) var key: String { switch self { case .form: return "user-form" case let .row(id): return "user_\(id)" case let .table(table): let key = "user-table" guard let table else { return key } return "\(key)-\(table.rawValue)" } } enum Table: String { case body } } } enum ViewRoute: String { case employees case login case purchaseOrders case users case vendors var title: String { switch self { case .purchaseOrders: return "Purchase Orders" default: return rawValue.capitalized } } var description: String { switch self { case .employees: return "Employees are who purchase orders can be issued to." case .purchaseOrders, .login: return "" case .users: return "Users are who can login and issue purchase orders for employees." case .vendors: return "Vendors are where purchase orders can be issued to." } } }