spazio-solazzo/lib/spazio_solazzo_web/live/admin/walk_in_live.html.heex

295 lines
14 KiB
Text

<Layouts.app flash={@flash} current_user={@current_user} current_path={@current_path}>
<main class="flex-1">
<section class="mx-auto max-w-[1000px] px-6 py-10">
<.back_to_link
navigate={~p"/admin/dashboard"}
value="Back to Dashboard"
/>
<div class="mb-10 flex flex-col items-center md:items-start text-center md:text-left">
<h1 class="text-3xl md:text-4xl font-black text-slate-900 dark:text-white tracking-tight mb-3">
New Walk-in Booking
</h1>
<p class="text-slate-600 dark:text-slate-400 max-w-2xl text-lg">
Select a space and create a walk-in booking.
</p>
</div>
<div class="space-y-8">
<article class="bg-white dark:bg-slate-800 rounded-3xl p-6 md:p-8 border border-slate-200 dark:border-slate-700 shadow-xl shadow-slate-200/50 dark:shadow-none transition-all hover:border-primary/50 dark:hover:border-primary/50 group">
<header class="flex flex-col md:flex-row md:items-center gap-4 mb-8 pb-6 border-b border-slate-100 dark:border-slate-700/50">
<div class="size-12 rounded-2xl bg-primary text-white flex items-center justify-center text-xl font-bold shadow-lg shadow-primary/30 group-hover:scale-110 transition-transform duration-300">
1
</div>
<div>
<h2 class="text-xl font-bold text-slate-900 dark:text-white">
Select Space
</h2>
<p class="text-sm font-medium text-slate-500 dark:text-slate-400 mt-1">
Choose the space for the walk-in booking.
</p>
</div>
</header>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
<%= for space <- @spaces do %>
<button
phx-click="select_space"
phx-value-space_slug={space.slug}
class={[
"flex flex-col items-start gap-2 p-5 rounded-2xl border-2 transition-all cursor-pointer text-left",
if(@space.slug == space.slug,
do:
"border-primary bg-primary/5 dark:bg-primary/10 shadow-lg shadow-primary/20",
else:
"border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-900/50 hover:border-primary/50 hover:bg-slate-100 dark:hover:bg-slate-800"
)
]}
>
<span class={[
"text-base font-bold",
if(@space.slug == space.slug,
do: "text-primary dark:text-primary",
else: "text-slate-900 dark:text-white"
)
]}>
{space.name}
</span>
</button>
<% end %>
</div>
</article>
<%!-- Date & Time --%>
<article class="bg-white dark:bg-slate-800 rounded-3xl p-6 md:p-8 border border-slate-200 dark:border-slate-700 shadow-xl shadow-slate-200/50 dark:shadow-none transition-all hover:border-primary/50 dark:hover:border-primary/50 group">
<header class="flex flex-col md:flex-row md:items-center gap-4 mb-8 pb-6 border-b border-slate-100 dark:border-slate-700/50">
<div class="size-12 rounded-2xl bg-primary text-white flex items-center justify-center text-xl font-bold shadow-lg shadow-primary/30 group-hover:scale-110 transition-transform duration-300">
2
</div>
<div>
<h2 class="text-xl font-bold text-slate-900 dark:text-white">
Select Date & Time
</h2>
<p class="text-sm font-medium text-slate-500 dark:text-slate-400 mt-1">
Check availability on the calendar and set your booking range.
</p>
</div>
</header>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<%!-- Calendar --%>
<div class="lg:col-span-2">
<.live_component
module={SpazioSolazzoWeb.Admin.AdminCalendarComponent}
id="walk-in-calendar"
space_id={@space.id}
booking_counts={@booking_counts}
/>
</div>
<%!-- Selected dates and time inputs --%>
<div class="flex flex-col gap-6 lg:border-l border-slate-100 dark:border-slate-700 lg:pl-8">
<%!-- Selected interval --%>
<div>
<h3 class="text-sm font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-4">
Selected Interval
</h3>
<div class="p-4 rounded-xl bg-slate-50 dark:bg-slate-900/50 border border-slate-200 dark:border-slate-700 flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-xs text-slate-500 dark:text-slate-400">
Start Date
</span>
<span class="text-sm font-bold text-slate-900 dark:text-white">
<%= if @start_date do %>
{Calendar.strftime(@start_date, "%b %d, %Y")}
<% else %>
<span class="text-slate-400">Not selected</span>
<% end %>
</span>
</div>
<div class="w-full h-px bg-slate-200 dark:bg-slate-700"></div>
<div class="flex items-center justify-between">
<span class="text-xs text-slate-500 dark:text-slate-400">
End Date
</span>
<span class="text-sm font-bold text-slate-900 dark:text-white">
<%= if @end_date do %>
{Calendar.strftime(@end_date, "%b %d, %Y")}
<% else %>
<span class="text-slate-400">Not selected</span>
<% end %>
</span>
</div>
<div class="mt-2 text-xs font-medium text-primary dark:text-secondary flex items-center gap-1">
<.icon
name={
if @multi_day_mode && @end_date,
do: "hero-calendar-days",
else: "hero-calendar"
}
class="w-4 h-4"
/>
<span>
<%= if @multi_day_mode && @start_date && @end_date do %>
{days_selected(@start_date, @end_date)} Days total
<% else %>
Single Day
<% end %>
</span>
</div>
</div>
</div>
<%!-- Daily schedule --%>
<div>
<h3 class="text-sm font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-4">
Daily Schedule
</h3>
<%= if @multi_day_mode do %>
<%!-- Multi-day mode: Show info card --%>
<div class="w-full bg-slate-50 dark:bg-slate-800/40 border border-slate-200 dark:border-slate-700 rounded-xl p-5 flex flex-col items-center text-center">
<div class="size-10 bg-primary/10 dark:bg-primary/20 text-primary rounded-full flex items-center justify-center mb-3">
<.icon name="hero-calendar-days" class="w-5 h-5" />
</div>
<p class="text-sm font-bold text-slate-900 dark:text-slate-100">
Full day booking applied for the selected range
</p>
<p class="text-xs text-slate-500 dark:text-slate-400 mt-1 leading-relaxed">
Start and end time inputs are disabled for multiday selections.
</p>
</div>
<% else %>
<%!-- Single-day mode: Show time inputs --%>
<.form
for={%{}}
as={:schedule}
id="walk-in-schedule-form"
class="p-4 rounded-xl bg-slate-50 dark:bg-slate-900/50 border border-slate-200 dark:border-slate-700 flex flex-col gap-4"
>
<div class="relative">
<label
class="block text-xs font-semibold text-slate-600 dark:text-slate-300 mb-2"
for="start-time"
>
Start Time
</label>
<div class="relative">
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none">
<.icon name="hero-clock" class="w-4 h-4" />
</span>
<.input
id="start-time"
name="start-time"
type="time"
value={Calendar.strftime(@start_time, "%H:%M")}
phx-change="update_start_time"
class="w-full bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 text-slate-900 dark:text-white text-sm rounded-xl pl-10 pr-4 py-3 focus:ring-2 focus:ring-primary focus:border-primary transition-all shadow-sm"
/>
</div>
</div>
<div class="relative">
<label
class="block text-xs font-semibold text-slate-600 dark:text-slate-300 mb-2"
for="end-time"
>
End Time
</label>
<div class="relative">
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none">
<.icon name="hero-clock" class="w-4 h-4" />
</span>
<.input
id="end-time"
name="end-time"
type="time"
value={Calendar.strftime(@end_time, "%H:%M")}
phx-change="update_end_time"
class="w-full bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 text-slate-900 dark:text-white text-sm rounded-xl pl-10 pr-4 py-3 focus:ring-2 focus:ring-primary focus:border-primary transition-all shadow-sm"
/>
</div>
</div>
</.form>
<% end %>
</div>
</div>
</div>
</article>
<%!-- Customer Details --%>
<article class="bg-white dark:bg-slate-800 rounded-3xl p-6 md:p-8 border border-slate-200 dark:border-slate-700 shadow-xl shadow-slate-200/50 dark:shadow-none transition-all hover:border-primary/50 dark:hover:border-primary/50 group">
<header class="flex flex-col md:flex-row md:items-center gap-4 mb-8 pb-6 border-b border-slate-100 dark:border-slate-700/50">
<div class="size-12 rounded-2xl bg-primary text-white flex items-center justify-center text-xl font-bold shadow-lg shadow-primary/30 group-hover:scale-110 transition-transform duration-300">
3
</div>
<div>
<h2 class="text-xl font-bold text-slate-900 dark:text-white">
Customer Details
</h2>
<p class="text-sm font-medium text-slate-500 dark:text-slate-400 mt-1">
Enter the customer's contact information to complete the booking.
</p>
</div>
</header>
<.form
for={@customer_details_form}
id="customer-details-form"
phx-change="validate_customer_details"
phx-submit="create_booking"
class="space-y-4 max-w-2xl"
>
<div class="relative">
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400">
<.icon name="hero-user" class="w-5 h-5" />
</span>
<.input
field={@customer_details_form["customer_name"]}
class="w-full bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-700 text-slate-900 dark:text-white text-sm rounded-xl pl-10 pr-4 py-3 focus:ring-2 focus:ring-primary focus:border-primary transition-all placeholder:text-slate-400"
placeholder="Customer Name"
type="text"
required
/>
</div>
<div class="relative">
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400">
<.icon name="hero-envelope" class="w-5 h-5" />
</span>
<.input
field={@customer_details_form["customer_email"]}
class="w-full bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-700 text-slate-900 dark:text-white text-sm rounded-xl pl-10 pr-4 py-3 focus:ring-2 focus:ring-primary focus:border-primary transition-all placeholder:text-slate-400"
placeholder="customer@example.com"
type="email"
required
/>
</div>
<div class="relative">
<span class="absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400">
<.icon name="hero-phone" class="w-5 h-5" />
</span>
<.input
field={@customer_details_form["customer_phone"]}
class="w-full bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-700 text-slate-900 dark:text-white text-sm rounded-xl pl-10 pr-4 py-3 focus:ring-2 focus:ring-primary focus:border-primary transition-all placeholder:text-slate-400"
placeholder="Customer Phone Number (Optional)"
type="tel"
/>
</div>
</.form>
</article>
<div class="flex justify-center pt-4">
<.button
type="submit"
form="customer-details-form"
class="w-full sm:w-auto flex items-center justify-center gap-2 overflow-hidden rounded-xl h-12 px-10 bg-primary hover:bg-primary/90 transition-colors text-white text-base font-bold shadow-lg shadow-primary/30 cursor-pointer"
>
<span>Create Booking</span>
</.button>
</div>
</div>
</section>
</main>
</Layouts.app>