first commit

This commit is contained in:
2026-04-15 22:37:39 +03:00
parent 3c59557946
commit 1590bef227
156 changed files with 13823 additions and 84 deletions

View File

@@ -0,0 +1,86 @@
"use client";
import Image from "next/image";
import Link from "next/link";
import { resortData } from "@/src/data/resort";
import { motion } from "framer-motion";
import { useRef } from "react";
interface AccommodationCardProps {
room: any;
lang: "tr";
}
const getCloudinaryUrl = (publicId: string, width = 1200) => {
if (!publicId) return "https://images.unsplash.com/photo-1566073771259-6a8506099945?auto=format&fit=crop&q=80&w=1200";
return `https://res.cloudinary.com/du7xohbct/image/upload/q_auto,f_auto,w_${width}/${publicId}`;
};
export default function AccommodationCard({ room, lang }: AccommodationCardProps) {
const allImages = [
room.mainImageId,
...(room.galleryImageIds || [])
];
const scrollRef = useRef<HTMLDivElement>(null);
return (
<div className="flex flex-col w-full bg-[#ECE7E1] mb-12 shadow-sm">
{/* Precision Header Section */}
<div className="flex flex-col lg:flex-row justify-between items-start lg:items-center px-10 py-12 gap-10">
{/* Left: Title & Descriptions */}
<div className="flex-[2] space-y-3">
<h3 className="text-[#4F5B3A] text-2xl font-serif tracking-tight leading-none mb-1">
{room.name[lang]} <span className="text-sm font-sans opacity-60">({room.size})</span>
</h3>
<p className="text-[13px] leading-relaxed text-[#4F5B3A] opacity-90 font-light max-w-2xl">
{room.description[lang]}
</p>
</div>
{/* Right: Booking Button */}
<div className="flex-shrink-0 w-full lg:w-auto">
<Link
href={`/accommodation/${room.slug}`}
className="block w-full lg:w-auto bg-[#C87E4B] hover:bg-[#A6693E] text-black px-12 py-4 text-[11px] font-bold tracking-[0.2em] rounded-md transition-all duration-300 transform hover:-translate-y-1 shadow-xl hover:shadow-[#C87E4B]/20 text-center uppercase"
>
Odayı İncele
</Link>
</div>
</div>
{/* DRAGGABLE SLIDER */}
<div
style={{ height: '550px', position: 'relative', width: '100vw', left: '50%', right: '50%', marginLeft: '-50vw', marginRight: '-50vw' }}
className="overflow-hidden cursor-grab active:cursor-grabbing bg-zinc-200"
>
<motion.div
ref={scrollRef}
drag="x"
dragConstraints={{ right: 80, left: -((allImages.length - 1) * 720) }}
className="flex h-full gap-4 px-[15vw]"
>
{allImages.map((id, idx) => (
<div
key={`${id}-${idx}`}
style={{ height: '100%', position: 'relative', minWidth: '700px', flexShrink: 0 }}
className="rounded-sm overflow-hidden shadow-sm group"
>
<Image
src={getCloudinaryUrl(id, 1200)}
alt="Gallery"
fill
style={{ objectFit: 'cover' }}
sizes="(max-width: 1024px) 100vw, 80vw"
className="transition-transform duration-700 group-hover:scale-105 pointer-events-none"
draggable={false}
priority={idx < 2}
/>
</div>
))}
</motion.div>
</div>
</div>
);
}

View File

