diff --git a/lib/mv_web/live/user_live/form.ex b/lib/mv_web/live/user_live/form.ex new file mode 100644 index 0000000..53d7af7 --- /dev/null +++ b/lib/mv_web/live/user_live/form.ex @@ -0,0 +1,80 @@ +defmodule MvWeb.UserLive.Form do + use MvWeb, :live_view + + @impl true + def render(assigns) do + ~H""" + + <.header> + {@page_title} + <:subtitle>Use this form to manage user records in your database. + + + <.form for={@form} id="user-form" phx-change="validate" phx-submit="save"> + <.button phx-disable-with="Saving..." variant="primary">Save User + <.button navigate={return_path(@return_to, @user)}>Cancel + + + """ + end + + @impl true + def mount(params, _session, socket) do + user = + case params["id"] do + nil -> nil + id -> Ash.get!(Mv.Accounts.User, id) + end + + action = if is_nil(user), do: "New", else: "Edit" + page_title = action <> " " <> "User" + + {:ok, + socket + |> assign(:return_to, return_to(params["return_to"])) + |> assign(user: user) + |> assign(:page_title, page_title) + |> assign_form()} + end + + defp return_to("show"), do: "show" + defp return_to(_), do: "index" + + @impl true + def handle_event("validate", %{"user" => user_params}, socket) do + {:noreply, assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, user_params))} + end + + def handle_event("save", %{"user" => user_params}, socket) do + case AshPhoenix.Form.submit(socket.assigns.form, params: user_params) do + {:ok, user} -> + notify_parent({:saved, user}) + + socket = + socket + |> put_flash(:info, "User #{socket.assigns.form.source.type}d successfully") + |> push_navigate(to: return_path(socket.assigns.return_to, user)) + + {:noreply, socket} + + {:error, form} -> + {:noreply, assign(socket, form: form)} + end + end + + defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) + + defp assign_form(%{assigns: %{user: user}} = socket) do + form = + if user do + AshPhoenix.Form.for_update(user, :update, as: "user") + else + AshPhoenix.Form.for_create(Mv.Accounts.User, :create, as: "user") + end + + assign(socket, form: to_form(form)) + end + + defp return_path("index", _user), do: ~p"/users" + defp return_path("show", user), do: ~p"/users/#{user.id}" +end diff --git a/lib/mv_web/live/user_live/index.ex b/lib/mv_web/live/user_live/index.ex new file mode 100644 index 0000000..47fee2f --- /dev/null +++ b/lib/mv_web/live/user_live/index.ex @@ -0,0 +1,62 @@ +defmodule MvWeb.UserLive.Index do + use MvWeb, :live_view + + @impl true + def render(assigns) do + ~H""" + + <.header> + Listing Users + <:actions> + <.button variant="primary" navigate={~p"/users/new"}> + <.icon name="hero-plus" /> New User + + + + + <.table + id="users" + rows={@streams.users} + row_click={fn {_id, user} -> JS.navigate(~p"/users/#{user}") end} + > + <:col :let={{_id, user}} label="Id">{user.id} + + <:col :let={{_id, user}} label="Email">{user.email} + + <:action :let={{_id, user}}> +
+ <.link navigate={~p"/users/#{user}"}>Show +
+ + <.link navigate={~p"/users/#{user}/edit"}>Edit + + + <:action :let={{id, user}}> + <.link + phx-click={JS.push("delete", value: %{id: user.id}) |> hide("##{id}")} + data-confirm="Are you sure?" + > + Delete + + + +
+ """ + end + + @impl true + def mount(_params, _session, socket) do + {:ok, + socket + |> assign(:page_title, "Listing Users") + |> stream(:users, Ash.read!(Mv.Accounts.User))} + end + + @impl true + def handle_event("delete", %{"id" => id}, socket) do + user = Ash.get!(Mv.Accounts.User, id) + Ash.destroy!(user) + + {:noreply, stream_delete(socket, :users, user)} + end +end diff --git a/lib/mv_web/live/user_live/show.ex b/lib/mv_web/live/user_live/show.ex new file mode 100644 index 0000000..f2fa602 --- /dev/null +++ b/lib/mv_web/live/user_live/show.ex @@ -0,0 +1,38 @@ +defmodule MvWeb.UserLive.Show do + use MvWeb, :live_view + + @impl true + def render(assigns) do + ~H""" + + <.header> + User {@user.id} + <:subtitle>This is a user record from your database. + + <:actions> + <.button navigate={~p"/users"}> + <.icon name="hero-arrow-left" /> + + <.button variant="primary" navigate={~p"/users/#{@user}/edit?return_to=show"}> + <.icon name="hero-pencil-square" /> Edit User + + + + + <.list> + <:item title="Id">{@user.id} + + <:item title="Email">{@user.email} + + + """ + end + + @impl true + def mount(%{"id" => id}, _session, socket) do + {:ok, + socket + |> assign(:page_title, "Show User") + |> assign(:user, Ash.get!(Mv.Accounts.User, id))} + end +end diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex index 75210b0..696a491 100644 --- a/lib/mv_web/router.ex +++ b/lib/mv_web/router.ex @@ -67,6 +67,12 @@ defmodule MvWeb.Router do live "/properties/:id", PropertyLive.Show, :show live "/properties/:id/show/edit", PropertyLive.Show, :edit + live "/users", UserLive.Index, :index + live "/users/new", UserLive.Form, :new + live "/users/:id/edit", UserLive.Form, :edit + live "/users/:id", UserLive.Show, :show + live "/users/:id/show/edit", UserLive.Show, :edit + post "/set_locale", LocaleController, :set_locale end