Files

134 lines
4.0 KiB
Elixir

defmodule DexiWeb.ProfileLive do
use DexiWeb, :live_view
alias Dexi.Accounts
alias Dexi.Accounts.Scope
alias DexiWeb.AccountComponents
@impl true
def mount(_params, _session, socket) do
{:ok,
socket
|> assign(:page_title, "Account")
|> assign(:editing?, false)
|> assign_account(socket.assigns.current_scope.user)}
end
@impl true
def handle_event("edit-profile", _params, socket) do
{:noreply, assign(socket, :editing?, true)}
end
def handle_event("cancel-edit", _params, socket) do
{:noreply,
socket
|> assign(:editing?, false)
|> assign(:form, to_form(Accounts.change_profile(socket.assigns.current_scope.user)))}
end
def handle_event("validate", %{"user" => params}, socket) do
form =
socket.assigns.current_scope.user
|> Accounts.change_profile(params)
|> Map.put(:action, :validate)
|> to_form()
{:noreply, assign(socket, :form, form)}
end
def handle_event("save", %{"user" => params}, socket) do
case Accounts.update_profile(socket.assigns.current_scope.user, params) do
{:ok, user} ->
{:noreply,
socket
|> assign_account(user)
|> assign(:editing?, false)
|> put_flash(:info, "Account saved.")}
{:error, changeset} ->
{:noreply, assign(socket, :form, to_form(changeset))}
end
end
def handle_event("send-confirmation", _params, socket) do
user = socket.assigns.current_scope.user
{:noreply, send_confirmation(socket, user)}
end
def handle_event("confirm-email", %{"confirmation" => %{"code" => code}}, socket) do
case Accounts.confirm_email(socket.assigns.current_scope.user, code) do
{:ok, user} ->
{:noreply,
socket
|> assign_account(user)
|> put_flash(:info, "Email confirmed.")}
{:error, :expired} ->
{:noreply, put_flash(socket, :error, "That code expired. Request a new one.")}
{:error, _reason} ->
{:noreply, put_flash(socket, :error, "That confirmation code is invalid.")}
end
end
@impl true
def render(assigns) do
~H"""
<Layouts.app flash={@flash} current_scope={@current_scope}>
<section class={["mx-auto max-w-2xl px-5 py-16 sm:py-24"]}>
<p class={["text-xs font-black uppercase tracking-[0.28em] text-blue-grey"]}>Account</p>
<h1 class={["mt-3 text-4xl font-black tracking-[-0.05em] sm:text-5xl"]}>Your details</h1>
<p class={["mt-4 text-blue-grey"]}>
Your public key is your identity. Email and name are optional.
</p>
<div class={[
"mt-8 rounded-3xl border border-muted-steel bg-slate-blue p-6 shadow-cyan-glow sm:p-8"
]}>
<AccountComponents.account_preview
:if={!@editing?}
user={@current_scope.user}
/>
<AccountComponents.profile_editor :if={@editing?} form={@form} />
<AccountComponents.email_confirmation_panel
user={@current_scope.user}
form={@confirmation_form}
/>
</div>
</section>
</Layouts.app>
"""
end
defp assign_account(socket, user) do
user =
case Accounts.clear_expired_email_confirmation(user) do
{:ok, refreshed_user} -> refreshed_user
{:error, _reason} -> user
end
socket
|> assign(:current_scope, Scope.for_user(user))
|> assign(:form, to_form(Accounts.change_profile(user)))
|> assign(:confirmation_form, to_form(%{"code" => ""}, as: :confirmation))
end
defp send_confirmation(socket, user) do
case Accounts.request_email_confirmation(user) do
{:ok, updated_user} ->
socket
|> assign_account(updated_user)
|> put_flash(:info, "Confirmation code sent.")
{:error, :rate_limited} ->
put_flash(socket, :error, "Please wait one minute before requesting another code.")
{:error, :already_confirmed} ->
put_flash(socket, :info, "That email is already confirmed.")
{:error, _reason} ->
put_flash(socket, :error, "The confirmation email could not be sent.")
end
end
end