@@ -0,0 +1,41 @@
import { ExperienceSection } from "@/src/data/resort";
import { getCloudinaryUrl } from "@/src/lib/cloudinary";
import Link from "next/link";
import Image from "next/image";
interface ExperienceCardProps {
experience: ExperienceSection;
lang: "tr" | "en" | "de";
}
export default function ExperienceCard({ experience, lang }: ExperienceCardProps) {
return (
<Link
href={experience.href}
className="group relative overflow-hidden rounded-2xl aspect-square block"
>
<Image
src={getCloudinaryUrl(experience.imageId, { width: 800, height: 800, crop: "fill" })}
alt={experience.title[lang]}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-110 group-hover:rotate-1"
/>
{/* Dark Overlay */}
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent opacity-60 transition-opacity duration-700 group-hover:opacity-40" />
{/* Minimal Gold Border Hover */}
<div className="absolute inset-4 border border-white/0 transition-all duration-700 group-hover:border-gold/30 group-hover:backdrop-blur-[2px] flex items-center justify-center">
<span className="text-white text-xs font-bold tracking-[0.4em] opacity-0 translate-y-4 transition-all duration-700 group-hover:opacity-100 group-hover:translate-y-0 border-b border-gold pb-1">
{lang === "tr" ? "KEŞFET" : lang === "en" ? "EXPLORE" : "ENTDECKEN"}
</span>
</div>
{/* Content */}
<div className="absolute bottom-8 left-8 text-white group-hover:opacity-0 transition-opacity duration-500">
<h3 className="text-2xl font-serif font-bold mb-1 tracking-wider">{experience.title[lang]}</h3>
<p className="text-white/70 text-[10px] uppercase tracking-[0.2em] font-medium">{experience.subtitle[lang]}</p>
</div>
</Link>
);
}

View File

@@ -0,0 +1,49 @@
"use client";
import { resortData } from "@/src/data/resort";
import Link from "next/link";
export default function FloatingBookingBar() {
// Normally would have state for dates, but following PRD's "minimal bar"
const lang = "tr"; // Mocked locale
return (
<div className="fixed bottom-6 left-0 right-0 z-40 px-6 animate-fade-in-up">
<div className="max-w-4xl mx-auto glass-dark text-white rounded-full p-2 flex items-center shadow-2xl">
<div className="flex-1 flex items-center divide-x divide-white/10 px-4 overflow-x-auto no-scrollbar">
{/* Check In */}
<div className="px-4 py-2 flex flex-col min-w-[120px]">
<span className="text-[10px] uppercase tracking-widest text-white/50">
{resortData.floatingBar.checkIn[lang]}
</span>
<span className="text-sm font-semibold italic">Select Date</span>
</div>
{/* Check Out */}
<div className="px-4 py-2 flex flex-col min-w-[120px]">
<span className="text-[10px] uppercase tracking-widest text-white/50">
{resortData.floatingBar.checkOut[lang]}
</span>
<span className="text-sm font-semibold italic">Select Date</span>
</div>
{/* Guests */}
<div className="px-4 py-2 flex flex-col min-w-[100px]">
<span className="text-[10px] uppercase tracking-widest text-white/50">
{resortData.floatingBar.guests[lang]}
</span>
<span className="text-sm font-semibold">2 Adults</span>
</div>
</div>
<Link
href={resortData.bookingUrl}
target="_blank"
className="bg-gold text-white px-8 py-3 rounded-full font-bold text-sm hover:bg-gold-dark transition-all whitespace-nowrap"
>
{resortData.floatingBar.search[lang]}
</Link>
</div>
</div>
);
}

124
app/components/Footer.tsx Normal file
View File

