import Elementary import Foundation import Validations public struct ResultView: HTML where ValueView: HTML, ErrorView: HTML { let result: Result let errorView: @Sendable (any Error) -> ErrorView public init( _ content: @escaping @Sendable () async throws -> ValueView, onError: @escaping @Sendable (any Error) -> ErrorView ) async { self.result = await Result(catching: content) self.errorView = onError } public var body: some HTML { switch result { case .success(let view): view case .failure(let error): errorView(error) } } } extension ResultView where ErrorView == Styleguide.ErrorView { public init( _ content: @escaping @Sendable () async throws -> ValueView ) async { await self.init( content, onError: { Styleguide.ErrorView(error: $0) } ) } public init( catching: @escaping @Sendable () async throws -> V, onSuccess content: @escaping @Sendable (V) -> ValueView ) async where ValueView: Sendable { await self.init( { try await content(catching()) } ) } public init( catching: @escaping @Sendable () async throws -> Void ) async where ValueView == EmptyHTML { await self.init( catching: catching, onSuccess: { EmptyHTML() } ) } } extension ResultView: Sendable where ValueView: Sendable, ErrorView: Sendable {} public struct ErrorView: HTML, Sendable { let error: any Error public init(error: any Error) { self.error = error } public var body: some HTML { div { h1(.class("text-xl font-bold text-error")) { "Oops: Error" } p { if let validationError = (error as? ValidationError) { "\(validationError.debugDescription)" } else { "\(error.localizedDescription)" } } } } }