import DatabaseClient import Dependencies import Elementary import Foundation import ManualDCore extension ViewController.Request { func render() async throws -> AnySendableHTML { @Dependency(\.database) var database switch route { case .login(let route): switch route { case .index: return view { LoginForm() } case .submit(let login): let user = try await authenticate(login) let projects = try await database.projects.fetch(user.id, .init(page: 1, per: 25)) return view { ProjectsTable(userID: user.id, projects: projects) } } case .signup(let route): switch route { case .index: return view { LoginForm(style: .signup) } case .submit(let request): // Create a new user and log them in. let user = try await createAndAuthenticate(request) let projects = try await database.projects.fetch(user.id, .init(page: 1, per: 25)) return view { ProjectsTable(userID: user.id, projects: projects) } } case .project(let route): return try await route.renderView(on: self) case .room(let route): return try await route.renderView(on: self) case .frictionRate(let route): return try await route.renderView(isHtmxRequest: isHtmxRequest) case .effectiveLength(let route): return try await route.renderView(isHtmxRequest: isHtmxRequest) // case .user(let route): // return try await route.renderView(isHtmxRequest: isHtmxRequest) default: // FIX: FIX return _render(isHtmxRequest: false) { div { "Fix me!" } } } } func view( @HTMLBuilder inner: () -> C ) -> AnySendableHTML where C: Sendable { _render(isHtmxRequest: isHtmxRequest, showSidebar: showSidebar) { inner() } } var showSidebar: Bool { switch route { case .login, .signup, .project(.page): return false default: return true } } } extension SiteRoute.View.ProjectRoute { func renderView(on request: ViewController.Request) async throws -> AnySendableHTML { @Dependency(\.database) var database let user = try request.currentUser() switch self { case .index: let projects = try await database.projects.fetchPage(userID: user.id) return request.view { ProjectsTable(userID: user.id, projects: projects) } case .page(let page, let limit): let projects = try await database.projects.fetchPage( userID: user.id, page: page, limit: limit) return ProjectsTable(userID: user.id, projects: projects) case .form(let dismiss): return ProjectForm(dismiss: dismiss) case .create(let form): let project = try await database.projects.create(user.id, form) return request.view { ProjectView(projectID: project.id, activeTab: .projects) { ProjectDetail(project: project) } } case .detail(let projectID): let project = try await database.projects.get(projectID)! return request.view { ProjectView(projectID: projectID, activeTab: .projects) { ProjectDetail(project: project) } } } } } extension SiteRoute.View.RoomRoute { func renderView(on request: ViewController.Request) async throws -> AnySendableHTML { @Dependency(\.database) var database switch self { case .form(let projectID, let dismiss): return RoomForm(dismiss: dismiss, projectID: projectID) case .index(let projectID): let rooms = try await database.rooms.fetch(projectID) return request.view { ProjectView(projectID: projectID, activeTab: .rooms) { RoomsView(projectID: projectID, rooms: rooms) } } case .submit(let projectID, let form): request.logger.debug("New room form submitted.") let _ = try await database.rooms.create(.init(form: form, projectID: projectID)) let rooms = try await database.rooms.fetch(projectID) return request.view { ProjectView(projectID: projectID, activeTab: .rooms) { RoomsView(projectID: projectID, rooms: rooms) } } } } } extension SiteRoute.View.FrictionRateRoute { func renderView(isHtmxRequest: Bool) async throws -> AnySendableHTML { switch self { case .index: return _render(isHtmxRequest: isHtmxRequest, active: .frictionRate) { FrictionRateView() } case .form(let type, let dismiss): // FIX: Forms need to reference existing items. switch type { case .equipmentInfo: return EquipmentForm(dismiss: dismiss) case .componentPressureLoss: return ComponentLossForm(dismiss: dismiss) } } } } extension SiteRoute.View.FrictionRateRoute.FormType { var id: String { switch self { case .equipmentInfo: return "equipmentForm" case .componentPressureLoss: return "componentLossForm" } } } extension SiteRoute.View.EffectiveLengthRoute { func renderView(isHtmxRequest: Bool) async throws -> AnySendableHTML { switch self { case .index: return _render(isHtmxRequest: isHtmxRequest, active: .effectiveLength) { EffectiveLengthsView(effectiveLengths: EffectiveLength.mocks) } case .form(let dismiss): return EffectiveLengthForm(dismiss: dismiss) case .field(let type): switch type { case .straightLength: return StraightLengthField() case .group: return GroupField() } } } } private func _render( isHtmxRequest: Bool, active activeTab: Sidebar.ActiveTab = .projects, showSidebar: Bool = true, @HTMLBuilder inner: () async throws -> C ) async throws -> AnySendableHTML where C: Sendable { let inner = try await inner() if isHtmxRequest { return inner } return MainPage { inner } } private func _render( isHtmxRequest: Bool, active activeTab: Sidebar.ActiveTab = .projects, showSidebar: Bool = true, @HTMLBuilder inner: () -> C ) -> AnySendableHTML where C: Sendable { let inner = inner() if isHtmxRequest { return inner } return MainPage { inner } }