Shitaye-FrontEnd/src/components/RoomSelectBooking.tsx
2026-04-16 10:10:26 +03:00

120 lines
4.4 KiB
TypeScript

"use client";
import Image from "next/image";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { RoomPrice } from "@/components/RoomPrice";
import type { Room } from "@/types/room";
import { useBooking } from "@/context/BookingContext";
type Props = {
selected: Room | null;
onSelect: (roomId: string) => void;
};
export function RoomSelectBooking({ selected, onSelect }: Props) {
const { rooms } = useBooking();
const [open, setOpen] = useState(false);
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
function onDoc(e: MouseEvent) {
if (!ref.current?.contains(e.target as Node)) setOpen(false);
}
if (open) document.addEventListener("mousedown", onDoc);
return () => document.removeEventListener("mousedown", onDoc);
}, [open]);
return (
<div className="relative" ref={ref}>
<span className="mb-2 block text-sm font-medium text-[var(--color-text)]">
Select room
</span>
<button
type="button"
onClick={() => setOpen((o) => !o)}
className="flex w-full items-center gap-3 rounded-2xl border border-(--color-border) bg-[var(--color-surface)] p-3 text-left shadow-sm transition hover:border-[var(--color-primary)]/40 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary)]"
aria-expanded={open}
aria-haspopup="listbox"
>
{selected ? (
<>
<div className="relative h-14 w-20 shrink-0 overflow-hidden rounded-lg">
<Image
src={selected.gallery[0] || "/images/shitaye-logo.png"}
alt={selected.name}
fill
className="object-cover"
sizes="80px"
/>
</div>
<div className="min-w-0 flex-1">
<p className="font-semibold text-[var(--color-text)]">{selected.name}</p>
<p className="text-xs text-[var(--color-muted)]">
From <RoomPrice room={selected} maximumFractionDigits={0} /> / night
</p>
</div>
</>
) : (
<span className="text-[var(--color-muted)]">Choose a room</span>
)}
<span className="shrink-0 text-[var(--color-muted)]" aria-hidden>
{open ? "▴" : "▾"}
</span>
</button>
{open ? (
<ul
className="absolute left-0 right-0 top-full z-40 mt-2 max-h-[min(70vh,400px)] overflow-y-auto rounded-2xl border border-[var(--color-border)] bg-[var(--color-surface)] py-2 shadow-xl"
role="listbox"
>
{rooms.map((room) => (
<li key={room.id} role="option" aria-selected={selected?.id === room.id}>
<button
type="button"
onClick={() => {
onSelect(room.id);
setOpen(false);
}}
className="flex w-full items-center gap-3 px-3 py-2.5 text-left transition hover:bg-[var(--color-surface-muted)]"
>
<div className="relative h-12 w-[4.5rem] shrink-0 overflow-hidden rounded-lg">
<Image
src={room.gallery[0] || "/images/shitaye-logo.png"}
alt={room.name}
fill
className="object-cover"
sizes="72px"
/>
</div>
<div className="min-w-0 flex-1">
<p className="text-sm font-semibold text-[var(--color-text)]">{room.name}</p>
<p className="text-xs text-[var(--color-muted)]">
<RoomPrice room={room} maximumFractionDigits={0} />
/night · max {room.maxGuests} guests
</p>
</div>
</button>
</li>
))}
</ul>
) : null}
{selected ? (
<Link
href={
/^[0-9a-f-]{36}$/i.test(selected.id)
? `/booking?room=${encodeURIComponent(selected.id)}`
: `/rooms/${selected.slug}`
}
className="mt-2 inline-block text-sm font-semibold text-[var(--color-primary)] hover:underline"
>
{/^[0-9a-f-]{36}$/i.test(selected.id)
? "Back to room selection"
: "View full room details & amenities"}
</Link>
) : null}
</div>
);
}