lib/tailwind/phoenix/show.ex

defmodule Tailwind.Phoenix.Show do
  @moduledoc """
  Helper to make useful notifications to be used in LiveView show.ex files.

  It implements handle_info/2 LiveView callbacks for events,
  updates the current assigns if the notified object matches
  and redirects to the given URL-function if the current item gets deleted.

  The to function gets passed the socket as first and only parameter.
  This way you can use any assign in the socket to use the correct Route-helper.

  ## Examples

  ```elixir
  defmodule MyWeb.MyDataLive.Show do
    use MyWeb, :live_view

    use Tailwind.Phoenix.Show,
      notifier: MyWeb.Notifier,
      key: :data,
      pattern: %My.MyData{},
      to: &Routes.my_data_path(&1, :index)

    ...
  end
  ```
  """

  @doc """
  When used, implements handle_info/2 for show.ex
  """
  defmacro __using__(opts) do
    notifier = Keyword.get(opts, :notifier)
    assign_key = Keyword.get(opts, :key)
    data_pattern = Keyword.get(opts, :pattern)
    return_to_fn = Keyword.get(opts, :to)

    quote do
      @impl true
      def handle_info({:updated, unquote(data_pattern) = data} = msg, socket) do
        {:noreply,
         socket
         |> unquote(notifier).to_flash(msg)
         |> Tailwind.Phoenix.update_if_id(
           unquote(assign_key),
           socket.assigns[unquote(assign_key)].id,
           data
         )}
      end

      @impl true
      def handle_info({:deleted, unquote(data_pattern) = data} = msg, socket) do
        to = unquote(return_to_fn).(socket)

        {:noreply,
         socket
         |> Tailwind.Phoenix.redirect_if_id(socket.assigns[unquote(assign_key)].id, data, to: to)
         |> unquote(notifier).to_flash(msg)}
      end

      defdelegate handle_info(msg, socket), to: unquote(notifier)
    end
  end
end