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 == .create { Float(shouldDisplay: true) { makeForm() } } else { makeForm() } } private func makeForm() -> some HTML { form( .id(.user(.form)), .class("user-form"), .hx.post(context.targetURL), .hx.pushURL(context.pushURL), .hx.target(context.target), .hx.swap(.outerHTML), .custom( name: "hx-on::after-request", value: "if(event.detail.successful) this.reset(); toggleContent('float');" ) ) { if case let .login(next) = context, let next { input(.type(.hidden), .name("next"), .value(next)) } 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 { case create case login(next: String?) var showConfirmPassword: Bool { switch self { case .create: return true case .login: return false } } var showEmailInput: Bool { switch self { case .create: return true case .login: return false } } var pushURL: Bool { switch self { case .create: return false case .login: return true } } var buttonLabel: String { switch self { case .create: return "Create" case .login: return "Login" } } var target: String { switch self { case .create: return "next table" case .login: return "body" } } // TODO: Return a ViewRoute. var targetURL: String { switch self { case .create: return "/users" case .login: return "/login" // let path = "/login" // if let next { // return "\(path)?next=\(next)" // } // return path } } } }