defmodule MvWeb.MemberLive.Index do use MvWeb, :live_view import Ash.Expr import Ash.Query import MvWeb.TableComponents @impl true def mount(_params, _session, socket) do members = Ash.read!(Mv.Membership.Member) sorted = Enum.sort_by(members, & &1.first_name) {:ok, socket |> assign(:page_title, gettext("Members")) |> assign(:query, "") |> assign(:sort_field, :first_name) |> assign(:sort_order, :asc) |> assign(:members, sorted) |> assign(:selected_members, [])} end # ----------------------------------------------------------------- # Receive messages from any toolbar component # ----------------------------------------------------------------- # Function to handle search @impl true def handle_info({:search_changed, q}, socket) do members = if String.trim(q) == "" do Ash.read!(Mv.Membership.Member) else Mv.Membership.Member |> filter(expr(fragment("search_vector @@ plainto_tsquery('simple', ?)", ^q))) |> Ash.read!() end {:noreply, socket |> assign(:query, q) |> assign(:members, members)} end # ----------------------------------------------------------------- # Handle Events # ----------------------------------------------------------------- @impl true def handle_event("delete", %{"id" => id}, socket) do member = Ash.get!(Mv.Membership.Member, id) Ash.destroy!(member) {:noreply, stream_delete(socket, :members, member)} end # Selects one member in the list of members @impl true def handle_event("select_member", %{"id" => id}, socket) do selected = if id in socket.assigns.selected_members do List.delete(socket.assigns.selected_members, id) else [id | socket.assigns.selected_members] end {:noreply, assign(socket, :selected_members, selected)} end # Sorts the list of members according to a field, when you click on the column header @impl true def handle_event("sort", %{"field" => field_str}, socket) do members = socket.assigns.members field = String.to_existing_atom(field_str) new_order = if socket.assigns.sort_field == field do toggle_order(socket.assigns.sort_order) else :asc end sorted_members = members |> Enum.sort_by(&Map.get(&1, field), sort_fun(new_order)) {:noreply, socket |> assign(:sort_field, field) |> assign(:sort_order, new_order) |> assign(:members, sorted_members)} end # Selects all members in the list of members @impl true def handle_event("select_all", _params, socket) do members = socket.assigns.members all_ids = Enum.map(members, & &1.id) selected = if Enum.sort(socket.assigns.selected_members) == Enum.sort(all_ids) do [] else all_ids end {:noreply, assign(socket, :selected_members, selected)} end defp toggle_order(:asc), do: :desc defp toggle_order(:desc), do: :asc defp sort_fun(:asc), do: &<=/2 defp sort_fun(:desc), do: &>=/2 end