111 lines
3 KiB
Elixir
111 lines
3 KiB
Elixir
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, :selected_item, nil)
|
|
socket = assign(socket, :details, nil)
|
|
|
|
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
|
|
|
|
def(handle_event("tap", %{"name" => item_name}, socket)) do
|
|
# 1 tap to select, 2 taps for details
|
|
item = socket.assigns.items[item_name]
|
|
socket =
|
|
case socket.assigns.selected_item do
|
|
nil ->
|
|
assign(socket, :selected_item, item)
|
|
|
|
selected ->
|
|
case selected.name == item_name do
|
|
true ->
|
|
case socket.assigns.details do
|
|
nil ->
|
|
assign(socket, :details, true)
|
|
|
|
_ ->
|
|
assign(socket, %{selected_item: item, details: nil})
|
|
end
|
|
|
|
false ->
|
|
assign(socket, %{selected_item: item, details: nil})
|
|
end
|
|
end
|
|
IO.inspect(socket.assigns.selected_item, label: "selected_item")
|
|
IO.inspect(socket.assigns.details, label: "details")
|
|
{: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)
|
|
Enum.into(%{}, items)
|
|
end
|
|
end
|
|
|
|
def get_active_filter(filters) do
|
|
filters |> Enum.find(& &1.active) |> Map.get(:key)
|
|
end
|
|
end
|