import Elementary import ElementaryHTMX import SharedModels // Form used to login or create a new user. struct UserForm: HTML, Sendable { let context: Context var content: some HTML { if context.isFloat { Float(shouldDisplay: true) { makeForm() } } else { makeForm() } } private func makeForm() -> some HTML { form( .id(.user(.form)), .class("user-form"), context.isResetPassword ? .hx.patch(route: context.targetURL) : .hx.post(route: context.targetURL), .hx.pushURL(context.pushURL), .hx.target(context.target), .hx.swap(context == .create ? .afterBegin.transition(true).swap("0.5s") : .outerHTML), .hx.on( .afterRequest, context.toggleContent ? .ifSuccessful(.resetForm, .toggleContent(.float)) : .ifSuccessful(.resetForm) ) ) { if case let .login(next) = context, let next { input(.type(.hidden), .name("next"), .value(next)) } if context.showUsername { div(.class("row")) { input(.type(.text), .id("username"), .name("username"), .placeholder("Username"), .autofocus, .required) } } if context.showEmailInput { div(.class("row")) { input(.type(.email), .id("email"), .name("email"), .placeholder("Email"), .required) } } div(.class("row")) { input(.type(.password), .id("password"), .name("password"), .placeholder("Password"), .required) } if context.showConfirmPassword { div(.class("row")) { input( .type(.password), .id("confirmPassword"), .name("confirmPassword"), .placeholder("Confirm Password"), .required ) } } div(.class("row")) { button(.type(.submit), .class("btn-primary")) { context.buttonLabel } } } } enum Context: Equatable, Sendable { case create case login(next: String?) case resetPassword(id: User.ID) var isResetPassword: Bool { guard case .resetPassword = self else { return false } return true } var isFloat: Bool { switch self { case .create, .resetPassword: return true case .login: return false } } var toggleContent: Bool { guard case .resetPassword = self else { return true } return false } var showUsername: Bool { switch self { case .create: return true case .login: return true case .resetPassword: return false } } var showConfirmPassword: Bool { switch self { case .create: return true case .login: return false case .resetPassword: return true } } var showEmailInput: Bool { switch self { case .create: return true case .login: return false case .resetPassword: return false } } var pushURL: Bool { switch self { case .create: return false case .login: return true case .resetPassword: return false } } var buttonLabel: String { switch self { case .create: return "Create" case .login: return "Login" case .resetPassword: return "Reset" } } var target: HXTarget { switch self { case .create: return .id(.user(.table)) case .login: return .body case .resetPassword: return .id(.float) } } var targetURL: SiteRoute.View { switch self { case .create: return .user(.index) case .login: return .login(.index()) case let .resetPassword(id: id): return .resetPassword(.index(id: id)) } } } }