import ApiController import Dependencies import DependenciesMacros import Elementary import Logging import PsychrometricClient import Routes import Styleguide public extension DependencyValues { var viewController: ViewController { get { self[ViewController.self] } set { self[ViewController.self] = newValue } } } public typealias AnySendableHTML = (any HTML & Sendable) @DependencyClient public struct ViewController: Sendable { public var view: @Sendable (Request) async throws -> AnySendableHTML public struct Request: Sendable { let route: SiteRoute.View let isHtmxRequest: Bool let logger: Logger public init( _ route: SiteRoute.View, isHtmxRequest: Bool, logger: Logger ) { self.route = route self.isHtmxRequest = isHtmxRequest self.logger = logger } } } extension ViewController: TestDependencyKey { public static let testValue: ViewController = Self() } extension ViewController: DependencyKey { public static var liveValue: ViewController { @Dependency(\.psychrometricClient) var psychrometricClient return .init(view: { request in let logger = request.logger logger.debug("View route: \(request.route)") switch request.route { case .index: return MainPage { div(.class("space-y-6")) { div(.class("pb-8")) { h1(.class("font-extrabold text-4xl dark:text-gray-200")) { "Professional Calculators" } p(.class("text-blue-500 font-bold")) { """ Professional calculators for HVAC system design and troublshooting. """ } } WarningBox( "This site is still under construction, not all it's functionality is working." ) HomePage() } } case let .atticVentilation(route): switch route { case .index: return request.respond(AtticVentilationForm(response: nil)) case let .submit(request): let response = try await request.respond(logger: logger) return AtticVentilationResponse(response: response) } case let .capacitor(route): switch route { case let .index(mode: mode): logger.debug("Capacitor view: \(String(describing: mode))") return request.respond(CapacitorForm(mode: mode, response: nil)) case let .submit(request): logger.debug("Capaitor view submit: \(request)") let response = try await request.respond(logger: logger) return CapacitorResponse(response: response) } case let .dehumidifierSize(route): switch route { case .index: return request.respond(DehumidifierSizeForm()) case let .submit(sizeRequest): let response = try await sizeRequest.respond(request.logger) return DehumidifierSizeResult(response: response) } case let .filterPressureDrop(route): switch route { case let .index(mode: mode): return request.respond(FilterPressureDropForm(mode: mode, response: nil)) case let .submit(request): let response = try await request.respond(logger: logger) return FilterPressureDropResponse(response: response) } case let .heatingBalancePoint(route): switch route { case let .index(mode: mode, heatLossMode: heatLossMode): return request.respond(HeatingBalancePointForm( mode: mode, heatLossMode: heatLossMode, response: nil )) case let .heatLossFields(mode: mode): return HeatingBalancePointForm.HeatLossFields(mode: mode) case let .submit(request): let response = try await request.respond(logger: logger) return HeatingBalancePointResponse(response: response) } case let .hvacSystemPerformance(route): switch route { case .index: return request.respond(HVACSystemPerformanceForm(response: nil)) case let .submit(hvacRequest): let response = try await hvacRequest.respond(logger: request.logger) return HVACSystemPerformanceResult(response: response) } case let .moldRisk(route): switch route { case .index: return request.respond(MoldRiskForm(response: nil)) case let .submit(request): let response = try await psychrometricClient.respond(request) return MoldRiskResponse(response: response) } case let .psychrometrics(route): switch route { case .index: return request.respond(PsychrometricsForm(response: nil)) case let .submit(request): let response = try await request.respond(logger: logger) return PsychrometricsResponse(response: response) } case let .roomPressure(route): switch route { case let .index(mode): return request.respond(RoomPressureForm(mode: mode, response: nil)) case let .submit(request): let response = try await request.respond(logger: logger) return RoomPressureResult(response: response) } } }) } } extension ViewController.Request { func respond( _ html: C ) -> AnySendableHTML where C: Sendable { guard isHtmxRequest else { return MainPage { html } } return html } }