diff --git a/src/app/confirmation/page.tsx b/src/app/confirmation/page.tsx index 6e33908..d9bd9a8 100644 --- a/src/app/confirmation/page.tsx +++ b/src/app/confirmation/page.tsx @@ -89,13 +89,21 @@ export default function ConfirmationPage() { - resetBooking()} - className="btn-mustard mt-10 inline-flex px-10 py-3.5 text-sm" - > - Back to home - +
+ + Open guest portal + + resetBooking()} + className="btn-mustard inline-flex px-10 py-3.5 text-sm" + > + Back to home + +
); } diff --git a/src/app/guest/GuestSpaGymBookingClient.tsx b/src/app/guest/GuestSpaGymBookingClient.tsx new file mode 100644 index 0000000..f986825 --- /dev/null +++ b/src/app/guest/GuestSpaGymBookingClient.tsx @@ -0,0 +1,174 @@ +"use client"; + +import Image from "next/image"; +import Link from "next/link"; +import { useMemo, useState } from "react"; +import { RequireAuth } from "@/components/RequireAuth"; +import { useAuth } from "@/context/AuthContext"; +import { spaGymServices, type SpaGymKind, type SpaGymService } from "@/lib/mocks/services"; + +const MOCK_SLOTS = ["09:00", "11:00", "14:00", "16:00", "18:00"]; + +type Props = { kind: SpaGymKind; title: string; description: string }; + +export function GuestSpaGymBookingClient({ kind, title, description }: Props) { + return ( + + + + ); +} + +function Inner({ kind, title, description }: Props) { + const { addOrder } = useAuth(); + const [serviceId, setServiceId] = useState(null); + const [slot, setSlot] = useState(MOCK_SLOTS[0]!); + const [note, setNote] = useState(""); + const [done, setDone] = useState(false); + + const items = useMemo(() => spaGymServices.filter((s) => s.kind === kind), [kind]); + const selected = useMemo( + () => items.find((s) => s.id === serviceId) ?? null, + [items, serviceId], + ); + + function book() { + if (!selected) return; + addOrder({ + category: kind === "spa" ? "spa" : "gym", + title: `${kind === "spa" ? "Spa" : "Gym"} · ${selected.title}`, + detail: `${selected.duration} · ${slot}${note ? ` · ${note}` : ""} · $${selected.priceUsd}`, + totalUsd: selected.priceUsd, + status: "confirmed", + }); + setDone(true); + } + + return ( +
+
+ + +
+
+

+ {title} +

+

{description}

+
+ + Full spa & gym menu → + +
+ + {done ? ( +
+ Request recorded (demo). See My stay for orders. +
+ ) : null} + +
+
+ {items.map((s: SpaGymService) => ( + + ))} +
+ +