97 lines
3.4 KiB
Elixir
97 lines
3.4 KiB
Elixir
defmodule MvWeb.Components.ExportDropdown do
|
|
@moduledoc """
|
|
Export dropdown component for member export (CSV/PDF).
|
|
|
|
Provides an accessible dropdown menu with CSV and PDF export options.
|
|
Uses the same export payload as the previous single-button export.
|
|
"""
|
|
use MvWeb, :live_component
|
|
use Gettext, backend: MvWeb.Gettext
|
|
|
|
@impl true
|
|
def mount(socket) do
|
|
{:ok, assign(socket, :open, false)}
|
|
end
|
|
|
|
@impl true
|
|
def update(assigns, socket) do
|
|
socket =
|
|
socket
|
|
|> assign(:id, assigns.id)
|
|
|> assign(:export_payload_json, assigns[:export_payload_json] || "")
|
|
|> assign(:selected_count, assigns[:selected_count] || 0)
|
|
|
|
{:ok, socket}
|
|
end
|
|
|
|
@impl true
|
|
def render(assigns) do
|
|
button_label =
|
|
gettext("Export") <>
|
|
" (" <>
|
|
(if assigns.selected_count == 0, do: gettext("all"), else: to_string(assigns.selected_count)) <>
|
|
")"
|
|
|
|
assigns = assign(assigns, :button_label, button_label)
|
|
|
|
~H"""
|
|
<div id={@id} data-testid="export-dropdown" class="flex-auto flex-wrap">
|
|
<.dropdown_menu
|
|
id={"#{@id}-menu"}
|
|
button_label={@button_label}
|
|
icon="hero-arrow-down-tray"
|
|
open={@open}
|
|
phx_target={@myself}
|
|
menu_width="w-48"
|
|
menu_align="left"
|
|
button_class="btn-secondary gap-2"
|
|
testid="export-dropdown"
|
|
button_testid="export-dropdown-button"
|
|
menu_testid="export-dropdown-menu"
|
|
>
|
|
<li role="none">
|
|
<form method="post" action={~p"/members/export.csv"} target="_blank" class="w-full">
|
|
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
|
|
<input type="hidden" name="payload" value={@export_payload_json} />
|
|
<button
|
|
type="submit"
|
|
role="menuitem"
|
|
class="flex items-center gap-2 px-2 py-1 rounded cursor-pointer hover:bg-base-200 w-full text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-base-content/20 focus-visible:ring-inset"
|
|
aria-label={gettext("Export members to CSV")}
|
|
data-testid="export-csv-link"
|
|
>
|
|
<.icon name="hero-document-arrow-down" class="h-4 w-4" />
|
|
<span>{gettext("CSV")}</span>
|
|
</button>
|
|
</form>
|
|
</li>
|
|
<li role="none">
|
|
<form method="post" action={~p"/members/export.pdf"} target="_blank" class="w-full">
|
|
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
|
|
<input type="hidden" name="payload" value={@export_payload_json} />
|
|
<button
|
|
type="submit"
|
|
role="menuitem"
|
|
class="flex items-center gap-2 px-2 py-1 rounded cursor-pointer hover:bg-base-200 w-full text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-base-content/20 focus-visible:ring-inset"
|
|
aria-label={gettext("Export members to PDF")}
|
|
data-testid="export-pdf-link"
|
|
>
|
|
<.icon name="hero-document-text" class="h-4 w-4" />
|
|
<span>{gettext("PDF")}</span>
|
|
</button>
|
|
</form>
|
|
</li>
|
|
</.dropdown_menu>
|
|
</div>
|
|
"""
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("toggle_dropdown", _params, socket) do
|
|
{:noreply, assign(socket, :open, !socket.assigns.open)}
|
|
end
|
|
|
|
def handle_event("close_dropdown", _params, socket) do
|
|
{:noreply, assign(socket, :open, false)}
|
|
end
|
|
end
|