defmodule SpazioSolazzoWeb.CalendarLiveComponent do @moduledoc """ LiveView component for rendering booking calendars. """ use SpazioSolazzoWeb, :live_component # There are 7 days displayed in the calendar @grid_cols 7 # The calendar can show max 6 weeks for one month @grid_rows 6 def update(assigns, socket) do # Initialize navigation date to today's month if not already viewing a month beginning_of_month = socket.assigns[:beginning_of_month] || Date.utc_today() |> Date.beginning_of_month() selected_date = assigns[:selected_date] || Date.utc_today() {:ok, socket |> assign(assigns) |> assign(:beginning_of_month, beginning_of_month) |> assign(:selected_date, selected_date) |> assign(:today, Date.utc_today()) |> assign_calendar_grid()} end def handle_event("prev-month", _params, socket) do new_beginning_of_month = socket.assigns.beginning_of_month |> Date.shift(month: -1) |> Date.beginning_of_month() {:noreply, socket |> assign(:beginning_of_month, new_beginning_of_month) |> assign_calendar_grid()} end def handle_event("next-month", _params, socket) do new_beginning_of_month = socket.assigns.beginning_of_month |> Date.shift(month: 1) |> Date.beginning_of_month() {:noreply, socket |> assign(:beginning_of_month, new_beginning_of_month) |> assign_calendar_grid()} end def handle_event("select-date", %{"date" => date_str}, socket) do date = Date.from_iso8601!(date_str) send(self(), {:date_selected, date}) {:noreply, assign(socket, :selected_date, date)} end defp assign_calendar_grid(socket) do first = socket.assigns.beginning_of_month # Calculate offset to start grid on Monday (Monday = 1) day_of_week = Date.day_of_week(socket.assigns.beginning_of_month) days_before = day_of_week - 1 start_date = Date.add(first, -days_before) grid = Enum.map(0..(@grid_cols * @grid_rows - 1), fn n -> Date.add(start_date, n) end) assign(socket, :grid, grid) end def render(assigns) do ~H"""

{Calendar.strftime(@beginning_of_month, "%B %Y")}

MoTuWeThFrSaSu
<%= for date <- @grid do %> <% is_selected = Date.compare(date, @selected_date) == :eq is_past = Date.compare(date, @today) == :lt is_beginning_of_month = date.month == @beginning_of_month.month %> <%= if is_beginning_of_month do %> <% else %>
<% end %> <% end %>
""" end end