anatolian2/components/experiences/BookingWidget.tsx
Temmuz Aslan 591d878ac6 Initial commit: The Anatolian Edit website
Next.js 14 website with standalone output configured for Docker deployment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:34:25 +03:00

140 lines
5.1 KiB
TypeScript

"use client";
import { useState } from "react";
import { motion } from "framer-motion";
import { Experience, WHATSAPP_NUMBER } from "@/lib/constants";
import { Button } from "@/components/shared/Button";
interface BookingWidgetProps {
experience: Experience;
}
export function BookingWidget({ experience }: BookingWidgetProps) {
const [guests, setGuests] = useState(2);
const [selectedDate, setSelectedDate] = useState("");
const total = experience.price * guests;
const dates = Array.from({ length: 7 }, (_, i) => {
const d = new Date();
d.setDate(d.getDate() + i + 2);
return d.toISOString().split("T")[0];
});
const formatDate = (dateStr: string) => {
const d = new Date(dateStr);
return d.toLocaleDateString("en-US", {
weekday: "short",
month: "short",
day: "numeric",
});
};
const whatsappUrl = `https://wa.me/${WHATSAPP_NUMBER.replace("+", "")}?text=${encodeURIComponent(
`Hi! I'd like to book "${experience.name}" for ${guests} guest(s)${selectedDate ? ` on ${formatDate(selectedDate)}` : ""}. Can you help?`
)}`;
return (
<section id="booking" className="py-16 md:py-24 section-padding bg-warm-sand">
<div className="max-w-2xl mx-auto">
<motion.div
className="bg-white rounded-3xl p-8 md:p-10 shadow-lg"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
>
<h2 className="font-display text-2xl md:text-3xl font-bold text-deep-nazar mb-2 text-center">
Book {experience.name}
</h2>
<p className="text-deep-nazar/60 text-center mb-8">
Secure your spot free cancellation up to 48 hours before
</p>
<div className="space-y-6">
{/* Date selection */}
<div>
<label className="block text-sm font-semibold text-deep-nazar mb-3">
Select a Date
</label>
<div className="flex flex-wrap gap-2">
{dates.map((date) => (
<button
key={date}
onClick={() => setSelectedDate(date)}
className={`px-4 py-2 rounded-full text-sm font-medium transition-all ${
selectedDate === date
? "bg-bosphorus text-white"
: "bg-deep-nazar/5 text-deep-nazar/70 hover:bg-bosphorus/10"
}`}
>
{formatDate(date)}
</button>
))}
</div>
</div>
{/* Guest count */}
<div>
<label className="block text-sm font-semibold text-deep-nazar mb-3">
Number of Guests
</label>
<div className="flex items-center gap-4">
<button
onClick={() => setGuests(Math.max(1, guests - 1))}
className="w-10 h-10 rounded-full bg-deep-nazar/5 flex items-center justify-center text-deep-nazar hover:bg-deep-nazar/10 transition-colors"
>
-
</button>
<span className="text-2xl font-bold text-deep-nazar w-8 text-center">
{guests}
</span>
<button
onClick={() => setGuests(Math.min(8, guests + 1))}
className="w-10 h-10 rounded-full bg-deep-nazar/5 flex items-center justify-center text-deep-nazar hover:bg-deep-nazar/10 transition-colors"
>
+
</button>
<span className="text-sm text-deep-nazar/50">
Max 8 per group
</span>
</div>
</div>
{/* Price summary */}
<div className="bg-warm-sand rounded-2xl p-5">
<div className="flex justify-between items-center mb-2">
<span className="text-deep-nazar/70">
&euro;{experience.price} &times; {guests} guest{guests > 1 ? "s" : ""}
</span>
<span className="font-semibold text-deep-nazar">
&euro;{total}
</span>
</div>
<div className="flex justify-between items-center pt-3 border-t border-deep-nazar/10">
<span className="font-bold text-deep-nazar">Total</span>
<span className="text-2xl font-bold text-deep-nazar">
&euro;{total}
</span>
</div>
</div>
{/* CTA */}
<div className="space-y-3">
<Button
href={whatsappUrl}
external
variant="coral"
size="lg"
className="w-full"
>
Reserve Now via WhatsApp
</Button>
<p className="text-center text-xs text-deep-nazar/40">
Instant confirmation &middot; Pay securely online &middot; Free cancellation up to 48h before
</p>
</div>
</div>
</motion.div>
</div>
</section>
);
}