@@ -0,0 +1,124 @@
"use client";
import Link from "next/link";
import { resortData } from "@/src/data/resort";
export default function Footer() {
return (
<footer className="bg-[#EAE5D8] pt-24 pb-8 px-6 overflow-hidden border-t border-black/5">
<div className="max-w-7xl mx-auto">
{/* Main Footer Content */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-12 mb-20">
{/* Column 1: Brand & Newsletter */}
<div className="lg:col-span-1 space-y-8">
<h2 className="text-3xl font-serif text-gray-900 tracking-tighter">SALMAKIS</h2>
<div className="space-y-4">
<div className="relative group">
<input
type="email"
placeholder="E-Posta Adresiniz"
className="w-full bg-white border-none py-4 px-6 pr-32 text-xs tracking-widest outline-none focus:ring-1 focus:ring-gold transition-all"
/>
<button className="absolute right-1 top-1 bottom-1 bg-[#C59D5F] text-white px-6 text-[10px] font-bold tracking-widest hover:bg-gold transition-all">
ABONE OL
</button>
</div>
<label className="flex items-center gap-3 cursor-pointer group">
<input type="checkbox" className="w-3 h-3 accent-gold border-gray-300" />
<span className="text-[10px] text-gray-400 font-light tracking-wider group-hover:text-gray-600 transition-colors">
Kişisel verilerimin işlenmesini kabul ediyorum.
</span>
</label>
</div>
<div className="flex gap-4 pt-4">
{resortData.social.map((social) => (
<Link
key={social.platform}
href={social.url}
className="text-gray-900 hover:text-gold transition-colors text-lg"
>
<i className={`fab fa-${social.platform.toLowerCase()}`}></i>
</Link>
))}
</div>
</div>
{/* Column 2: Salmakis */}
<div className="space-y-6">
<h4 className="text-[10px] font-bold tracking-[0.3em] text-gray-400 uppercase">SALMAKIS</h4>
<ul className="space-y-3">
{["Doğada.", "Sofrada.", "Odalarda.", "Bizimle."].map((item) => (
<li key={item}>
<Link href="#" className="text-sm font-light text-gray-600 hover:text-gold transition-colors">{item}</Link>
</li>
))}
</ul>
</div>
{/* Column 3: Sayfalar */}
<div className="space-y-6">
<h4 className="text-[10px] font-bold tracking-[0.3em] text-gray-400 uppercase">SAYFALAR</h4>
<ul className="space-y-3">
{["Konaklama", "S.S.S", "Sürdürülebilirlik", "Resim Galerisi", "Fiyat Listesi"].map((item) => (
<li key={item}>
<Link href="#" className="text-sm font-light text-gray-600 hover:text-gold transition-colors">{item}</Link>
</li>
))}
</ul>
</div>
{/* Column 4: Yasal */}
<div className="space-y-6">
<h4 className="text-[10px] font-bold tracking-[0.3em] text-gray-400 uppercase">VERİ KORUMA</h4>
<ul className="space-y-3">
{["Künye", "Gizlilik Politikası", "KVKK", "Çerez Ayarları"].map((item) => (
<li key={item}>
<Link href="#" className="text-sm font-light text-gray-600 hover:text-gold transition-colors">{item}</Link>
</li>
))}
</ul>
</div>
{/* Column 5: İletişim */}
<div className="space-y-6">
<h4 className="text-[10px] font-bold tracking-[0.3em] text-gray-400 uppercase">İLETİŞİM</h4>
<ul className="space-y-3">
<li><Link href="#" className="text-sm font-light text-gray-600 hover:text-gold transition-colors">Oda Rezerve Et</Link></li>
<li><Link href="#" className="text-sm font-light text-gray-600 hover:text-gold transition-colors">Yol Tarifi Al</Link></li>
<li><Link href="#" className="text-sm font-light text-gray-600 hover:text-gold transition-colors">İletişime Geç</Link></li>
<li className="pt-2 text-sm text-gray-900 font-medium tracking-wider">{resortData.contact.phone}</li>
<li className="text-sm text-gray-400 font-light">{resortData.contact.email}</li>
</ul>
</div>
</div>
{/* Brand Logos / Partners */}
<div className="border-t border-black/5 py-16 flex flex-wrap justify-center items-center gap-12 md:gap-24 opacity-40 grayscale hover:grayscale-0 transition-all duration-700">
{/* Placeholder Logos reflecting the style in the image */}
<div className="text-2xl font-serif tracking-widest text-[#1a2e1e]">BODRUM</div>
<div className="text-sm font-bold tracking-[0.4em] text-[#1a2e1e]">EGE MUTFAĞI</div>
<div className="text-xl font-serif text-[#1a2e1e] border border-current px-2">S</div>
<div className="text-2xl font-sans font-extralight tracking-[0.3em] text-[#1a2e1e]">BLUE FLAG</div>
</div>
{/* Bottom copyright area */}
<div className="relative pt-12 flex flex-col md:flex-row justify-between items-center gap-4 text-[9px] tracking-[0.2em] font-medium text-gray-400 uppercase">
<div>© 2026 HER HAKKI SAKLIDIR.</div>
{/* Decorative Mountain Line (SVG) */}
<div className="absolute bottom-[-20px] left-1/2 -translate-x-1/2 w-full max-w-4xl opacity-10 -z-10">
<svg viewBox="0 0 1000 100" className="w-full">
<path d="M0 100 L200 60 L400 90 L600 40 L800 70 L1000 50 L1000 100 Z" fill="none" stroke="currentColor" strokeWidth="1" />
</svg>
</div>
<div>SALMAKIS RESORT & SPA</div>
</div>
</div>
</footer>
);
}

80
app/components/Navbar.tsx Normal file
View File

@@ -0,0 +1,80 @@
"use client";
import Link from "next/link";
export default function Navbar() {
const lang = "tr"; // Mocked locale
const navLinks = [
{ label: { tr: "KONAKLAMA", en: "ACCOMMODATION", de: "UNTERKUNFT" }, href: "/accommodation", side: "left" },
{ label: { tr: "YİYECEK & İÇECEK", en: "FOOD & BEVERAGE", de: "FOOD & BEVERAGE" }, href: "/dining", side: "left" },
{ label: { tr: "AKTİVİTE", en: "ACTIVITIES", de: "AKTIVITÄTEN" }, href: "/activities", side: "left" },
{ label: { tr: "ORGANİZASYON", en: "ORGANIZER", de: "ORGANISATION" }, href: "/organizations", side: "right" },
{ label: { tr: "GALERİ", en: "GALLERY", de: "GALERIE" }, href: "/gallery", side: "right" },
{ label: { tr: "SPA CENTER", en: "SPA CENTER", de: "SPA CENTER" }, href: "/spa", side: "right" },
];
return (
<nav className=" top-0 left-0 right-0 z-50 transition-all duration-500 py-6 bg-white shadow-sm border-b border-gray-50">
<div className="max-w-[1600px] mx-auto px-10 flex items-center justify-between">
{/* Left Menu */}
<div className="hidden lg:flex items-center space-x-12 flex-1">
{navLinks.filter(l => l.side === "left").map((link) => (
<Link
key={link.href}
href={link.href}
className="group relative text-[11px] font-medium tracking-[0.2em] transition-all text-gray-900 overflow-hidden"
>
<span className="relative z-10 block transition-transform duration-300 group-hover:-translate-y-full">
{link.label[lang as "tr"]}
</span>
<span className="absolute inset-0 z-20 block transition-transform duration-300 translate-y-full group-hover:translate-y-0 text-gold italic">
{link.label[lang as "tr"]}
</span>
</Link>
))}
</div>
{/* Centered Logo */}
<div className="flex flex-col items-center">
<Link href="/" className="flex flex-col items-center group">
<span className="text-3xl md:text-5xl font-serif font-light tracking-[0.3em] text-gray-900 leading-none">
SALMAKIS
</span>
<span className="text-[10px] tracking-[0.6em] mt-2 text-gray-400 font-sans uppercase">
Resort & Spa
</span>
</Link>
</div>
{/* Right Menu */}
<div className="hidden lg:flex items-center justify-end space-x-12 flex-1">
{navLinks.filter(l => l.side === "right").map((link) => (
<Link
key={link.href}
href={link.href}
className="group relative text-[11px] font-medium tracking-[0.2em] transition-all text-gray-900 overflow-hidden"
>
<span className="relative z-10 block transition-transform duration-300 group-hover:-translate-y-full">
{link.label[lang as "tr"]}
</span>
<span className="absolute inset-0 z-20 block transition-transform duration-300 translate-y-full group-hover:translate-y-0 text-gold italic">
{link.label[lang as "tr"]}
</span>
</Link>
))}
</div>
{/* Mobile Menu */}
<div className="lg:hidden">
<button className="p-2 text-gray-900">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1} stroke="currentColor" className="w-8 h-8">
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 9h16.5m-16.5 6.75h16.5" />
</svg>
</button>
</div>
</div>
</nav>
);
}

