defmodule LiveAdmin.Components.Container.Form.SearchSelect do
use Phoenix.LiveComponent
use Phoenix.HTML
import LiveAdmin, only: [record_label: 2]
alias LiveAdmin.Resource
@impl true
def mount(socket) do
{:ok, assign(socket, :options, [])}
end
@impl true
def update(assigns = %{resource: resource, form: form, field: field}, socket) do
selected_option =
form
|> input_value(field)
|> case do
nil -> nil
"" -> nil
id -> Resource.find!(id, resource, assigns.session[:__prefix__])
end
socket =
socket
|> assign(assigns)
|> assign(:selected_option, selected_option)
{:ok, socket}
end
@impl true
def update(assigns, socket) do
{:ok, assign(socket, assigns)}
end
@impl true
def render(assigns = %{disabled: true}) do
~H"""
<div>
<span class="resource__action--disabled">
<%= if @selected_option do %>
<%= record_label(@selected_option, @config) %>
<% else %>
None
<% end %>
</span>
</div>
"""
end
@impl true
def render(assigns) do
~H"""
<div>
<div class="resource__action--drop">
<%= hidden_input(@form, @field, disabled: @disabled) %>
<%= if @selected_option do %>
<a
href="#"
phx-click="put_change"
phx-value-field={@field}
phx-target={@form_ref}
class="resource__action--btn"
>
<%= record_label(@selected_option, @config) %>
</a>
<% else %>
<%= text_input(:search, :select,
id: input_id(@form, @field) <> "search_select",
disabled: @disabled,
placeholder: "Search",
phx_focus: "load_options",
phx_keyup: "load_options",
phx_target: @myself,
phx_debounce: 200,
autocomplete: "off"
) %>
<% end %>
<%= unless @selected_option do %>
<nav>
<ul>
<%= if Enum.empty?(@options) do %>
<li>No options</li>
<% end %>
<%= for option <- @options, option.id != input_value(@form, @field) do %>
<li>
<a
href="#"
phx-click="put_change"
phx-value-field={@field}
phx-value-value={option.id}
phx-target={@form_ref}
>
<%= record_label(option, @config) %>
</a>
</li>
<% end %>
</ul>
</nav>
<% end %>
</div>
</div>
"""
end
@impl true
def handle_event(
"load_options",
%{"value" => q},
socket = %{assigns: %{resource: resource, config: config, session: session}}
) do
options =
resource
|> Resource.list(config, [search: q], session)
|> elem(0)
{:noreply, assign(socket, :options, options)}
end
end