Packages
moon
2.87.3
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/calendar.ex
defmodule Moon.Components.Calendar do
@moduledoc false
use Moon.StatefulComponent
alias Moon.Assets.Icons.IconChevronLeftRounded
alias Moon.Assets.Icons.IconChevronRightRounded
alias Moon.Components.Button
alias Moon.Components.Calendar.Month
alias Moon.Components.Calendar.Week
prop(week_starts_on, :integer, default: 1, values: Enum.to_list(1..7))
prop(events, :list, default: [])
data(date, :datetime, default: Timex.today())
data(show_month, :boolean, default: true)
def render(assigns) do
~F"""
<div class="min-w-min">
<div class="flex items-center mb-6">
<Button class="font-semibold rounded-lg" variant="tertiary" on_click="set_today">
Today
</Button>
<button type="button" class="ml-6" :on-click="shift_range" phx-value-shift={-1}>
<IconChevronLeftRounded class="block" font_size="1rem" />
</button>
<button type="button" class="ml-5 mr-6" :on-click="shift_range" phx-value-shift={1}>
<IconChevronRightRounded class="block" font_size="1rem" />
</button>
<div>
{calendar_title(@date, @week_starts_on, @show_month)}
</div>
<div class="grow text-right">
<Button class="font-semibold rounded-lg" variant="tertiary" on_click="toggle_view">
<span :if={@show_month}>
Month
</span>
<span :if={!@show_month}>
Week
</span>
</Button>
</div>
</div>
<div class="flex text-moon-12 text-center text-trunks">
<div :for={day_name <- days_names(@week_starts_on)} class="flex-1 py-3">
{day_name}
</div>
</div>
<Month :if={@show_month} date={@date} week_starts_on={@week_starts_on} events={@events} />
<Week :if={!@show_month} date={@date} week_starts_on={@week_starts_on} />
</div>
"""
end
defp days_names(weekstart) do
date = Timex.today()
Timex.Interval.new(
from: Timex.beginning_of_week(date, weekstart),
until: Timex.end_of_week(date, weekstart),
left_open: false,
right_open: false
)
|> Enum.map(fn day ->
Timex.format!(day, "%a", :strftime)
end)
end
defp calendar_title(date, _, true), do: Timex.format!(date, "%B %Y", :strftime)
defp calendar_title(date, weekstart, false) do
date
|> Timex.beginning_of_week(weekstart)
|> calendar_title(weekstart, true)
end
def handle_event("set_today", _, socket) do
{:noreply, assign(socket, date: Timex.today())}
end
def handle_event("shift_range", %{"shift" => shift}, socket) do
shift = String.to_integer(shift)
if socket.assigns.show_month do
{:noreply, update(socket, :date, &Timex.shift(&1, months: shift))}
else
{:noreply, update(socket, :date, &Timex.shift(&1, weeks: shift))}
end
end
def handle_event("toggle_view", _, socket) do
date = socket.assigns.date
date =
if socket.assigns.show_month do
Timex.beginning_of_week(date, socket.assigns.week_starts_on)
else
date
end
{:noreply, assign(socket, show_month: !socket.assigns.show_month, date: date)}
end
end