View File

@@ -0,0 +1,57 @@
"use client";
import { useRef } from "react";
import { motion, useScroll, useTransform, useSpring } from "framer-motion";
export default function ScrollVideo() {
const containerRef = useRef<HTMLDivElement>(null);
// Use scroll progress within this section
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ["start start", "end end"]
});
// Smooth out the scroll value
const smoothProgress = useSpring(scrollYProgress, {
stiffness: 100,
damping: 30,
restDelta: 0.001
});
// Calculate the expansion: Starts at 25% circle, grows to 150% (to fully cover screen)
const clipPathValue = useTransform(smoothProgress, [0, 1], ["circle(25% at 50% 50%)", "circle(100% at 50% 50%)"]);
// Also fade the overlay
const overlayOpacity = useTransform(smoothProgress, [0, 0.8], [0.3, 0]);
return (
<section
ref={containerRef}
className="relative h-[250vh] bg-white"
>
<div className="sticky top-0 h-screen w-full flex items-center justify-center overflow-hidden z-30">
<motion.div
style={{ clipPath: clipPathValue }}
className="relative w-full h-full flex items-center justify-center bg-white will-change-transform shadow-2xl"
>
{/* YouTube Embed with Hardware Acceleration */}
<div className="absolute inset-0 pointer-events-none scale-110 will-change-transform">
<iframe
className="absolute top-1/2 left-1/2 w-[115vw] h-[115vh] -translate-x-1/2 -translate-y-1/2 object-cover pointer-events-none"
src="https://www.youtube.com/embed/avqL1kRkX0c?autoplay=1&mute=1&controls=0&loop=1&playlist=avqL1kRkX0c&playsinline=1&rel=0&modestbranding=1"
allow="autoplay; encrypted-media"
allowFullScreen
></iframe>
</div>
{/* Subtle Overlay */}
<motion.div
style={{ opacity: overlayOpacity }}
className="absolute inset-0 bg-black/20 z-10 pointer-events-none"
/>
</motion.div>
</div>
</section>
);
}

