154 lines
3.6 KiB
Swift
154 lines
3.6 KiB
Swift
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))
|
|
}
|
|
}
|
|
}
|
|
}
|