mirror of
https://codeberg.org/JasterV/spazio-solazzo.git
synced 2026-04-26 18:20:03 +00:00
245 lines
12 KiB
Text
245 lines
12 KiB
Text
<Layouts.app flash={@flash} current_user={@current_user}>
|
|
<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"
|
|
/>
|
|
|
|
<%!-- Title --%>
|
|
<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 Arcipelago Walk-in Booking
|
|
</h1>
|
|
<p class="text-slate-600 dark:text-slate-400 max-w-2xl text-lg">
|
|
Create a walk-in booking for the Arcipelago space.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="space-y-8">
|
|
<%!-- 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">
|
|
1
|
|
</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 --%>
|
|
<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-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"
|
|
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"
|
|
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>
|
|
</div>
|
|
<% 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">
|
|
2
|
|
</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>
|