defmodule FreediveWeb.LiliformLive do defmacro __using__(opts) do quote location: :keep, bind_quoted: [opts: opts] do use FreediveWeb, :live_view @behaviour FreediveWeb.LiliformLive @filters_all [ %{ title: "All", icon: "all", active: false, key: :all } ] def(mount(_params, _session, socket)) do items = items() filters = filters() socket = assign(socket, :opts, Keyword.get(unquote(opts), :opts, [])) socket = assign(socket, :items_all, items) socket = assign( socket, :items, FreediveWeb.LiliformLive.filter( items, FreediveWeb.LiliformLive.get_active_filter(filters) ) ) socket = assign(socket, :filters, @filters_all ++ filters) socket = assign(socket, :query, "") {:ok, socket} end def(handle_event("search", %{"value" => query}, socket)) do items = search(query) socket = assign(socket, :items, items) {:noreply, socket} end def(handle_event("filter", %{"key" => key}, socket)) do key = String.to_existing_atom(key) items = FreediveWeb.LiliformLive.filter(socket.assigns.items_all, key) socket = assign(socket, :items, items) socket = assign( socket, :filters, Enum.map(socket.assigns.filters, fn filter -> Map.put(filter, :active, filter.key == key) end) ) {:noreply, socket} end end end @callback items() :: [map] @callback filters() :: [map] @callback search(query :: String.t()) :: [map] def filter(items, key) do case key do :all -> items _ -> Enum.filter(items, fn item -> Map.get(item, key) == true end) end end def get_active_filter(filters) do filters |> Enum.find(& &1.active) |> Map.get(:key) end end