spazio-solazzo/lib/spazio_solazzo_web/live/booking/space_booking_live.ex
Víctor Martínez 69f992f8f6
feat: new booking system + admin dashboard (#12)
feat: implement a new booking system and admin dashboard
2026-02-07 19:08:39 +01:00

148 lines
4.2 KiB
Elixir

defmodule SpazioSolazzoWeb.SpaceBookingLive do
use SpazioSolazzoWeb, :live_view
alias SpazioSolazzo.BookingSystem
import SpazioSolazzoWeb.BookingComponents
def mount(%{"space_slug" => space_slug}, _session, socket) do
case BookingSystem.get_space_by_slug(space_slug) do
{:ok, space} ->
selected_date = Date.utc_today()
current_user = socket.assigns[:current_user]
time_slots = load_time_slots_with_stats(space, selected_date, current_user)
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,
socket
|> assign(
space: space,
selected_date: selected_date,
selected_time_slot: nil,
show_booking_modal: false,
show_success_modal: false,
time_slots: time_slots
)}
{:error, _error} ->
{:ok,
socket
|> put_flash(:error, "Space not found")
|> push_navigate(to: "/")}
end
end
def handle_event("select_slot", %{"time_slot_id" => time_slot_id}, socket) do
time_slot = Enum.find(socket.assigns.time_slots, &(&1.id == time_slot_id))
{:noreply, assign(socket, selected_time_slot: time_slot, show_booking_modal: true)}
end
def handle_event("cancel_booking", _params, socket) do
{:noreply, assign(socket, show_booking_modal: false)}
end
def handle_event("close_success_modal", _params, socket) do
{:noreply, assign(socket, show_success_modal: false)}
end
def handle_info({:create_booking, booking_data}, socket) do
case parse_booking_data(booking_data) do
{:error, error} -> {:noreply, put_flash(socket, :error, error)}
{:ok, booking_data} -> create_booking(booking_data, socket)
end
end
def handle_info({:date_selected, date}, socket) do
time_slots =
load_time_slots_with_stats(socket.assigns.space, date, socket.assigns.current_user)
{:noreply,
socket
|> assign(
selected_date: date,
time_slots: time_slots
)}
end
def handle_info(
%{topic: "booking:" <> _event, payload: %{data: %{space_id: space_id, date: date}}},
%{assigns: %{space: %{id: space_id}, selected_date: date}} = socket
) do
time_slots =
load_time_slots_with_stats(socket.assigns.space, date, socket.assigns.current_user)
{:noreply,
socket
|> assign(time_slots: time_slots)}
end
def handle_info(_msg, socket) do
{:noreply, socket}
end
defp create_booking(booking_data, socket) do
current_user = socket.assigns.current_user
result =
BookingSystem.create_booking(
socket.assigns.space.id,
current_user.id,
socket.assigns.selected_date,
socket.assigns.selected_time_slot.start_time,
socket.assigns.selected_time_slot.end_time,
booking_data.customer_name,
current_user.email,
booking_data.customer_phone,
booking_data.customer_comment
)
case result do
{:ok, _booking} ->
{:noreply,
socket
|> assign(
show_booking_modal: false,
show_success_modal: true
)}
{:error, _error} ->
{:noreply,
socket
|> assign(show_booking_modal: false)
|> put_flash(:error, "Failed to create booking request.")}
end
end
defp parse_booking_data(%{customer_name: ""}) do
{:error, "Please fill all the required fields to create a booking request."}
end
defp parse_booking_data(
%{
customer_name: _,
customer_phone: _,
customer_comment: _
} = form
) do
{:ok, form}
end
defp load_time_slots_with_stats(space, date, current_user) do
BookingSystem.get_space_time_slots_by_date!(space.id, date,
load: [
booking_stats: %{
date: date,
space_id: space.id,
capacity: space.capacity,
user_id: current_user.id
}
]
)
end
end