Packages
moon
2.89.4
2.90.5
retired
2.90.4
2.90.3
2.90.2
2.90.1
2.90.0
2.89.4
2.89.1
2.89.0
2.88.0
2.87.11
2.87.10
2.87.9
2.87.8
2.87.7
2.87.6
2.87.5
2.87.4
2.87.3
2.87.2
2.87.1
2.87.0
2.86.1
2.86.0
2.85.1
2.85.0
2.84.0
2.83.0
2.82.0
2.81.4
2.81.3
2.81.2
2.81.1
2.81.0
2.80.2
2.80.1
2.80.0
2.79.13
2.79.12
2.79.11
2.79.10
2.79.9
2.79.8
2.79.7
2.79.6
2.79.5
2.79.4
2.79.3
2.79.2
2.79.1
2.79.0
2.78.4
2.78.3
2.78.2
2.78.1
2.78.0
2.77.0
2.76.5
2.76.4
2.76.3
2.76.2
2.76.1
2.76.0
2.75.0
2.74.1
2.74.0
2.73.8
2.73.7
2.73.6
2.73.5
2.73.4
2.73.3
2.73.2
2.73.1
2.73.0
2.72.5
2.72.4
2.72.3
2.72.2
2.72.1
2.72.0
2.71.1
2.71.0
2.70.0
2.69.2
2.69.1
2.69.0
2.68.11
2.68.10
Components-based design system written in elixir
Current section
Files
Jump to
Current section
Files
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