Current section

Files

Jump to
moon lib moon components line_chart_card.ex
Raw

lib/moon/components/line_chart_card.ex

defmodule Moon.Components.LineChartCard do
@moduledoc false
use Moon.StatefulComponent
alias Moon.Assets.Icons.IconRefresh
alias Moon.Components.LineChart
alias Moon.Components.Select
prop(title, :string, required: true)
prop(select_options, :list, default: [])
prop(filters, :list, default: [])
prop(values, :list, default: [])
prop(time_format, :string, default: "%d/%m")
def render(assigns) do
~F"""
<div class="bg-goku p-6 rounded-sm">
<div class="flex items-center mt-0.5 mb-6">
<div class="grow text-moon-20 text-bulma">
{@title}
</div>
<div class="flex-none" :if={length(@select_options) > 0}>
<Select options={@select_options} class="pl-2 rounded-sm text-moon-12 text-trunks bg-gohan" />
</div>
<button type="button" class="flex-none ml-3 p-2">
<IconRefresh class="block text-trunks" />
</button>
</div>
{#if length(@filters) > 0}
<div class="flex gap-x-3 mb-5 overflow-x-scroll">
<button
:for={filter <- @filters}
class={
"p-3 font-normal text-left rounded-sm hover:bg-gohan",
"bg-goku": !filter.is_active,
"bg-gohan": filter.is_active
}
style="min-width: 120px;"
type="button"
:on-click="toggle_filter"
phx-value-name={filter.data_key}
>
<p class="text-trunks text-moon-12">{filter.label}</p>
<p class="text-bulma text-moon-20">{filter.value}</p>
</button>
</div>
{/if}
<LineChart
id="line-chart"
width="container"
values={filter_values(@values, @filters)}
{=@time_format}
/>
</div>
"""
end
def handle_event("toggle_filter", %{"name" => filter_data_key}, socket) do
filters =
Enum.map(socket.assigns.filters, fn item ->
if item.data_key == filter_data_key do
%{item | is_active: !item.is_active}
else
item
end
end)
socket =
if filters |> only_active() |> Enum.empty?() do
socket
else
socket
|> assign(filters: filters)
|> push_event("vega_lite:line-chart:redraw", %{
"data" => filter_values(socket.assigns.values, filters)
})
end
{:noreply, socket}
end
defp filter_values(values, filters) do
active_filters = active_filters_keys(filters)
Enum.filter(values, fn item ->
item.category in active_filters
end)
end
defp active_filters_keys(filters) do
filters
|> only_active()
|> Enum.map(& &1.data_key)
end
defp only_active(filters), do: Enum.filter(filters, & &1.is_active)
end