View File

@@ -0,0 +1,22 @@
import { resortData } from "@/src/data/resort";
export default function SecurityBadge({ lang }: { lang: "tr" | "en" | "de" }) {
return (
<div className="flex flex-col items-center text-center max-w-2xl mx-auto py-12 px-6 border-t border-gray-100">
<div className="w-16 h-16 bg-bodrum-blue rounded-full mb-6 flex items-center justify-center text-white shadow-xl shadow-bodrum-blue/20">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-8 h-8">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 0 1-1.043 3.296 3.745 3.745 0 0 1-3.296 1.043A3.745 3.745 0 0 1 12 21a3.745 3.745 0 0 1-3.127-1.593 3.745 3.745 0 0 1-3.296-1.043 3.745 3.745 0 0 1-1.043-3.296A3.745 3.745 0 0 1 3 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 0 1 1.043-3.296 3.745 3.745 0 0 1 3.296-1.043A3.745 3.745 0 0 1 12 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 0 1 3.296 1.043 3.746 3.746 0 0 1 1.043 3.296A3.745 3.745 0 0 1 21 12Z" />
</svg>
</div>
<h4 className="text-xl font-bold text-bodrum-blue mb-2">
{resortData.securityBadge.title[lang]}
</h4>
<p className="text-gray-500 text-sm leading-relaxed mb-4">
{resortData.securityBadge.description[lang]}
</p>
<div className="text-[10px] uppercase tracking-[0.2em] font-bold text-gray-400">
Official Website Protection Verified Secure
</div>
</div>
);
}

