add forms for user auth
This commit is contained in:
parent
7bd63caae7
commit
69db46715f
3 changed files with 146 additions and 93 deletions
lib/web
|
@ -3,4 +3,99 @@ defmodule Web.CoreComponents do
|
|||
Provides core UI components.
|
||||
"""
|
||||
use Phoenix.Component
|
||||
|
||||
alias Phoenix.HTML.FormField
|
||||
|
||||
attr :id, :any, default: nil
|
||||
attr :name, :any
|
||||
attr :label, :string, default: nil
|
||||
attr :value, :any
|
||||
attr :type, :string, default: "text", values: ~w[text password]
|
||||
attr :field, FormField
|
||||
attr :errors, :list, default: []
|
||||
attr :rest, :global, include: ~w[disabled form pattern placeholder readonly required]
|
||||
|
||||
def input(%{field: %FormField{} = field} = assigns) do
|
||||
errors =
|
||||
if Phoenix.Component.used_input?(field) do
|
||||
field.errors
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
assigns
|
||||
|> assign(field: nil, id: assigns.id || field.id, errors: Enum.map(errors, &translate_error/1))
|
||||
|> assign_new(:name, fn -> field.name end)
|
||||
|> assign_new(:value, fn -> field.value end)
|
||||
|> input()
|
||||
end
|
||||
|
||||
def input(assigns) do
|
||||
~H"""
|
||||
<div>
|
||||
<.label for={@id}>{@label}</.label>
|
||||
<input
|
||||
id={@id}
|
||||
type={@type}
|
||||
name={@name}
|
||||
value={Phoenix.HTML.Form.normalize_value(@type, @value)}
|
||||
{@rest}
|
||||
/>
|
||||
<.error :for={error <- @errors}>{error}</.error>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
attr :for, :string, default: nil
|
||||
slot :inner_block, required: true
|
||||
|
||||
def label(assigns) do
|
||||
~H"""
|
||||
<label for={@for}>
|
||||
{render_slot(@inner_block)}
|
||||
</label>
|
||||
"""
|
||||
end
|
||||
|
||||
slot :inner_block, required: true
|
||||
|
||||
def error(assigns) do
|
||||
~H"""
|
||||
<p>
|
||||
<.icon name="hero-exclamation-circle-mini" class="h-5 w-5 flex-none" />
|
||||
{render_slot(@inner_block)}
|
||||
</p>
|
||||
"""
|
||||
end
|
||||
|
||||
attr :name, :string, required: true
|
||||
attr :class, :string, default: nil
|
||||
|
||||
def icon(%{name: "hero-" <> _} = assigns) do
|
||||
~H"""
|
||||
<span class={[@name, @class]} />
|
||||
"""
|
||||
end
|
||||
|
||||
def translate_error({msg, opts}) do
|
||||
Enum.reduce(opts, msg, fn {key, value}, acc ->
|
||||
String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end)
|
||||
end)
|
||||
end
|
||||
|
||||
def translate_errors(errors, field) when is_list(errors) do
|
||||
for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts})
|
||||
end
|
||||
|
||||
attr :type, :string, default: "button", values: ~w[button submit]
|
||||
attr :rest, :global
|
||||
slot :inner_block, required: true
|
||||
|
||||
def button(assigns) do
|
||||
~H"""
|
||||
<button type={@type} {@rest}>
|
||||
{render_slot(@inner_block)}
|
||||
</button>
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,46 +2,24 @@ defmodule Web.UserLoginLive do
|
|||
@moduledoc false
|
||||
use Web, :live_view
|
||||
|
||||
def mount(_params, _session, socket) do
|
||||
form = to_form(%{}, as: "user")
|
||||
{:ok, assign(socket, form: form), temporary_assigns: [form: form], layout: false}
|
||||
end
|
||||
|
||||
def render(assigns) do
|
||||
# ~H"""
|
||||
# <div class="mx-auto max-w-sm">
|
||||
# <.header class="text-center">
|
||||
# Log in to account
|
||||
# <:subtitle>
|
||||
# Don't have an account?
|
||||
# <.link navigate={~p/admin/users/register"} class="font-semibold text-brand hover:underline">
|
||||
# Sign up
|
||||
# </.link>
|
||||
# for an account now.
|
||||
# </:subtitle>
|
||||
# </.header>
|
||||
|
||||
# <.simple_form for={@form} id="login_form" action={~p/admin/users/log_in"} phx-update="ignore">
|
||||
# <.input field={@form[:email]} type="email" label="Email" required />
|
||||
# <.input field={@form[:password]} type="password" label="Password" required />
|
||||
|
||||
# <:actions>
|
||||
# <.input field={@form[:remember_me]} type="checkbox" label="Keep me logged in" />
|
||||
# <.link href={~p/admin/users/reset_password"} class="text-sm font-semibold">
|
||||
# Forgot your password?
|
||||
# </.link>
|
||||
# </:actions>
|
||||
# <:actions>
|
||||
# <.button phx-disable-with="Logging in..." class="w-full">
|
||||
# Log in <span aria-hidden="true">→</span>
|
||||
# </.button>
|
||||
# </:actions>
|
||||
# </.simple_form>
|
||||
# </div>
|
||||
# """
|
||||
~H"""
|
||||
<pre>UserLoginLive</pre>
|
||||
<div class="mx-auto max-w-sm">
|
||||
<header>sign in</header>
|
||||
|
||||
<.form for={@form} id="login_form" action={~p"/admin/users/log_in"} phx-update="ignore">
|
||||
<.input field={@form[:username]} type="text" label="username" required />
|
||||
<.input field={@form[:password]} type="password" label="password" required />
|
||||
<.button phx-disable-with="signing in..." class="w-full" type="submit">
|
||||
sign in
|
||||
</.button>
|
||||
</.form>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
def mount(_params, _session, socket) do
|
||||
email = Phoenix.Flash.get(socket.assigns.flash, :email)
|
||||
form = to_form(%{"email" => email}, as: "user")
|
||||
{:ok, assign(socket, form: form), temporary_assigns: [form: form]}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,67 +4,29 @@ defmodule Web.UserRegistrationLive do
|
|||
|
||||
alias Core.Accounts
|
||||
|
||||
def render(assigns) do
|
||||
# ~H"""
|
||||
# <div class="mx-auto max-w-sm">
|
||||
# <.header class="text-center">
|
||||
# Register for an account
|
||||
# <:subtitle>
|
||||
# Already registered?
|
||||
# <.link navigate={~p/admin/users/log_in"} class="font-semibold text-brand hover:underline">
|
||||
# Log in
|
||||
# </.link>
|
||||
# to your account now.
|
||||
# </:subtitle>
|
||||
# </.header>
|
||||
|
||||
# <.simple_form
|
||||
# for={@form}
|
||||
# id="registration_form"
|
||||
# phx-submit="save"
|
||||
# phx-change="validate"
|
||||
# phx-trigger-action={@trigger_submit}
|
||||
# action={~p/admin/users/log_in?_action=registered"}
|
||||
# method="post"
|
||||
# >
|
||||
# <.error :if={@check_errors}>
|
||||
# Oops, something went wrong! Please check the errors below.
|
||||
# </.error>
|
||||
|
||||
# <.input field={@form[:email]} type="email" label="Email" required />
|
||||
# <.input field={@form[:password]} type="password" label="Password" required />
|
||||
|
||||
# <:actions>
|
||||
# <.button phx-disable-with="Creating account..." class="w-full">Create an account</.button>
|
||||
# </:actions>
|
||||
# </.simple_form>
|
||||
# </div>
|
||||
# """
|
||||
~H"""
|
||||
<pre>UserRegistrationLive</pre>
|
||||
"""
|
||||
end
|
||||
|
||||
def mount(_params, _session, socket) do
|
||||
changeset = Accounts.change_user_registration(%Schema.User{})
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(trigger_submit: false, check_errors: false)
|
||||
|> assign(trigger_submit: false)
|
||||
|> assign_form(changeset)
|
||||
|
||||
{:ok, socket, temporary_assigns: [form: nil]}
|
||||
{:ok, socket, temporary_assigns: [form: nil], layout: false}
|
||||
end
|
||||
|
||||
def handle_event("save", %{"user" => user_params}, socket) do
|
||||
case Accounts.register_user(user_params) do
|
||||
{:ok, user} ->
|
||||
changeset = Accounts.change_user_registration(user)
|
||||
{:noreply, socket |> assign(trigger_submit: true) |> assign_form(changeset)}
|
||||
socket =
|
||||
case Accounts.register_user(user_params) do
|
||||
{:ok, user} ->
|
||||
changeset = Accounts.change_user_registration(user)
|
||||
socket |> assign(trigger_submit: true) |> assign_form(changeset)
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
{:noreply, socket |> assign(check_errors: true) |> assign_form(changeset)}
|
||||
end
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
assign_form(socket, changeset)
|
||||
end
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("validate", %{"user" => user_params}, socket) do
|
||||
|
@ -72,13 +34,31 @@ defmodule Web.UserRegistrationLive do
|
|||
{:noreply, assign_form(socket, Map.put(changeset, :action, :validate))}
|
||||
end
|
||||
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div class="mx-auto max-w-sm">
|
||||
<header class="text-center">finish installation</header>
|
||||
|
||||
<.form
|
||||
for={@form}
|
||||
id="registration_form"
|
||||
phx-submit="save"
|
||||
phx-change="validate"
|
||||
phx-trigger-action={@trigger_submit}
|
||||
action={~p"/admin/users/log_in?_action=registered"}
|
||||
method="post"
|
||||
>
|
||||
<.input field={@form[:username]} type="text" label="username" />
|
||||
<.input field={@form[:password]} type="password" label="password" />
|
||||
<.button type="submit">create administrator</.button>
|
||||
</.form>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
defp assign_form(socket, %Ecto.Changeset{} = changeset) do
|
||||
form = to_form(changeset, as: "user")
|
||||
|
||||
if changeset.valid? do
|
||||
assign(socket, form: form, check_errors: false)
|
||||
else
|
||||
assign(socket, form: form)
|
||||
end
|
||||
assign(socket, form: form)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue