mirror of
https://codeberg.org/JasterV/spazio-solazzo.git
synced 2026-04-26 18:20:03 +00:00
180 lines
5.5 KiB
Elixir
180 lines
5.5 KiB
Elixir
defmodule SpazioSolazzoWeb.Admin.WalkInLive do
|
|
@moduledoc """
|
|
Admin walk-in booking tool for the coworking space.
|
|
"""
|
|
|
|
use SpazioSolazzoWeb, :live_view
|
|
alias SpazioSolazzo.BookingSystem
|
|
|
|
def mount(_params, _session, socket) do
|
|
{:ok, space} = BookingSystem.get_space_by_slug("coworking")
|
|
|
|
today = Date.utc_today()
|
|
first_day = Date.beginning_of_month(today)
|
|
booking_counts = fetch_booking_counts(space.id, first_day)
|
|
|
|
if connected?(socket) do
|
|
Phoenix.PubSub.subscribe(SpazioSolazzo.PubSub, "booking:created")
|
|
Phoenix.PubSub.subscribe(SpazioSolazzo.PubSub, "booking:approved")
|
|
Phoenix.PubSub.subscribe(SpazioSolazzo.PubSub, "booking:cancelled")
|
|
Phoenix.PubSub.subscribe(SpazioSolazzo.PubSub, "booking:rejected")
|
|
end
|
|
|
|
{:ok,
|
|
assign(socket,
|
|
space: space,
|
|
first_day_of_month: first_day,
|
|
booking_counts: booking_counts,
|
|
start_date: nil,
|
|
end_date: nil,
|
|
start_time: ~T[09:00:00],
|
|
end_time: ~T[18:00:00],
|
|
multi_day_mode: false,
|
|
customer_details_form: customer_details_form()
|
|
)}
|
|
end
|
|
|
|
def handle_event("update_start_time", %{"value" => time_str}, socket) do
|
|
case Time.from_iso8601(time_str <> ":00") do
|
|
{:ok, time} -> {:noreply, assign(socket, start_time: time)}
|
|
_ -> {:noreply, socket}
|
|
end
|
|
end
|
|
|
|
def handle_event("update_end_time", %{"value" => time_str}, socket) do
|
|
case Time.from_iso8601(time_str <> ":00") do
|
|
{:ok, time} -> {:noreply, assign(socket, end_time: time)}
|
|
_ -> {:noreply, socket}
|
|
end
|
|
end
|
|
|
|
def handle_event("validate_customer_details", form, socket) do
|
|
{:noreply, assign(socket, customer_details_form: to_form(form))}
|
|
end
|
|
|
|
def handle_event("create_booking", _, %{assigns: %{start_date: s, end_date: e}} = socket)
|
|
when is_nil(s) or is_nil(e) do
|
|
{:noreply, put_flash(socket, :error, "Please fill in all required fields and select a date")}
|
|
end
|
|
|
|
def handle_event("create_booking", form, socket) do
|
|
case parse_submitted_form(form) do
|
|
{:error, error} -> {:noreply, put_flash(socket, :error, error)}
|
|
{:ok, form} -> create_walk_in(form, socket)
|
|
end
|
|
end
|
|
|
|
def handle_info({:change_month, new_date}, socket) do
|
|
booking_counts = fetch_booking_counts(socket.assigns.space.id, new_date)
|
|
{:noreply, assign(socket, first_day_of_month: new_date, booking_counts: booking_counts)}
|
|
end
|
|
|
|
def handle_info({:date_selected, start_date, end_date}, socket) do
|
|
{:noreply, assign(socket, start_date: start_date, end_date: end_date)}
|
|
end
|
|
|
|
def handle_info({:multi_day_mode_toggle, mode}, socket) do
|
|
{:noreply, assign(socket, multi_day_mode: mode)}
|
|
end
|
|
|
|
def handle_info(%{topic: "booking:" <> _}, socket) do
|
|
booking_counts =
|
|
fetch_booking_counts(socket.assigns.space.id, socket.assigns.first_day_of_month)
|
|
|
|
{:noreply, assign(socket, booking_counts: booking_counts)}
|
|
end
|
|
|
|
def handle_info(_msg, socket) do
|
|
{:noreply, socket}
|
|
end
|
|
|
|
defp fetch_booking_counts(space_id, date) do
|
|
start_dt = DateTime.new!(Date.beginning_of_month(date), ~T[00:00:00])
|
|
end_dt = DateTime.new!(Date.end_of_month(date), ~T[23:59:59])
|
|
|
|
{:ok, bookings} =
|
|
BookingSystem.search_bookings(
|
|
space_id,
|
|
start_dt,
|
|
end_dt,
|
|
[:accepted],
|
|
[:start_datetime, :end_datetime]
|
|
)
|
|
|
|
Enum.reduce(bookings, %{}, fn booking, acc ->
|
|
range =
|
|
Date.range(
|
|
DateTime.to_date(booking.start_datetime),
|
|
DateTime.to_date(booking.end_datetime)
|
|
)
|
|
|
|
Enum.reduce(range, acc, fn d, count_acc ->
|
|
Map.update(count_acc, d, 1, &(&1 + 1))
|
|
end)
|
|
end)
|
|
end
|
|
|
|
defp create_walk_in(form, socket) do
|
|
%{
|
|
start_date: start_date,
|
|
end_date: end_date,
|
|
start_time: start_time,
|
|
end_time: end_time,
|
|
space: space
|
|
} = socket.assigns
|
|
|
|
start_datetime = DateTime.new!(start_date, start_time, "Etc/UTC")
|
|
end_datetime = DateTime.new!(end_date, end_time, "Etc/UTC")
|
|
|
|
case BookingSystem.create_walk_in(
|
|
space.id,
|
|
start_datetime,
|
|
end_datetime,
|
|
form.customer_name,
|
|
form.customer_email,
|
|
form.customer_phone
|
|
) do
|
|
{:ok, _booking} ->
|
|
SpazioSolazzoWeb.Admin.AdminCalendarComponent.reset("walk-in-calendar")
|
|
|
|
{:noreply,
|
|
socket
|
|
|> assign(
|
|
customer_details_form: customer_details_form(),
|
|
start_date: nil,
|
|
end_date: nil
|
|
)
|
|
|> put_flash(:info, "Walk-in booking created successfully")}
|
|
|
|
{:error, error} ->
|
|
{:noreply, put_flash(socket, :error, "Failed to create walk-in: #{inspect(error)}")}
|
|
end
|
|
end
|
|
|
|
defp parse_submitted_form(%{
|
|
"customer_name" => name,
|
|
"customer_email" => email,
|
|
"customer_phone" => phone
|
|
}) do
|
|
name = String.trim(name)
|
|
email = String.trim(email)
|
|
phone = String.trim(phone)
|
|
|
|
if name == "" || email == "" do
|
|
{:error, "Please fill in all required fields and select a date"}
|
|
else
|
|
{:ok, %{customer_name: name, customer_email: email, customer_phone: phone}}
|
|
end
|
|
end
|
|
|
|
defp days_selected(nil, nil), do: 0
|
|
defp days_selected(start_date, nil) when not is_nil(start_date), do: 1
|
|
|
|
defp days_selected(start_date, end_date) when not is_nil(start_date) and not is_nil(end_date),
|
|
do: Date.diff(end_date, start_date) + 1
|
|
|
|
defp days_selected(_, _), do: 0
|
|
|
|
defp customer_details_form(),
|
|
do: to_form(%{"customer_name" => "", "customer_email" => "", "customer_phone" => ""})
|
|
end
|