View File

@@ -0,0 +1,16 @@
"use client";
import { ReactLenis } from "lenis/react";
import { ReactNode } from "react";
export default function SmoothScroll({ children }: { children: ReactNode }) {
return (
<ReactLenis root options={{
lerp: 0.05,
duration: 1.5,
smoothWheel: true
}}>
{children}
</ReactLenis>
);
}

View File

@@ -0,0 +1,95 @@
"use client";
import Image from "next/image";
import Link from "next/link";
import { getCloudinaryUrl } from "@/src/lib/cloudinary";
import { motion } from "framer-motion";
interface SplitSectionProps {
title: string;
subtitle: string;
description: string;
mainImage: string;
secondImage: string;
href: string;
reverse?: boolean;
}
export default function SplitSection({
title,
subtitle,
description,
mainImage,
secondImage,
href,
reverse = false
}: SplitSectionProps) {
return (
<section className={`flex flex-col ${reverse ? 'md:flex-row-reverse' : 'md:flex-row'} min-h-screen w-full bg-[#FAF9F6] overflow-hidden`}>
{/* Text Side */}
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.8, ease: "easeOut" }}
className="w-full md:w-1/2 flex flex-col justify-center px-10 md:px-24 py-20"
>
<span className="text-gold text-xs tracking-[0.4em] font-bold uppercase mb-6 block">
{subtitle}
</span>
<h2 className="text-5xl md:text-7xl font-serif text-gray-900 leading-tight mb-8">
{title}
</h2>
<p className="text-gray-500 text-lg leading-relaxed max-w-md mb-12 font-light">
{description}
</p>
<div>
<Link
href={href}
className="group relative inline-block overflow-hidden bg-[#C59D5F] text-white px-10 py-4 rounded-md text-[10px] font-bold tracking-widest transition-all hover:bg-gold uppercase active:scale-95"
>
<span className="relative z-10">KEŞFET</span>
<motion.div
className="absolute inset-0 bg-white/20 -translate-x-full group-hover:translate-x-full transition-transform duration-700 ease-in-out"
/>
</Link>
</div>
</motion.div>
{/* Image Side */}
<div className="w-full md:w-1/2 relative min-h-[500px] md:min-h-screen">
<motion.div
initial={{ scale: 1.1, opacity: 0 }}
whileInView={{ scale: 1, opacity: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, ease: "easeOut" }}
className="relative w-full h-full"
>
<Image
src={getCloudinaryUrl(mainImage, { width: 1200, height: 1600, crop: "fill" })}
alt={title}
fill
className="object-cover"
/>
</motion.div>
{/* Floating Secondary Image with Parallax-ish Scroll Effect */}
<motion.div
initial={{ opacity: 0, x: reverse ? -100 : 100, y: 50 }}
whileInView={{ opacity: 1, x: reverse ? "-40px" : "40px", y: 0 }}
viewport={{ once: true }}
transition={{ duration: 1, delay: 0.4, ease: "easeOut" }}
className={`absolute bottom-20 ${reverse ? 'left-0' : 'right-0'} z-10 w-48 md:w-80 aspect-[3/4] shadow-2xl hidden md:block`}
>
<Image
src={getCloudinaryUrl(secondImage, { width: 600, height: 800, crop: "fill" })}
alt={`${title} detail`}
fill
className="object-cover border-[10px] border-white"
/>
</motion.div>
</div>
</section>
);
}

View File

