freedive/lib/freedive_web/live/liliform_live.ex

112 lines
3 KiB
Elixir
Raw Normal View History

defmodule FreediveWeb.LiliformLive do
defmacro __using__(opts) do
quote location: :keep, bind_quoted: [opts: opts] do
2024-05-15 22:18:55 +02:00
use FreediveWeb, :live_view
@behaviour FreediveWeb.LiliformLive
2024-05-16 01:47:37 +02:00
@filters_all [
2024-05-16 01:37:36 +02:00
%{
title: "All",
icon: "all",
2024-05-16 02:22:56 +02:00
active: false,
key: :all
2024-05-16 01:37:36 +02:00
}
]
2024-05-16 01:37:36 +02:00
def(mount(_params, _session, socket)) do
2024-05-16 01:47:37 +02:00
items = items()
2024-05-16 02:22:56 +02:00
filters = filters()
2024-05-16 01:37:36 +02:00
socket = assign(socket, :opts, Keyword.get(unquote(opts), :opts, []))
2024-05-16 01:47:37 +02:00
socket = assign(socket, :items_all, items)
socket = assign(socket, :selected_item, nil)
socket = assign(socket, :details, nil)
2024-05-16 02:22:56 +02:00
socket =
assign(
socket,
:items,
FreediveWeb.LiliformLive.filter(
items,
FreediveWeb.LiliformLive.get_active_filter(filters)
)
)
socket = assign(socket, :filters, @filters_all ++ filters)
2024-05-16 01:37:36 +02:00
socket = assign(socket, :query, "")
{:ok, socket}
end
2024-05-16 01:37:36 +02:00
2024-05-16 01:47:37 +02:00
def(handle_event("search", %{"value" => query}, socket)) do
items = search(query)
socket = assign(socket, :items, items)
{:noreply, socket}
end
2024-05-16 02:22:56 +02:00
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
2024-05-15 22:18:55 +02:00
end
end
@callback items() :: [map]
2024-05-16 01:37:36 +02:00
@callback filters() :: [map]
@callback search(query :: String.t()) :: [map]
2024-05-16 02:22:56 +02:00
def filter(items, key) do
case key do
:all ->
items
_ ->
Enum.filter(items, fn {_, item} ->
2024-05-16 02:22:56 +02:00
Map.get(item, key) == true
end)
Enum.into(%{}, items)
2024-05-16 02:22:56 +02:00
end
end
def get_active_filter(filters) do
filters |> Enum.find(& &1.active) |> Map.get(:key)
end
end