@@ -0,0 +1,120 @@
"use client";
import { motion } from "framer-motion";
import { useRef, useState, useEffect } from "react";
const testimonials = [
{
name: "Ayşe Y.",
location: "Türkiye",
text: "Bardakçı Koyu'nun büyüleyici manzarasında unutulmaz bir tatil geçirdik. Personelin ilgisi ve otelin zarafeti bizi mest etti.",
stars: 5
},
{
name: "John D.",
location: "United Kingdom",
text: "An absolutely stunning resort. The spa treatment was world-class, and the breakfast by the sea was the highlight of our stay.",
stars: 5
},
{
name: "Klaus M.",
location: "Germany",
text: "Sehr schönes Hotel mit exzellentem Service. Der Privatstrand ist kristallklar ve sehr ruhig. Wir kommen auf jeden Fall wieder!",
stars: 5
},
{
name: "Elena S.",
location: "Italy",
text: "Un posto magico. La colazione è fantastica e la camera con vista mare ha superato le nostre aspettative. Grazie Salmakis!",
stars: 5
},
{
name: "Mehmet A.",
location: "Türkiye",
text: "Gastronomi anlamında gerçekten çok başarılı. Her akşam farklı bir lezzet şöleni yaşadık. Sahili ise kelimenin tam anlamıyla kusursuz.",
stars: 5
}
];
export default function TestimonialsSlider() {
const constraintsRef = useRef<HTMLDivElement>(null);
const [width, setWidth] = useState(0);
useEffect(() => {
if (constraintsRef.current) {
// Calculate how much we can drag: total width - container width
setWidth(constraintsRef.current.scrollWidth - constraintsRef.current.offsetWidth);
}
}, []);
return (
<section className="bg-[#EAE5D8] py-24 overflow-hidden">
<div className="max-w-7xl mx-auto px-6 mb-16">
<div className="flex flex-col md:flex-row justify-between items-end gap-8">
<div className="space-y-4">
<span className="text-gold text-xs tracking-[0.4em] font-bold uppercase">
MİSAFİR YORUMLARI
</span>
<h2 className="text-5xl md:text-7xl font-serif text-gray-900 leading-tight">
Misafirlerimiz <br /> Ne Diyor?
</h2>
</div>
<div className="max-w-md text-right md:text-right flex flex-col items-end gap-6 pb-4">
<p className="text-gray-600 font-light leading-relaxed">
Gerçek deneyimler ve samimi sözler. Salmakis Resort & Spa&apos;daki anıların
her türlü tanımdan daha fazlasını anlattığına inanıyoruz.
</p>
<button className="bg-[#C59D5F] text-white px-8 py-3 rounded-md text-[10px] font-bold tracking-[0.2em] hover:bg-gold transition-all uppercase">
DENEYİMİNİZİ PAYLAŞIN
</button>
</div>
</div>
</div>
{/* Slider Container */}
<div className="relative w-full overflow-hidden pb-10">
<motion.div
ref={constraintsRef}
drag="x"
dragConstraints={{ right: 0, left: -width }}
dragElastic={0.1}
whileTap={{ cursor: "grabbing" }}
className="flex gap-6 px-6 md:px-[calc((100vw-1280px)/2)] cursor-grab whitespace-nowrap"
initial={{ x: 100, opacity: 0 }}
whileInView={{ x: 0, opacity: 1 }}
transition={{ duration: 1 }}
>
{testimonials.map((item, i) => (
<div
key={i}
className="min-w-[320px] md:min-w-[400px] bg-[#3A4D3F] p-10 flex flex-col justify-between h-[450px] shadow-2xl select-none"
>
<div className="space-y-6">
<div className="flex gap-1">
{[...Array(item.stars)].map((_, i) => (
<span key={i} className="text-white text-sm"></span>
))}
</div>
<div className="space-y-4">
<span className="text-white/40 text-[10px] tracking-widest font-bold uppercase">
{item.location}
</span>
<p className="text-white/90 text-lg md:text-xl font-light leading-relaxed italic whitespace-normal">
&ldquo;{item.text}&rdquo;
</p>
</div>
</div>
<div className="pt-6 border-t border-white/10">
<span className="text-white text-xs tracking-[0.2em] font-bold uppercase">
{item.name}
</span>
</div>
</div>
))}
</motion.div>
</div>
</section>
);
}