ss
This commit is contained in:
@@ -0,0 +1,778 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useRef, useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 40 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.7, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.1 } },
|
||||
};
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navReserve: "Rezervasyon",
|
||||
navHours: "Çalışma Saatleri",
|
||||
navCurator: "Kokteyl Menüsü",
|
||||
navReviews: "Değerlendirmeler",
|
||||
bookTable: "Masa Ayırt",
|
||||
exclusiveLounge: "ÖZEL KOKTEYL SALONU",
|
||||
cocktailStage: "KOKTEYL SAHNESİ",
|
||||
evenings: "geceleri",
|
||||
heroDesc: "Noir Velvet Lounge'a adım atın. Klasik karışımlar, botanik aromalar ve yıllanmış özel içkilerin loş kehribar akustiği altındaki benzersiz sunumunu keşfedin.",
|
||||
discoverMenu: "MENÜYÜ KEŞFET",
|
||||
reserveTableTitle: "Stage Booking",
|
||||
reserveTableHeader: "MASA AYIRTIN",
|
||||
reserveTableDesc: "Ana sahne akustik çizgilerinin altında, size özel bar tezgahı veya lounge masanızı şimdiden ayırtın.",
|
||||
fieldsName: "İsim Soyisim",
|
||||
fieldsPhone: "İletişim Numarası",
|
||||
fieldsDate: "Tarih",
|
||||
fieldsTime: "Saat",
|
||||
guarantee: "Bu formu doldurarak doğrulanmış bir rezervasyon sağlarsınız. Masalar, rezervasyon saatinden itibaren 15 dakika boyunca adınıza tutulur.",
|
||||
secureRes: "REZERVASYON YAP",
|
||||
curatorSpecials: "Küratörün Seçtikleri",
|
||||
weRecommend: "TAVSİYE EDİLENLER",
|
||||
signature: "İmza",
|
||||
loungeStories: "LOUNGE HİKAYELERİ",
|
||||
loungeStoriesDesc: "Seçkin miksolojistlerin ve caz akustiği kuratörlerinin salon hakkındaki yorumlarını keşfedin.",
|
||||
loungeHours: "ÇALIŞMA SAATLERİ",
|
||||
loungeDials: "İMZA KOKTEYLLER",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Salon Koşulları",
|
||||
dismiss: "KAPAT",
|
||||
enquiryActive: "REZERVASYON YAPILDI",
|
||||
ambassadorActive: "Sahne Mihmandarı Aktif",
|
||||
enquirySuccess: "Bar tezgahı veya lounge masası rezervasyonunuzu başarıyla kaydettik. Özel mihmandarımız giriş koordinatlarınızı doğrulamak için sizinle iletişime geçecektir. Teşekkürler!",
|
||||
},
|
||||
en: {
|
||||
navReserve: "Reserve Table",
|
||||
navHours: "Hours",
|
||||
navCurator: "Curator's Specials",
|
||||
navReviews: "Reviews",
|
||||
bookTable: "Book a table",
|
||||
exclusiveLounge: "EXCLUSIVE LOUNGE SERVICE",
|
||||
cocktailStage: "COCKTAIL STAGE",
|
||||
evenings: "evenings",
|
||||
heroDesc: "Step into Noir Velvet Lounge. Indulge in classic mixes, botanic blends, and aged private reserve spirits staged under moody amber acoustics.",
|
||||
discoverMenu: "DISCOVER STAGE MENU",
|
||||
reserveTableTitle: "Stage Booking",
|
||||
reserveTableHeader: "RESERVE A TABLE",
|
||||
reserveTableDesc: "Allocate your private counter or lounge table under the main stage acoustic lines.",
|
||||
fieldsName: "Name",
|
||||
fieldsPhone: "Phone",
|
||||
fieldsDate: "Date",
|
||||
fieldsTime: "Time",
|
||||
guarantee: "By submitting this form, you secure a verified reservation. Tables are held for 15 minutes past the booking coordinates.",
|
||||
secureRes: "SECURE RESERVATION",
|
||||
curatorSpecials: "Curator's Specials",
|
||||
weRecommend: "WE RECOMMEND",
|
||||
signature: "Signature",
|
||||
loungeStories: "LOUNGE STORIES",
|
||||
loungeStoriesDesc: "Hear what prominent mixologists and jazz acoustic curators write about the lounge.",
|
||||
loungeHours: "OPEN HOURS",
|
||||
loungeDials: "SPECIAL DIALS",
|
||||
privacyRegs: "Privacy Regulations",
|
||||
termsStay: "Terms of Lounge",
|
||||
dismiss: "DISMISS",
|
||||
enquiryActive: "TABLE RESERVED",
|
||||
ambassadorActive: "Stage Concierge Active",
|
||||
enquirySuccess: "We have secured your counter or lounge table reservation. A private host has registered your parameters. Thank you!",
|
||||
}
|
||||
};
|
||||
|
||||
export default function BarTemplate({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], yorumlar = [] } = data;
|
||||
const [showBookingModal, setShowBookingModal] = useState(false);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// 1. Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// 2. Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Localized statistics/hours
|
||||
const getLocalizedStat = (deger: string, etiket: string) => {
|
||||
if (deger.toLowerCase().includes("weekdays") || etiket.toLowerCase().includes("weekdays") || etiket.toLowerCase().includes("pazartesi")) {
|
||||
return {
|
||||
deger: lang === "tr" ? "Hafta İçi" : "Weekdays",
|
||||
etiket: lang === "tr" ? "Pazartesi - Cuma · 16:00 - 02:00" : "Monday - Friday · 4:00 PM - 2:00 AM"
|
||||
};
|
||||
}
|
||||
if (deger.toLowerCase().includes("weekends") || etiket.toLowerCase().includes("weekends") || etiket.toLowerCase().includes("cumartesi")) {
|
||||
return {
|
||||
deger: lang === "tr" ? "Hafta Sonu" : "Weekends",
|
||||
etiket: lang === "tr" ? "Cumartesi - Pazar · 16:00 - 04:00" : "Saturday - Sunday · 4:00 PM - 4:00 AM"
|
||||
};
|
||||
}
|
||||
if (deger.toLowerCase().includes("happy") || etiket.toLowerCase().includes("happy")) {
|
||||
return {
|
||||
deger: lang === "tr" ? "Happy Hour" : "Happy Hour",
|
||||
etiket: lang === "tr" ? "Her gün 17:00 - 19:00 arası imza kokteyllerde %20 indirim" : "Daily 5:00 PM - 7:00 PM · 20% off signature mixology"
|
||||
};
|
||||
}
|
||||
return {
|
||||
deger: lang === "tr" ? "Özel Karışımlar" : deger,
|
||||
etiket: lang === "tr" ? "Taze botanik şuruplar ve el yapımı bitters infüzyonları." : etiket
|
||||
};
|
||||
};
|
||||
|
||||
// Localized services/beverages
|
||||
const getLocalizedService = (baslik: string, aciklama: string) => {
|
||||
if (baslik.toLowerCase().includes("velvet") || baslik.toLowerCase().includes("velvet kiss")) {
|
||||
return {
|
||||
title: lang === "tr" ? "VELVET KISS KOKTEYLİ" : "VELVET KISS COCKTAIL",
|
||||
desc: lang === "tr" ? "Kendi yapımımız taze vişne likörü, vanilya şurubu ve dumanlanmış ardıç aromaları ile hazırlanan imza içkimiz." : aciklama
|
||||
};
|
||||
}
|
||||
if (baslik.toLowerCase().includes("amber") || baslik.toLowerCase().includes("amber smoke") || baslik.toLowerCase().includes("smoke")) {
|
||||
return {
|
||||
title: lang === "tr" ? "KEHRİBAR DUMANI" : "AMBER SMOKE",
|
||||
desc: lang === "tr" ? "Ağaç talaşı isi ile tütsülenmiş viski, botanik acı otlar ve karamelize portakal dilimi." : aciklama
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: lang === "tr" ? "BOTANİK RÜYA" : "BOTANICAL DREAM",
|
||||
desc: lang === "tr" ? "Taze biberiye infüzyonu, narenciye asidi ve organik zencefil gazozu ile canlandırıcı hafif bir karışım." : aciklama
|
||||
};
|
||||
};
|
||||
|
||||
// Custom visual styles & Google Fonts for our Classic Noir Velvet aesthetic
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;0,700;1,400&family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
|
||||
|
||||
:root {
|
||||
--color-velvet-gold: #D4AF37;
|
||||
--color-velvet-black: #09090C;
|
||||
--color-velvet-card: #14141A;
|
||||
--color-text-white: #E8E8E8;
|
||||
--color-text-muted: rgba(232, 232, 232, 0.6);
|
||||
}
|
||||
|
||||
.font-serif-editorial {
|
||||
font-family: 'Cormorant Garamond', Georgia, serif;
|
||||
}
|
||||
|
||||
.font-serif-lux {
|
||||
font-family: 'Cormorant Garamond', Georgia, serif;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.font-sans-clean {
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
}
|
||||
|
||||
.bg-mesh-velvet {
|
||||
background-image:
|
||||
radial-gradient(circle at 5% 5%, rgba(212, 175, 55, 0.03) 0%, transparent 40%),
|
||||
radial-gradient(circle at 95% 95%, rgba(212, 175, 55, 0.02) 0%, transparent 50%);
|
||||
}
|
||||
|
||||
.gold-glow {
|
||||
box-shadow: 0 0 20px rgba(212, 175, 55, 0.15);
|
||||
}
|
||||
|
||||
/* Slow pulse for active indicators */
|
||||
.pulse-gold {
|
||||
animation: goldPulse 2.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes goldPulse {
|
||||
0% { box-shadow: 0 0 0 0 rgba(212, 175, 55, 0.4); }
|
||||
70% { box-shadow: 0 0 0 10px rgba(212, 175, 55, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(212, 175, 55, 0); }
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(48px, 8vw, 110px);
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 0.9;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#09090C] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-black tracking-[4px] uppercase text-[#D4AF37] block font-sans-clean"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
NOIR VELVET LOUNGE
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#D4AF37]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-serif-editorial text-white text-lg italic font-light tracking-wider"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
mixology & acoustic lounge
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* ── NOIR VELVET LOUNGE ── */}
|
||||
<div className="bg-[#09090C] text-[#E8E8E8] min-h-screen font-sans-clean selection:bg-[#D4AF37] selection:text-black overflow-hidden relative bg-mesh-velvet pb-20">
|
||||
|
||||
{/* Floating Ambient Gold Orbs */}
|
||||
<div className="absolute top-[25%] left-[-10%] w-[500px] h-[500px] bg-[#D4AF37]/3 blur-[120px] rounded-full pointer-events-none z-0" />
|
||||
<div className="absolute bottom-[25%] right-[-10%] w-[500px] h-[500px] bg-[#D4AF37]/3 blur-[130px] rounded-full pointer-events-none z-0" />
|
||||
|
||||
{/* ── MANDATORY FLOATING DEMO BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#09090C]/95 backdrop-blur-md border border-white/5 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#D4AF37] animate-pulse" />
|
||||
<span className="text-[9px] font-black uppercase tracking-[1.5px] text-white/90">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* ── GOLD FLOATING NAVBAR ── */}
|
||||
<motion.header
|
||||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||||
initial={{ y: -80, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.7, ease: "easeOut" }}
|
||||
>
|
||||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-[#09090C]/80 backdrop-blur-xl border border-[#D4AF37]/10 rounded-2xl shadow-[0_15px_30px_rgba(0,0,0,0.6)]">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2 group">
|
||||
<span className="text-xl font-bold tracking-[2px] text-white font-serif-lux flex items-center gap-2.5 uppercase">
|
||||
<svg className="w-5 h-5 text-[#D4AF37]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M12 22V12" />
|
||||
<path d="M5 12h14" />
|
||||
<path d="M21 3H3l9 9Z" />
|
||||
<path d="M12 12H7.5" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Navigation Links */}
|
||||
<nav className="hidden lg:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navReserve, href: "#booking-flow" },
|
||||
{ label: t.navHours, href: "#hours-happy" },
|
||||
{ label: t.navCurator, href: "#curated-menu" },
|
||||
{ label: t.navReviews, href: "#testimonials" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[10px] font-bold tracking-[2px] uppercase text-[#E8E8E8]/70 hover:text-[#D4AF37] transition-colors relative py-1 cursor-pointer group"
|
||||
>
|
||||
{item.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#D4AF37] transition-all group-hover:w-full" />
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Action button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-white/5 border border-white/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-[#D4AF37] text-black shadow-sm" : "text-white/60 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-[#D4AF37] text-black shadow-sm" : "text-white/60 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[10px] font-bold tracking-[2.5px] uppercase text-black bg-[#D4AF37] hover:bg-white px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_5px_15px_rgba(212,175,55,0.15)] hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.bookTable}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── HERO & HOURS BLOCK ── */}
|
||||
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-12 items-center">
|
||||
|
||||
{/* Left Column: Headings & Hours details */}
|
||||
<motion.div
|
||||
className="lg:col-span-6 z-20"
|
||||
variants={stagger}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="inline-flex items-center gap-2 text-[10px] font-bold uppercase tracking-widest text-[#D4AF37] mb-6 bg-[#D4AF37]/5 border border-[#D4AF37]/15 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#D4AF37]" />
|
||||
{t.exclusiveLounge}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={fadeUp}
|
||||
className="font-serif-lux text-white leading-[0.95] tracking-tight mb-8 uppercase hero-title-clamp"
|
||||
>
|
||||
{t.cocktailStage}
|
||||
<br />
|
||||
<span className="italic font-serif-editorial font-light text-[#D4AF37] lowercase">{t.evenings}</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-white/60 text-xs lg:text-sm leading-relaxed max-w-md mb-12 font-medium"
|
||||
>
|
||||
{t.heroDesc}
|
||||
</motion.p>
|
||||
|
||||
{/* Grid details (Open Hours & Happy Hour) */}
|
||||
<motion.div
|
||||
id="hours-happy"
|
||||
variants={fadeUp}
|
||||
className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-12"
|
||||
>
|
||||
{istatistikler.map((stat, idx) => {
|
||||
const locStat = getLocalizedStat(stat.deger, stat.etiket);
|
||||
return (
|
||||
<div key={idx} className="border-l border-[#D4AF37]/30 pl-4 py-1">
|
||||
<h4 className="font-serif-lux font-bold text-white text-xs uppercase tracking-widest mb-2 text-[#D4AF37]">
|
||||
{locStat.deger}
|
||||
</h4>
|
||||
<p className="text-white/50 text-[11px] leading-relaxed font-medium">
|
||||
{locStat.etiket}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
|
||||
{/* Action CTA */}
|
||||
<motion.div variants={fadeUp}>
|
||||
<a
|
||||
href="#curated-menu"
|
||||
className="inline-flex items-center gap-3 px-8 py-4 rounded-xl bg-[#D4AF37] hover:bg-white text-black font-bold text-[10px] tracking-[2px] uppercase transition-all shadow-[0_5px_15px_rgba(212,175,55,0.2)] cursor-pointer animate-pulse"
|
||||
>
|
||||
{t.discoverMenu}
|
||||
</a>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: Parallax Moody Graphic Counter */}
|
||||
<div className="lg:col-span-6 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-md lg:max-w-lg h-[450px] lg:h-[520px] rounded-3xl overflow-hidden shadow-2xl border border-[#D4AF37]/15 group"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
>
|
||||
{/* Outer glowing gold ring */}
|
||||
<div className="absolute inset-4 rounded-[20px] border border-dashed border-[#D4AF37]/10 animate-[spin_80s_linear_infinite] pointer-events-none" />
|
||||
|
||||
{/* Using 8k Fresh Citrus flatlay to represent natural ingredients and botanical prep */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/sicilia_lemon_heritage.png"
|
||||
alt="Noir Velvet Fresh Citrus & Botanical Garnishes"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms] brightness-[0.75]"
|
||||
/>
|
||||
|
||||
{/* Overlay velvet glow */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-80" />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── RESERVATION TABLE BUILDER ── */}
|
||||
<section id="booking-flow" className="py-24 relative z-10 px-6 border-t border-[#D4AF37]/15 bg-[#09090C]/90">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
|
||||
<div className="bg-[#14141A] rounded-3xl border border-white/5 p-8 md:p-12 shadow-2xl relative">
|
||||
|
||||
{/* Thin gold line connector indicator */}
|
||||
<div className="absolute top-0 left-12 right-12 h-0.5 bg-gradient-to-r from-transparent via-[#D4AF37] to-transparent" />
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-12">
|
||||
<span className="text-[#D4AF37] font-bold text-[10px] tracking-[2px] uppercase block mb-2 font-serif-lux">{t.reserveTableTitle}</span>
|
||||
<h2 className="font-serif-lux text-3xl font-black uppercase text-white">
|
||||
{t.reserveTableHeader}
|
||||
</h2>
|
||||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||||
{t.reserveTableDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Form Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{[
|
||||
{ label: t.fieldsName, placeholder: lang === "tr" ? "Adınız Soyadınız" : "Your Name", type: "text" },
|
||||
{ label: t.fieldsPhone, placeholder: lang === "tr" ? "İrtibat Numarası" : "Contact Number", type: "tel" },
|
||||
{ label: t.fieldsDate, placeholder: "", type: "date" },
|
||||
{ label: t.fieldsTime, placeholder: "", type: "time" },
|
||||
].map((field, idx) => (
|
||||
<div key={idx} className="flex flex-col">
|
||||
<label className="text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{field.label}</label>
|
||||
<input
|
||||
type={field.type}
|
||||
placeholder={field.placeholder}
|
||||
className="px-4 py-3.5 rounded-xl border border-white/5 bg-[#09090C] text-xs text-white placeholder-white/20 focus:outline-none focus:border-[#D4AF37] focus:ring-1 focus:ring-[#D4AF37] transition-all font-medium cursor-pointer"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Form Submit Row */}
|
||||
<div className="mt-8 pt-4 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p className="text-white/40 text-xs font-medium max-w-md text-center md:text-left">
|
||||
{t.guarantee}
|
||||
</p>
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="w-full md:w-auto px-10 py-4.5 rounded-xl bg-[#D4AF37] hover:bg-white text-black font-bold text-[10px] tracking-[2px] uppercase transition-all cursor-pointer shadow-[0_5px_15px_rgba(212,175,55,0.2)] shrink-0"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.secureRes}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CURATOR'S SPECIALS MENU (DOTTED CONNECTORS) ── */}
|
||||
<section id="curated-menu" className="py-32 relative z-10 px-6 bg-[#09090C]">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||||
|
||||
{/* Left Column: Fine dotted Menu lists */}
|
||||
<motion.div
|
||||
className="lg:col-span-7 flex flex-col justify-center"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true, amount: 0.2 }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="text-[#D4AF37] font-serif-lux italic text-xs tracking-[2px] uppercase block mb-4"
|
||||
>
|
||||
{t.curatorSpecials}
|
||||
</motion.span>
|
||||
<motion.h2
|
||||
variants={fadeUp}
|
||||
className="font-serif-lux text-4xl lg:text-5xl font-black tracking-tight text-white uppercase mb-16"
|
||||
>
|
||||
{t.weRecommend}
|
||||
</motion.h2>
|
||||
|
||||
{/* Dotted menu */}
|
||||
<div className="space-y-8">
|
||||
{hizmetler.map((item, idx) => {
|
||||
const locBeverage = getLocalizedService(item.baslik, item.aciklama);
|
||||
return (
|
||||
<motion.div
|
||||
key={idx}
|
||||
variants={fadeUp}
|
||||
className="flex flex-col cursor-pointer group"
|
||||
>
|
||||
<div className="flex items-end justify-between gap-4">
|
||||
<span className="font-serif-lux text-base lg:text-lg font-bold text-white group-hover:text-[#D4AF37] transition-colors uppercase tracking-wider">
|
||||
{locBeverage.title}
|
||||
</span>
|
||||
{/* Fine dotted line */}
|
||||
<div className="grow border-b border-dashed border-[#D4AF37]/25 mb-2.5 mx-2" />
|
||||
<span className="font-serif-lux text-base lg:text-lg font-black text-[#D4AF37]">
|
||||
$19
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-white/50 text-[11px] mt-1.5 leading-relaxed max-w-lg font-medium">
|
||||
{locBeverage.desc}
|
||||
</p>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: Close-up action image counter */}
|
||||
<div className="lg:col-span-5 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-sm h-[480px] lg:h-[550px] rounded-3xl overflow-hidden shadow-2xl border border-white/5 group"
|
||||
initial={{ opacity: 0, x: 40 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
>
|
||||
{/* Using 8k Chef Plating Smoke image to represent curator mixology and smoky vapor */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/chef_plating_smoke.png"
|
||||
alt="Curator liquid smoke mixology stage"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms] brightness-[0.8]"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-60" />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── TESTIMONIALS ── */}
|
||||
<section id="testimonials" className="py-28 relative z-10 px-6 bg-[#09090C]/90 border-t border-[#D4AF37]/10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#D4AF37] font-bold text-[10px] tracking-[2px] uppercase block mb-2 font-serif-lux">{t.navReviews}</span>
|
||||
<h2 className="font-serif-lux text-3xl lg:text-4xl font-black uppercase text-white tracking-widest">
|
||||
{t.loungeStories}
|
||||
</h2>
|
||||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||||
{t.loungeStoriesDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Testimonials 2-Column Grid */}
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{yorumlar.map((y, yIdx) => (
|
||||
<motion.div
|
||||
key={yIdx}
|
||||
className="bg-[#14141A] border border-white/5 rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 hover:border-[#D4AF37]/30 group shadow-lg"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: yIdx * 0.1 }}
|
||||
whileHover={{ y: -4 }}
|
||||
>
|
||||
{/* Rating Stars SVG */}
|
||||
<div className="flex gap-1.5 mb-6">
|
||||
{[...Array(y.puan)].map((_, starIdx) => (
|
||||
<svg key={starIdx} className="w-4 h-4 fill-[#D4AF37]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="text-white/70 text-xs leading-relaxed italic mb-8 font-medium font-serif-editorial">
|
||||
“{y.yorum}”
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full border border-white/10 flex items-center justify-center text-lg bg-[#09090C] font-sans-clean select-none font-bold">
|
||||
{y.yazar.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-serif-lux text-white text-xs font-black uppercase tracking-wider">
|
||||
{y.yazar}
|
||||
</h4>
|
||||
<span className="text-[9px] text-white/40 uppercase tracking-widest font-bold font-sans-clean">
|
||||
{y.tarih}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-[#09090C] border-t border-white/5 pt-24 pb-8 px-6 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
|
||||
|
||||
{/* About Column */}
|
||||
<div className="md:col-span-2">
|
||||
<span className="font-serif-lux text-2xl font-black text-white tracking-wider uppercase mb-4 block">
|
||||
Noir<span className="text-[#D4AF37]">Velvet</span>
|
||||
</span>
|
||||
<p className="text-white/50 text-xs leading-relaxed max-w-sm mb-8 font-medium">
|
||||
{firma.slogan} — Classic dark luxury lounge delivering organic mixology under curated acoustic stage lines.
|
||||
</p>
|
||||
<div className="text-white/60 text-xs font-medium space-y-3">
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#D4AF37] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
<span className="text-white/80">{firma.adres}</span>
|
||||
</p>
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#D4AF37] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect width="20" height="16" x="2" y="4" rx="2" />
|
||||
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" />
|
||||
</svg>
|
||||
<span className="text-white/80">{firma.email}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Hours Column */}
|
||||
<div>
|
||||
<h4 className="font-serif-lux text-[#D4AF37] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{t.loungeHours}
|
||||
</h4>
|
||||
<div className="space-y-4 text-xs text-white/50 font-medium">
|
||||
<p>{lang === "tr" ? "Pazartesi - Cuma" : "Monday - Friday"} <br /> <span className="text-white/70">4:00 PM - 2:00 AM</span></p>
|
||||
<p>{lang === "tr" ? "Cumartesi - Pazar" : "Saturday - Sunday"} <br /> <span className="text-white/70">4:00 PM - 4:00 AM</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Specials Column */}
|
||||
<div>
|
||||
<h4 className="font-serif-lux text-[#D4AF37] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{t.loungeDials}
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{hizmetler.map((h, hIdx) => {
|
||||
const locB = getLocalizedService(h.baslik, h.aciklama);
|
||||
return (
|
||||
<a
|
||||
key={hIdx}
|
||||
href="#curated-menu"
|
||||
className="block text-white/50 hover:text-[#D4AF37] text-xs transition-colors font-medium"
|
||||
>
|
||||
{locB.title} {t.signature}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs font-medium">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-white transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── FAST TABLE SUCCESS MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showBookingModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/85 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-[#14141A] rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-[#D4AF37]/20"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-[#09090C] border border-white/5 flex items-center justify-center text-white/40 hover:text-[#D4AF37] hover:border-[#D4AF37]/20 transition-all cursor-pointer font-bold"
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
{/* Success check indicator */}
|
||||
<div className="w-16 h-16 rounded-2xl bg-[#D4AF37]/10 border border-[#D4AF37]/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-8 h-8 stroke-[#D4AF37] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 className="font-serif-lux font-black text-white text-2xl mb-1 uppercase tracking-wider">
|
||||
{t.enquiryActive}
|
||||
</h3>
|
||||
<p className="text-[#D4AF37] font-mono text-[10px] mb-6 uppercase tracking-widest font-bold">
|
||||
{t.ambassadorActive}
|
||||
</p>
|
||||
|
||||
<p className="text-white/60 text-xs leading-relaxed mb-8 font-medium">
|
||||
{t.enquirySuccess}
|
||||
</p>
|
||||
|
||||
<motion.button
|
||||
className="w-full py-4.5 rounded-xl bg-[#D4AF37] hover:bg-white text-black font-bold text-[10px] tracking-[2px] uppercase cursor-pointer shadow-md shadow-[#D4AF37]/15"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
{t.dismiss}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,873 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useRef, useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 40 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.7, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.1 } },
|
||||
};
|
||||
|
||||
interface DrinkSpec {
|
||||
name: string;
|
||||
desc: string;
|
||||
capacity: string;
|
||||
alcohol: string;
|
||||
relax: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navSpecials: "İmza Serisi",
|
||||
navReserve: "Etkinlik Planla",
|
||||
navFlights: "Tadım Serileri",
|
||||
navReviews: "Gurme Yorumları",
|
||||
scheduleCall: "Görüşme Planla",
|
||||
ultimateExp: "EŞSİZ KOKTEYL DENEYİMİ",
|
||||
dedicationTitle: "PROFESYONEL MİKSOLOJİ VE",
|
||||
dedicationTail: "EL YAPIMI BAĞLILIK",
|
||||
heroDesc: "Zanaatkar viski tadım uçuşları, kişisel miksoloji eğitimleri ve kurumsal atölye buluşmalarına dahil olun. Ham meşe ağacı ve oyma taş tezgahlar üzerinde hazırlanır.",
|
||||
scheduleCallBtn: "GÖRÜŞME AYARLA",
|
||||
artisanalSelections: "SANATSAL SEÇENEKLER",
|
||||
signatureLiquors: "İmza İksirler",
|
||||
chooseDrink: "FAVORİ İÇKİNİZİ SEÇİN",
|
||||
sliderDesc: "Ustalıkla hazırlanan reçetelerimizi inceleyin. Aktif hacim, alkol derecesi ve gevşeme oranlarını görüntüleyin.",
|
||||
capacity: "HACİM",
|
||||
alcohol: "ALKOL",
|
||||
relax: "GEVŞEME",
|
||||
barrelhouseEvents: "Fıçı Evi Etkinlikleri",
|
||||
featuredServices: "SEÇKİN HİZMETLER",
|
||||
learnMore: "DAHA FAZLA KEŞFET →",
|
||||
masterclassBooking: "Rezervasyon",
|
||||
scheduleEvent: "BİR ETKİNLİK PLANLAYIN",
|
||||
formDesc: "Viski tadım serileri veya miksoloji dersleri organize etmek için sommelier koordinatörümüzle iletişime geçin.",
|
||||
fieldsName: "İsim Soyisim",
|
||||
fieldsEmail: "E-Posta Adresi",
|
||||
fieldsPhone: "İrtibat Numarası",
|
||||
fieldsEvent: "Etkinlik Kategorisi",
|
||||
fieldsNotes: "Özel İstekler",
|
||||
fieldsNotesPlaceholder: "Aroma tercihleri veya VIP mihmandar gereksinimleri...",
|
||||
dispatchRequest: "ETKİNLİK TALEBİNİ GÖNDER",
|
||||
sommelierReviews: "Gurme Yorumları",
|
||||
happyGuests: "MİSAFİR DENEYİMLERİ",
|
||||
happyGuestsDesc: "Yıllanmış tek malt ve fıçı serisi tadım etkinliklerimiz hakkında ne yazdıklarını keşfedin.",
|
||||
artisanalDials: "SANATSAL SERİ",
|
||||
vipServices: "VIP HİZMETLER",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Fıçı Koşulları",
|
||||
dismiss: "KAPAT",
|
||||
enquiryActive: "TALEBİNİZ GÖNDERİLDİ",
|
||||
ambassadorActive: "Mihmandar Sommelier Aktif",
|
||||
enquirySuccess: "Özel fıçı evi tadım/etkinlik talebinizi başarıyla kaydettik. Sertifikalı mihmandarımız tadım parametrelerinizi kesinleştirmek için sizinle iletişime geçecektir. Teşekkürler!",
|
||||
},
|
||||
en: {
|
||||
navSpecials: "Specials",
|
||||
navReserve: "Book experience",
|
||||
navFlights: "Sommelier flights",
|
||||
navReviews: "Sommelier reviews",
|
||||
scheduleCall: "Schedule call",
|
||||
ultimateExp: "THE ULTIMATE COCKTAIL EXPERIENCE",
|
||||
dedicationTitle: "DEDICATION TO",
|
||||
dedicationTail: "PROFESSIONAL CRAFT & SPIRIT",
|
||||
heroDesc: "Indulge in artisanal whiskey flights, custom mixology, and corporate masterclass gatherings. Staged on heavy raw oak and carved stones.",
|
||||
scheduleCallBtn: "SCHEDULE A CALL",
|
||||
artisanalSelections: "ARTISANAL SELECTIONS",
|
||||
signatureLiquors: "Signature Liquors",
|
||||
chooseDrink: "CHOOSE FAVORITE DRINK",
|
||||
sliderDesc: "Cycle through our mastercraft recipes. Toggle active stats, proof, and relax levels.",
|
||||
capacity: "CAPACITY",
|
||||
alcohol: "ALCOHOL",
|
||||
relax: "RELAX",
|
||||
barrelhouseEvents: "Barrelhouse Events",
|
||||
featuredServices: "FEATURED SERVICES",
|
||||
learnMore: "LEARN MORE →",
|
||||
masterclassBooking: "Masterclass booking",
|
||||
scheduleEvent: "SCHEDULE AN EVENT",
|
||||
formDesc: "Connect with our sommelier coordinator to arrange whiskey flights or mixology classes.",
|
||||
fieldsName: "Name",
|
||||
fieldsEmail: "Email",
|
||||
fieldsPhone: "Phone",
|
||||
fieldsEvent: "Event Type",
|
||||
fieldsNotes: "Special notes",
|
||||
fieldsNotesPlaceholder: "Flavor preferences or VIP requirements...",
|
||||
dispatchRequest: "DISPATCH EVENT REQUEST",
|
||||
sommelierReviews: "Sommelier Reviews",
|
||||
happyGuests: "HAPPY GUESTS",
|
||||
happyGuestsDesc: "Hear what craft enthusiasts write about our private aged single malt coordinates.",
|
||||
artisanalDials: "ARTISANAL DIALS",
|
||||
vipServices: "VIP SERVICES",
|
||||
privacyRegs: "Privacy Regulations",
|
||||
termsStay: "Terms of Cask",
|
||||
dismiss: "DISMISS",
|
||||
enquiryActive: "EVENT DISPATCHED",
|
||||
ambassadorActive: "Barrelhouse Sommelier Active",
|
||||
enquirySuccess: "We have registered your private barrelhouse coordinate request. A certified somatic host will contact you shortly to confirm whiskey flights or mixology parameters. Thank you!",
|
||||
}
|
||||
};
|
||||
|
||||
export default function BarTemplate2({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], yorumlar = [] } = data;
|
||||
const [showBookingModal, setShowBookingModal] = useState(false);
|
||||
const [activeDrink, setActiveDrink] = useState<number>(1); // Mai Tai active by default
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// 1. Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// 2. Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const getLocalizedDrinks = () => {
|
||||
return [
|
||||
{
|
||||
name: lang === "tr" ? "Mojito" : "Mojito",
|
||||
desc: lang === "tr" ? "Taze beyaz Küba romu, el ezmesi nane yaprakları, organik misket limonu suyu, ham kamış şekeri ve soğuk maden suyu." : "Fresh white cuban rum, hand-crushed spearmint, organic lime juice reduction, raw cane sugar, chilled splash of soda.",
|
||||
capacity: "350ml",
|
||||
alcohol: "12%",
|
||||
relax: "80%",
|
||||
color: "#00E5FF"
|
||||
},
|
||||
{
|
||||
name: lang === "tr" ? "Mai Tai" : "Mai Tai",
|
||||
desc: lang === "tr" ? "Premium Jamaika kehribar romu, üç kez damıtılmış portakal likörü, organik badem şurubu ve taze sıkılmış misket limonu." : "Premium Jamaican amber rum, triple-distilled orange curaçao, organic almond orgeat syrup, fresh lime squeeze.",
|
||||
capacity: "280ml",
|
||||
alcohol: "18%",
|
||||
relax: "90%",
|
||||
color: "#FF9F00"
|
||||
},
|
||||
{
|
||||
name: lang === "tr" ? "Rum Cosmo" : "Rum Cosmo",
|
||||
desc: lang === "tr" ? "Fıçıda yıllanmış koyu rom, dağ kızılcığı infüzyonu, organik portakal likörü ve portakal yağı buğusu." : "Cask-aged dark rum, wild mountain cranberry infusion, organic triple sec, orange oil mist garnish.",
|
||||
capacity: "200ml",
|
||||
alcohol: "22%",
|
||||
relax: "95%",
|
||||
color: "#FF007A"
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
const getLocalizedService = (baslik: string, aciklama: string) => {
|
||||
if (baslik.toLowerCase().includes("whiskey") || baslik.toLowerCase().includes("flight") || baslik.toLowerCase().includes("tadim")) {
|
||||
return {
|
||||
title: lang === "tr" ? "VİSKİ TADIM UÇUŞLARI" : "WHISKEY FLIGHTS",
|
||||
desc: lang === "tr" ? "Dünyanın en seçkin fıçılarından gelen yıllanmış tek malt ve burbon viski serilerinin özel sunumu." : aciklama
|
||||
};
|
||||
}
|
||||
if (baslik.toLowerCase().includes("mixology") || baslik.toLowerCase().includes("class") || baslik.toLowerCase().includes("ders")) {
|
||||
return {
|
||||
title: lang === "tr" ? "MİKSOLOJİ EĞİTİMLERİ" : "MIXOLOGY CLASSES",
|
||||
desc: lang === "tr" ? "Profesyonel barmenlerimiz eşliğinde kendi taze şuruplarınızı ve kokteyllerinizi yapmayı öğrenin." : aciklama
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: lang === "tr" ? "ÖZEL KOKTEYL HİZMETİ" : "PRIVATE COCKTAIL CATERING",
|
||||
desc: lang === "tr" ? "Kurumsal lansmanlar, VIP davetler ve butik etkinlikler için özel miksoloji menüsü ve servis ekibi." : aciklama
|
||||
};
|
||||
};
|
||||
|
||||
const drinks = getLocalizedDrinks();
|
||||
|
||||
// Custom visual styles & Google Fonts for our Rustic Chalk & Char aesthetic
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;0,700;1,400&family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
|
||||
|
||||
:root {
|
||||
--color-char-red: #E63946;
|
||||
--color-char-slate: #111215;
|
||||
--color-char-card: #18191E;
|
||||
--color-text-white: #FCFAF7;
|
||||
--color-text-muted: rgba(252, 252, 247, 0.5);
|
||||
}
|
||||
|
||||
.font-industrial {
|
||||
font-family: 'Cormorant Garamond', Georgia, serif;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.font-sans-clean {
|
||||
font-family: 'Space Grotesk', sans-serif;
|
||||
}
|
||||
|
||||
.bg-mesh-char {
|
||||
background-image:
|
||||
radial-gradient(circle at 10% 20%, rgba(230, 57, 70, 0.04) 0%, transparent 45%),
|
||||
radial-gradient(circle at 90% 80%, rgba(229, 169, 0, 0.03) 0%, transparent 50%),
|
||||
linear-gradient(rgba(255, 255, 255, 0.005) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(255, 255, 255, 0.005) 1px, transparent 1px);
|
||||
background-size: 100% 100%, 100% 100%, 40px 40px, 40px 40px;
|
||||
}
|
||||
|
||||
.crimson-glow {
|
||||
box-shadow: 0 0 20px rgba(230, 57, 70, 0.25);
|
||||
}
|
||||
|
||||
/* Pulse animation for CTA strip */
|
||||
.pulse-glow-crimson {
|
||||
animation: crimsonPulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes crimsonPulse {
|
||||
0% { box-shadow: 0 0 0 0 rgba(230, 57, 70, 0.4); }
|
||||
70% { box-shadow: 0 0 0 12px rgba(230, 57, 70, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(230, 57, 70, 0); }
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(42px, 7.5vw, 100px);
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 0.95;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#111215] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-black tracking-[4px] uppercase text-[#E63946] block font-sans-clean"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
CHAR BARRELHOUSE
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#E63946]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-industrial text-white text-lg font-light tracking-wider"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
barrel aged mixology
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* ── CHALK & CHAR BARRELHOUSE ── */}
|
||||
<div className="bg-[#111215] text-[#FCFAF7] min-h-screen font-sans-clean selection:bg-[#E63946] selection:text-white overflow-hidden relative bg-mesh-char pb-20">
|
||||
|
||||
{/* Floating Ambient Red Orbs */}
|
||||
<div className="absolute top-[15%] left-[-15%] w-[600px] h-[600px] bg-[#E63946]/4 blur-[130px] rounded-full pointer-events-none z-0" />
|
||||
<div className="absolute bottom-[15%] right-[-15%] w-[600px] h-[600px] bg-[#E5A900]/2 blur-[140px] rounded-full pointer-events-none z-0" />
|
||||
|
||||
{/* ── MANDATORY FLOATING DEMO BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#18191E]/95 backdrop-blur-md border border-white/5 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#E63946] animate-pulse" />
|
||||
<span className="text-[9px] font-black uppercase tracking-[1.5px] text-white/90">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* ── HIGH CONTRAST NAVBAR ── */}
|
||||
<motion.header
|
||||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||||
initial={{ y: -80, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.7, ease: "easeOut" }}
|
||||
>
|
||||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-[#18191E]/95 backdrop-blur-xl border border-white/5 rounded-2xl shadow-[0_15px_30px_rgba(0,0,0,0.5)]">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2 group">
|
||||
<span className="text-xl font-bold tracking-[1.5px] text-white font-industrial flex items-center gap-2.5 uppercase">
|
||||
<svg className="w-5 h-5 text-[#E63946]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M5 3l1.5 15.5a2 2 0 0 0 2 1.5h7a2 2 0 0 0 2-1.5L19 3H5Z" />
|
||||
<path d="M6 10h12" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Navigation Links */}
|
||||
<nav className="hidden lg:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navSpecials, href: "#drink-selector" },
|
||||
{ label: t.navReserve, href: "#booking-flow" },
|
||||
{ label: t.navFlights, href: "#experiences" },
|
||||
{ label: t.navReviews, href: "#testimonials" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[10px] font-bold tracking-[2px] uppercase text-[#FCFAF7]/70 hover:text-[#E63946] transition-colors relative py-1 cursor-pointer group"
|
||||
>
|
||||
{item.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#E63946] transition-all group-hover:w-full" />
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Action button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-white/5 border border-white/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-[#E63946] text-white shadow-sm" : "text-white/60 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-[#E63946] text-white shadow-sm" : "text-white/60 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[10px] font-bold tracking-[2.5px] uppercase text-white bg-[#E63946] hover:bg-white hover:text-black px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_5px_15px_rgba(230,57,70,0.2)] hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.scheduleCall}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── HERO SECTION ── */}
|
||||
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-12 items-center">
|
||||
|
||||
{/* Left Column: Heading and description */}
|
||||
<motion.div
|
||||
className="lg:col-span-7 z-20"
|
||||
variants={stagger}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="inline-flex items-center gap-2 text-[10px] font-bold uppercase tracking-widest text-[#E63946] mb-6 bg-[#E63946]/10 border border-[#E63946]/20 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#E63946]" />
|
||||
{t.ultimateExp}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={fadeUp}
|
||||
className="font-industrial text-white leading-[0.95] tracking-tight mb-6 uppercase hero-title-clamp"
|
||||
>
|
||||
{t.dedicationTitle}
|
||||
<br />
|
||||
<span className="text-[#E63946]">{t.dedicationTail}</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-white/60 text-xs lg:text-sm leading-relaxed max-w-xl mb-10 font-medium"
|
||||
>
|
||||
{t.heroDesc}
|
||||
</motion.p>
|
||||
|
||||
{/* Quick actions */}
|
||||
<motion.div variants={fadeUp} className="flex gap-4">
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="px-8 py-4 rounded-xl bg-[#E63946] hover:bg-white hover:text-black text-white font-bold text-[10px] tracking-[2px] uppercase transition-all shadow-[0_5px_15px_rgba(230,57,70,0.25)] cursor-pointer"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
>
|
||||
{t.scheduleCallBtn}
|
||||
</motion.button>
|
||||
<a
|
||||
href="#drink-selector"
|
||||
className="px-8 py-4 rounded-xl border border-white/10 bg-white/5 hover:bg-white/10 text-white font-bold text-[10px] tracking-[2px] uppercase transition-all cursor-pointer text-center"
|
||||
>
|
||||
{t.artisanalSelections}
|
||||
</a>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: High-fidelity image (steak/drink counter) */}
|
||||
<div className="lg:col-span-5 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-md lg:max-w-lg h-[400px] lg:h-[480px] rounded-3xl overflow-hidden shadow-2xl border border-white/5 group"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
>
|
||||
{/* Using 8k Chef Plating Smoke image to represent premium cask smoking counter */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/chef_plating_smoke.png"
|
||||
alt="Char Barrelhouse Cask-Aged Spirits Smoking Counter"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms]"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-50" />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── ARTISANAL CAROUSEL SLIDER ── */}
|
||||
<section id="drink-selector" className="py-28 relative z-10 px-6 bg-[#18191E]/60 border-t border-white/5">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#E63946] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.signatureLiquors}</span>
|
||||
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
|
||||
{t.chooseDrink}
|
||||
</h2>
|
||||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||||
{t.sliderDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Slider container */}
|
||||
<div className="grid lg:grid-cols-12 gap-12 items-center">
|
||||
|
||||
{/* Left Column: Drink Tabs & Specifications */}
|
||||
<div className="lg:col-span-7 space-y-8">
|
||||
{/* Tabs */}
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
{drinks.map((d, dIdx) => (
|
||||
<button
|
||||
key={d.name}
|
||||
onClick={() => setActiveDrink(dIdx)}
|
||||
className={`px-6 py-3.5 rounded-xl border text-xs font-bold uppercase tracking-widest transition-all cursor-pointer ${
|
||||
activeDrink === dIdx
|
||||
? "bg-[#E63946] text-white border-[#E63946] shadow-[0_4px_12px_rgba(230,57,70,0.2)]"
|
||||
: "bg-white/[0.02] text-white/60 border-white/5 hover:border-white/10"
|
||||
}`}
|
||||
>
|
||||
{d.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Active Drink Info */}
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={activeDrink}
|
||||
initial={{ opacity: 0, y: 15 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -15 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="space-y-6"
|
||||
>
|
||||
<h3 className="font-industrial text-4xl font-black text-white uppercase tracking-wider">
|
||||
{drinks[activeDrink].name}
|
||||
</h3>
|
||||
<p className="text-white/60 text-xs lg:text-sm leading-relaxed max-w-xl font-medium">
|
||||
{drinks[activeDrink].desc}
|
||||
</p>
|
||||
|
||||
{/* Circular Dials Indicators */}
|
||||
<div className="grid grid-cols-3 gap-4 pt-6 max-w-md">
|
||||
|
||||
{/* Dial 1: Capacity */}
|
||||
<div className="bg-white/[0.02] border border-white/5 p-4 rounded-xl flex flex-col items-center text-center">
|
||||
<span className="text-[#FCFAF7] font-industrial text-xl font-bold">{drinks[activeDrink].capacity}</span>
|
||||
<span className="text-white/30 text-[9px] uppercase tracking-widest font-bold mt-1">{t.capacity}</span>
|
||||
</div>
|
||||
|
||||
{/* Dial 2: Alcohol */}
|
||||
<div className="bg-white/[0.02] border border-white/5 p-4 rounded-xl flex flex-col items-center text-center">
|
||||
<span className="text-[#E63946] font-industrial text-xl font-bold">{drinks[activeDrink].alcohol}</span>
|
||||
<span className="text-white/30 text-[9px] uppercase tracking-widest font-bold mt-1">{t.alcohol}</span>
|
||||
</div>
|
||||
|
||||
{/* Dial 3: Relax */}
|
||||
<div className="bg-white/[0.02] border border-white/5 p-4 rounded-xl flex flex-col items-center text-center">
|
||||
<span className="text-[#E5A900] font-industrial text-xl font-bold">{drinks[activeDrink].relax}</span>
|
||||
<span className="text-white/30 text-[9px] uppercase tracking-widest font-bold mt-1">{t.relax}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Large closeup beverage display */}
|
||||
<div className="lg:col-span-5 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-xs h-[420px] rounded-3xl overflow-hidden shadow-2xl border border-white/5 group"
|
||||
initial={{ opacity: 0, x: 40 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7 }}
|
||||
>
|
||||
{/* Using 8k lemon/citrus flatlay to represent fresh botanical drink prep */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/sicilia_lemon_heritage.png"
|
||||
alt="Fresh citrus botanic preparation"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms]"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-40" />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FEATURED EXPERIENCES ── */}
|
||||
<section id="experiences" className="py-28 relative z-10 px-6 bg-[#111215]">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#E63946] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.barrelhouseEvents}</span>
|
||||
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white">
|
||||
{t.featuredServices}
|
||||
</h2>
|
||||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||||
{lang === "tr" ? "Özel viski tadım uçuşları ve sommelier eğitim paketleri ayırtın." : "Reserve custom whiskey flights and private sommelier masterclass packages."}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Bento Grid layout */}
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{hizmetler.map((experience, idx) => {
|
||||
const locServ = getLocalizedService(experience.baslik, experience.aciklama);
|
||||
return (
|
||||
<motion.div
|
||||
key={idx}
|
||||
className="bg-[#18191E] rounded-3xl border border-white/5 overflow-hidden transition-all duration-300 hover:border-[#E63946]/30 flex flex-col justify-between group shadow-sm"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: idx * 0.1 }}
|
||||
whileHover={{ y: -4 }}
|
||||
>
|
||||
{/* Header cover using chef smoke image to represent luxury experience */}
|
||||
<div className="h-48 overflow-hidden relative border-b border-white/5">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={idx === 1 ? "/sicilia_lemon_heritage.png" : "/chef_plating_smoke.png"}
|
||||
alt={locServ.title}
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-1000"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/40" />
|
||||
</div>
|
||||
|
||||
<div className="p-8 space-y-4">
|
||||
<h3 className="font-industrial font-black text-xl text-white tracking-wider uppercase leading-snug">
|
||||
{locServ.title}
|
||||
</h3>
|
||||
<p className="text-white/50 text-[11px] leading-relaxed font-medium">
|
||||
{locServ.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="px-8 pb-8">
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[#E63946] group-hover:text-white transition-colors text-[10px] font-bold tracking-[2px] uppercase flex items-center gap-1.5 cursor-pointer"
|
||||
>
|
||||
{t.learnMore}
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── RESERVATION RESERVATION RESERVATION ── */}
|
||||
<section id="booking-flow" className="py-24 relative z-10 px-6 border-t border-white/5 bg-[#18191E]/40">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
|
||||
<div className="bg-[#18191E] rounded-3xl p-8 md:p-12 shadow-2xl border border-white/5 relative">
|
||||
<div className="absolute top-0 left-12 right-12 h-0.5 bg-gradient-to-r from-transparent via-[#E63946] to-transparent glowing-bar" />
|
||||
|
||||
<div className="text-center mb-10">
|
||||
<span className="text-[#E63946] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.masterclassBooking}</span>
|
||||
<h2 className="font-industrial text-3xl md:text-4xl font-black uppercase text-white">
|
||||
{t.scheduleEvent}
|
||||
</h2>
|
||||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||||
{t.formDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-5">
|
||||
{[
|
||||
{ label: t.fieldsName, placeholder: lang === "tr" ? "Adınız Soyadınız" : "Your Name", type: "text", full: false },
|
||||
{ label: t.fieldsEmail, placeholder: "you@company.com", type: "email", full: false },
|
||||
{ label: t.fieldsPhone, placeholder: lang === "tr" ? "İrtibat Numarası" : "Contact Number", type: "tel", full: false },
|
||||
{ label: t.fieldsEvent, placeholder: lang === "tr" ? "Viski Tadım Serisi" : "Whiskey Tasting Flight", type: "text", full: false },
|
||||
{ label: t.fieldsNotes, placeholder: t.fieldsNotesPlaceholder, type: "text", full: true },
|
||||
].map((field, idx) => (
|
||||
<div key={idx} className={field.full ? "col-span-2" : "col-span-1"}>
|
||||
<label className="block text-[10px] font-bold text-white/50 mb-1.5 uppercase tracking-widest">{field.label}</label>
|
||||
<input
|
||||
type={field.type}
|
||||
placeholder={field.placeholder}
|
||||
className="w-full px-4 py-3 rounded-xl border border-white/5 bg-[#111215] text-xs text-white placeholder-white/20 focus:outline-none focus:border-[#E63946] focus:ring-1 focus:ring-[#E63946] transition-all font-medium cursor-pointer"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="mt-8 w-full py-4.5 rounded-xl bg-[#E63946] hover:bg-white hover:text-black text-white font-bold text-[10px] tracking-[2.5px] uppercase transition-colors cursor-pointer"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.dispatchRequest}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── TESTIMONIALS ── */}
|
||||
<section id="testimonials" className="py-28 relative z-10 px-6 bg-[#111215] border-t border-white/5">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#E63946] font-bold text-xs uppercase tracking-widest block mb-2 font-industrial">{t.sommelierReviews}</span>
|
||||
<h2 className="font-industrial text-3xl lg:text-4xl font-black uppercase text-white font-industrial tracking-widest">
|
||||
{t.happyGuests}
|
||||
</h2>
|
||||
<p className="text-white/40 text-xs mt-2 font-medium">
|
||||
{t.happyGuestsDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Testimonials 2-Column Grid */}
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{yorumlar.map((y, yIdx) => (
|
||||
<motion.div
|
||||
key={yIdx}
|
||||
className="bg-[#18191E] border border-white/5 rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 hover:border-[#E63946]/30 group shadow-lg"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: yIdx * 0.1 }}
|
||||
whileHover={{ y: -4 }}
|
||||
>
|
||||
{/* Rating Stars SVG */}
|
||||
<div className="flex gap-1.5 mb-6">
|
||||
{[...Array(5)].map((_, starIdx) => (
|
||||
<svg key={starIdx} className="w-4.5 h-4.5 fill-[#E63946]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="text-white/70 text-xs leading-relaxed italic mb-8 font-medium font-serif-editorial">
|
||||
“{y.yorum}”
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full border border-white/10 flex items-center justify-center text-lg bg-[#111215] font-sans-clean select-none font-bold">
|
||||
{y.yazar.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-industrial text-white text-xs font-black uppercase tracking-wider">
|
||||
{y.yazar}
|
||||
</h4>
|
||||
<span className="text-[9px] text-white/40 uppercase tracking-widest font-bold font-sans-clean">
|
||||
{y.tarih}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-[#18191E] border-t border-white/5 pt-24 pb-8 px-6 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
|
||||
|
||||
{/* About Column */}
|
||||
<div className="md:col-span-2">
|
||||
<span className="font-industrial text-2xl font-black text-white tracking-wider uppercase mb-4 block">
|
||||
Char<span className="text-[#E63946]">Barrel</span>
|
||||
</span>
|
||||
<p className="text-white/50 text-xs leading-relaxed max-w-sm mb-8 font-medium">
|
||||
{firma.slogan} — Heavy rustic slate-crimson themed barrelhouse coordinates offering masterclass mixology and corporate single malt tastings.
|
||||
</p>
|
||||
<div className="text-white/60 text-xs font-medium space-y-3">
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#E63946] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
<span className="text-white/80">{firma.adres}</span>
|
||||
</p>
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#E63946] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect width="20" height="16" x="2" y="4" rx="2" />
|
||||
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" />
|
||||
</svg>
|
||||
<span className="text-white/80">{firma.email}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Dials Column */}
|
||||
<div>
|
||||
<h4 className="font-industrial text-[#E63946] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{t.artisanalDials}
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{drinks.map(d => (
|
||||
<a
|
||||
key={d.name}
|
||||
href="#drink-selector"
|
||||
className="block text-white/50 hover:text-[#E63946] text-xs transition-colors font-medium uppercase tracking-wider font-industrial"
|
||||
>
|
||||
{d.name} Signature
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Experiences Column */}
|
||||
<div>
|
||||
<h4 className="font-industrial text-[#E63946] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{t.vipServices}
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{hizmetler.map((h, hIdx) => {
|
||||
const locS = getLocalizedService(h.baslik, h.aciklama);
|
||||
return (
|
||||
<a
|
||||
key={hIdx}
|
||||
href="#experiences"
|
||||
className="block text-white/50 hover:text-[#E63946] text-xs transition-colors font-medium"
|
||||
>
|
||||
{locS.title}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs font-medium">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-white transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── FAST BOOKING SUCCESS MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showBookingModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/80 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-[#18191E] rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-[#E63946]/20"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-[#111215] border border-white/5 flex items-center justify-center text-white/40 hover:text-[#E63946] hover:border-[#E63946]/20 transition-all cursor-pointer font-bold"
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
{/* Success check indicator */}
|
||||
<div className="w-16 h-16 rounded-2xl bg-[#E63946]/10 border border-[#E63946]/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-8 h-8 stroke-[#E63946] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 className="font-industrial font-black text-white text-2xl mb-1 uppercase tracking-wider">
|
||||
{t.enquiryActive}
|
||||
</h3>
|
||||
<p className="text-[#E63946] font-mono text-[10px] mb-6 uppercase tracking-widest font-bold">
|
||||
{t.ambassadorActive}
|
||||
</p>
|
||||
|
||||
<p className="text-white/60 text-xs leading-relaxed mb-8 font-medium">
|
||||
{t.enquirySuccess}
|
||||
</p>
|
||||
|
||||
<motion.button
|
||||
className="w-full py-4.5 rounded-xl bg-[#E63946] hover:bg-black hover:text-white text-white font-bold text-[10px] tracking-[2.5px] uppercase cursor-pointer shadow-md shadow-[#E63946]/15"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
{t.dismiss}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,890 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 35 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.75, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.1 } },
|
||||
};
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navMembership: "Üyelik Programı",
|
||||
navServices: "Hizmetlerimiz",
|
||||
navWorks: "Portföyümüz",
|
||||
navReviews: "Hasta Hikayeleri",
|
||||
navBooking: "Randevu Al",
|
||||
badge: "SEAMLESS DENTAL CLINIC",
|
||||
heroTitlePart1: "Kusursuz",
|
||||
heroTitlePart2: "Ağız ve Diş Sağlığı",
|
||||
heroTitlePart3: "Deneyimi",
|
||||
heroDesc: "Sağlıklı ve özgüvenli bir gülümseme için pürüzsüz ve stressiz bir diş hekimliği deneyimi. Odentries modern klinik koordinatları ile dijital sağlık lüksünü yaşayın.",
|
||||
bookNow: "Randevu Al",
|
||||
contactUs: "İletişim",
|
||||
statTitle1: "Özel Üye Tasarrufu",
|
||||
statDesc1: "Ağız Muayeneleri, Temizlik ve Röntgen dahil olmak üzere Diş Prosedürlerinde %60 - %80 arasında tasarruf sağlayın.",
|
||||
statTitle2: "Gelişmiş Üye Avantajları",
|
||||
statDesc2: "Kozmetik, Restoratif ve Uzmanlık Diş Tedavileri dahil olmak üzere Diğer Tüm Diş Hizmetlerinde %40 Tasarruf Sağlayın.",
|
||||
membershipHeader: "Aileniz İçin Erişilebilir Diş Hekimliği",
|
||||
membershipDesc: "Sevdikleriniz için en iyi diş sağlığı planlarını keşfedin. Muayene, temizlik ve özel estetik tedavilerde benzersiz fiyat avantajlarından yararlanın.",
|
||||
joinedText: "Bu ay 1.200'den fazla üye katıldı",
|
||||
joinBtn: "Üye Olun",
|
||||
servicesHeader: "Ayrıcalıklı Klinik Hizmetleri",
|
||||
worksHeader: "Sağlıklı Gülüşler Burada Başlar",
|
||||
worksDesc: "Daha parlak, daha sağlıklı bir gülümseme ve kalıcı özgüven için uzman diş bakımı ve profesyonel temizlik uygulamaları.",
|
||||
reviewsHeader: "Hasta Görüşleri",
|
||||
bookingHeader: "Online Randevu Oluşturun",
|
||||
bookingDesc: "Hayalinizdeki sağlıklı gülüşe kavuşmak için formu doldurun, sizi arayalım.",
|
||||
fieldsName: "Ad Soyad",
|
||||
fieldsPhone: "Telefon Numarası",
|
||||
fieldsEmail: "E-Posta Adresi",
|
||||
fieldsService: "Hizmet Türü",
|
||||
fieldsDate: "Tercih Edilen Tarih",
|
||||
fieldsNotes: "Şikayetiniz / Notunuz",
|
||||
fieldsNotesPlaceholder: "Belirtmek istediğiniz özel detaylar...",
|
||||
dispatchForm: "RANDEVU TALEP ET",
|
||||
footerDesc: "Ferah ve hijyenik modern klinik ortamında, ağrısız ve en son teknoloji tedavi yöntemleri ile size özel ağız sağlığı çözümleri.",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Kullanım Şartları",
|
||||
dismiss: "KAPAT",
|
||||
contactTitle: "Hızlı İletişim",
|
||||
contactDesc: "İletişim bilgilerinizi bırakın, en kısa sürede sizi arayalım.",
|
||||
submit: "Gönder",
|
||||
viewAllWorks: "PORTFÖYÜ KEŞFET • PORTFÖYÜ KEŞFET • ",
|
||||
preventTitle: "Diş Çürüklerini Önleme",
|
||||
preventDesc: "Kapsamlı diş muayeneleri ve koruyucu hekimlik uygulamaları ile dişlerinizi koruyoruz.",
|
||||
sparkleTitle: "Işıldayan Temizlik",
|
||||
sparkleDesc: "Profesyonel temizleme ve beyazlatma teknikleriyle parıldayan sağlıklı gülüşler yaratıyoruz.",
|
||||
detectionTitle: "Erken Teşhis İmkanı",
|
||||
detectionDesc: "İleri teknoloji röntgen ve teşhis araçlarıyla sorunları büyümeden yakalıyoruz.",
|
||||
},
|
||||
en: {
|
||||
navMembership: "Membership Plan",
|
||||
navServices: "Our Services",
|
||||
navWorks: "Our Works",
|
||||
navReviews: "Patient Stories",
|
||||
navBooking: "Book Now",
|
||||
badge: "SEAMLESS DENTAL CLINIC",
|
||||
heroTitlePart1: "Seamless",
|
||||
heroTitlePart2: "Dental Care",
|
||||
heroTitlePart3: "Experience",
|
||||
heroDesc: "A smooth and hassle-free dental care experience for a healthy and confident smile. Indulge in digital health luxury structured by Odentries clinic.",
|
||||
bookNow: "Book Now",
|
||||
contactUs: "Contact",
|
||||
statTitle1: "Exclusive Member Savings",
|
||||
statDesc1: "Save 60% - 80% on Dental Procedures, including Oral Exams, Cleanings, and X-Rays.",
|
||||
statTitle2: "Enhanced Member Benefits",
|
||||
statDesc2: "Save 40% on All Other Dental Services, including Cosmetic, Restorative, and Specialty Dental Procedures.",
|
||||
membershipHeader: "Affordable Dental Care for Your Family",
|
||||
membershipDesc: "Unlock optimal dental wellness for your loved ones. Get massive savings on check-ups, cleaning, and specialized cosmetic treatments.",
|
||||
joinedText: "Joined by 1,200+ members this month",
|
||||
joinBtn: "Join Membership",
|
||||
servicesHeader: "Exclusive Clinic Services",
|
||||
worksHeader: "A Healthy Smile Starts Here",
|
||||
worksDesc: "Expert Dental Care and Cleaning Procedures for a Brighter, Healthier Smile and Lasting Confidence.",
|
||||
reviewsHeader: "Patient Testimonials",
|
||||
bookingHeader: "Online Appointment",
|
||||
bookingDesc: "Fill out the appointment details to secure your priority consultation slot with our experts.",
|
||||
fieldsName: "Full Name",
|
||||
fieldsPhone: "Phone Number",
|
||||
fieldsEmail: "Email Address",
|
||||
fieldsService: "Service Category",
|
||||
fieldsDate: "Preferred Date",
|
||||
fieldsNotes: "Notes / Symptoms",
|
||||
fieldsNotesPlaceholder: "Any specific dental notes or requests...",
|
||||
dispatchForm: "REQUEST APPOINTMENT",
|
||||
footerDesc: "Custom dental care solutions designed in an ultra-clean, welcoming clinic layout using advanced high-tech treatment instruments.",
|
||||
privacyRegs: "Privacy Policy",
|
||||
termsStay: "Terms of Service",
|
||||
dismiss: "DISMISS",
|
||||
contactTitle: "Quick Consultation",
|
||||
contactDesc: "Leave your contact details and our medical coordinator will call you back within 15 minutes.",
|
||||
submit: "Submit",
|
||||
viewAllWorks: "VIEW ALL WORKS • VIEW ALL WORKS • ",
|
||||
preventTitle: "Prevent Cavities & Disease",
|
||||
preventDesc: "State-of-the-art checkups and preventative dentistry to protect your raw teeth structure.",
|
||||
sparkleTitle: "Keep Your Teeth Sparkling Clean",
|
||||
sparkleDesc: "Professional scale cleaning and premium laser whitening for an immediate aesthetic update.",
|
||||
detectionTitle: "Early Detection of Dental Issues",
|
||||
detectionDesc: "Advanced high-resolution diagnostic tools to intercept hidden micro-cavities before they expand.",
|
||||
}
|
||||
};
|
||||
|
||||
export default function DentalTemplate({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], projeler = [], yorumlar = [] } = data;
|
||||
const [showBookingModal, setShowBookingModal] = useState(false);
|
||||
const [activeYorum, setActiveYorum] = useState(0);
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (x: number) => Math.min(1, 1.001 - Math.pow(2, -10 * x)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Map service icons without generic emojis
|
||||
const getServiceIconSvg = (ikon: string) => {
|
||||
switch (ikon) {
|
||||
case "🦷":
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#1E2E38] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9s2.015-9 4.5-9" />
|
||||
</svg>
|
||||
);
|
||||
case "✨":
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#1E2E38] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9.813 15.904L9 21l-1.813-5.096L2.1 14.1 7.187 13.2 9 8.1l1.813 5.1 5.087.9-5.087.904zM19.071 4.929l-.707 1.414-.707-1.414-.707-.707 1.414-.707.707 1.414.707-1.414.707.707-1.414.707zm-12.02 0l-.707 1.414-.707-1.414-.707-.707 1.414-.707.707 1.414.707-1.414.707.707-1.414.707z" />
|
||||
</svg>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#1E2E38] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const getLocalizedServiceText = (baslik: string) => {
|
||||
if (baslik.includes("Prevent")) return { title: t.preventTitle, desc: t.preventDesc };
|
||||
if (baslik.includes("Sparkling")) return { title: t.sparkleTitle, desc: t.sparkleDesc };
|
||||
return { title: t.detectionTitle, desc: t.detectionDesc };
|
||||
};
|
||||
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700;800;900&family=Sora:wght@300;400;500;600;700;800&display=swap');
|
||||
|
||||
:root {
|
||||
--bg-ivory: #FAF7F2;
|
||||
--bg-mint: #EBF5F0;
|
||||
--text-slate: #1E2E38;
|
||||
--text-dark: #121C22;
|
||||
--color-gold: #D4AF37;
|
||||
}
|
||||
|
||||
.font-elegant {
|
||||
font-family: 'Sora', sans-serif;
|
||||
}
|
||||
|
||||
.font-sans-clean {
|
||||
font-family: 'DM Sans', sans-serif;
|
||||
}
|
||||
|
||||
.spinning-text {
|
||||
animation: spin 24s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(38px, 6vw, 85px);
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 0.95;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#1E2E38] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-elegant tracking-[4px] uppercase text-[#EBF5F0] block"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
ODENTRIES CLINIC
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#EBF5F0]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-elegant text-white/50 text-xs tracking-wider uppercase"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
interactive prototype
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<div className="bg-[#FAF7F2] text-[#1E2E38] min-h-screen font-sans-clean selection:bg-[#1E2E38] selection:text-white overflow-hidden relative pb-20">
|
||||
|
||||
{/* Floating cross graphics (+) from reference design */}
|
||||
<div className="absolute inset-0 pointer-events-none z-10">
|
||||
<div className="absolute top-[25%] left-[8%] text-[#1E2E38]/20 text-3xl font-light select-none">+</div>
|
||||
<div className="absolute top-[35%] left-[30%] text-[#1E2E38]/30 text-lg font-light select-none">+</div>
|
||||
<div className="absolute bottom-[20%] left-[28%] text-[#1E2E38]/20 text-3xl font-light select-none">+</div>
|
||||
<div className="absolute top-[20%] right-[32%] text-[#1E2E38]/20 text-2xl font-light select-none">+</div>
|
||||
<div className="absolute bottom-[35%] right-[5%] text-[#1E2E38]/30 text-3xl font-light select-none">+</div>
|
||||
</div>
|
||||
|
||||
{/* ── FLOATING CONCEPT BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#1E2E38]/90 backdrop-blur-md border border-white/10 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#EBF5F0] animate-pulse" />
|
||||
<span className="text-[9px] font-elegant uppercase tracking-[1.5px] text-white/90">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* ── PREMIUM HEADER ── */}
|
||||
<motion.header
|
||||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||||
initial={{ y: -80, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.85, ease: [0.16, 1, 0.3, 1] }}
|
||||
>
|
||||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-white/70 backdrop-blur-xl border border-white/40 rounded-2xl shadow-[0_10px_30px_rgba(30,46,56,0.03)]">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2.5 group">
|
||||
<span className="text-lg font-black tracking-tight text-[#1E2E38] font-elegant flex items-center gap-2 uppercase">
|
||||
<svg className="w-5 h-5 text-[#1E2E38]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" />
|
||||
<path d="M12 6v12M6 12h12" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Links */}
|
||||
<nav className="hidden lg:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navMembership, href: "#uyelik" },
|
||||
{ label: t.navServices, href: "#hizmetler" },
|
||||
{ label: t.navWorks, href: "#works" },
|
||||
{ label: t.navReviews, href: "#yorumlar" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[10px] font-black tracking-[2px] uppercase text-[#1E2E38]/70 hover:text-[#1E2E38] transition-colors relative py-1 cursor-pointer group"
|
||||
>
|
||||
{item.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#1E2E38] transition-all group-hover:w-full" />
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Language Selector + Action Button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-[#1E2E38]/5 border border-[#1E2E38]/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-elegant px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-white text-slate-900 shadow-sm" : "text-[#1E2E38]/60 hover:text-[#1E2E38]"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-elegant px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-white text-slate-900 shadow-sm" : "text-[#1E2E38]/60 hover:text-[#1E2E38]"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[10px] font-black tracking-[2.5px] uppercase text-[#FAF7F2] bg-[#1E2E38] hover:bg-[#121C22] px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_4px_12px_rgba(30,46,56,0.15)] hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.bookNow}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── HERO SECTION ── */}
|
||||
<section className="relative min-h-screen flex items-center overflow-hidden pt-32 pb-20 px-6">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||||
|
||||
{/* Left Col - Text Content */}
|
||||
<motion.div
|
||||
className="lg:col-span-6 z-20"
|
||||
variants={stagger}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="inline-flex items-center gap-2 text-[10px] font-black uppercase tracking-widest text-[#1E2E38]/60 mb-6 bg-[#1E2E38]/5 border border-[#1E2E38]/10 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#1E2E38] animate-pulse" />
|
||||
{t.badge}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={fadeUp}
|
||||
className="font-elegant font-black text-[#1E2E38] mb-8 hero-title-clamp uppercase"
|
||||
>
|
||||
{t.heroTitlePart1}
|
||||
<br />
|
||||
<span className="italic font-light opacity-90 text-slate-600 lowercase">{t.heroTitlePart2}</span>
|
||||
<br />
|
||||
{t.heroTitlePart3}
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-[#1E2E38]/70 text-xs lg:text-sm leading-relaxed max-w-md mb-10 font-semibold"
|
||||
>
|
||||
{t.heroDesc}
|
||||
</motion.p>
|
||||
|
||||
<motion.div variants={fadeUp}>
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="inline-flex items-center gap-3 px-8 py-4.5 rounded-xl bg-[#1E2E38] hover:bg-[#121C22] text-[#FAF7F2] font-black text-[10px] tracking-[2px] uppercase transition-all shadow-[0_5px_15px_rgba(30,46,56,0.1)] cursor-pointer"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.bookNow} <span className="text-[10px]">→</span>
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Col - Cropped Smiling Portrait Overlay */}
|
||||
<div className="lg:col-span-6 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-md lg:max-w-lg h-[460px] lg:h-[530px] rounded-3xl overflow-hidden shadow-2xl border border-white/60"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
>
|
||||
{/* Background soft lighting */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-[#FAF7F2] via-transparent to-transparent z-10 pointer-events-none" />
|
||||
|
||||
{/* Main Generated High-Fidelity Smiling Image */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/dental_hero.png"
|
||||
alt="Odentries Smiling Model"
|
||||
className="w-full h-full object-cover object-center scale-102 hover:scale-105 transition-transform duration-[4000ms]"
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── SECTION 001: AFFORDABLE CARE & BENTO CARDS ── */}
|
||||
<section id="uyelik" className="py-32 bg-[#FAF7F2] px-6 border-t border-[#1E2E38]/5">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-start">
|
||||
|
||||
{/* Left Content */}
|
||||
<motion.div
|
||||
className="lg:col-span-5"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest text-[#1E2E38]/50 mb-4"
|
||||
>
|
||||
001 - Join Membership
|
||||
</motion.span>
|
||||
<motion.h2
|
||||
variants={fadeUp}
|
||||
className="text-4xl lg:text-5xl font-elegant font-black text-[#1E2E38] leading-tight mb-6 uppercase"
|
||||
>
|
||||
{t.membershipHeader}
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-[#1E2E38]/70 text-xs lg:text-sm leading-relaxed mb-10 font-semibold"
|
||||
>
|
||||
{t.membershipDesc}
|
||||
</motion.p>
|
||||
|
||||
{/* Patient Pile from Reference Design */}
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="flex items-center gap-6 mb-8 font-semibold"
|
||||
>
|
||||
<div className="flex -space-x-3 select-none">
|
||||
{["👨⚕️", "👩⚕️", "🧑⚕️", "✨"].map((emoji, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="w-9 h-9 rounded-full bg-white border-2 border-[#FAF7F2] flex items-center justify-center text-sm shadow-sm"
|
||||
>
|
||||
{emoji}
|
||||
</div>
|
||||
))}
|
||||
<div className="w-9 h-9 rounded-full bg-[#1E2E38] border-2 border-[#FAF7F2] flex items-center justify-center text-[10px] text-[#FAF7F2] font-black">
|
||||
+
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-[#1E2E38]/80">
|
||||
{t.joinedText}
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="px-8 py-4 rounded-xl bg-[#1E2E38] hover:bg-[#121C22] text-[#FAF7F2] font-black text-[10px] tracking-[2.5px] uppercase transition-colors"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.joinBtn} <span className="text-[9px]">→</span>
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Bento Cards */}
|
||||
<div className="lg:col-span-7 grid md:grid-cols-2 gap-6 w-full">
|
||||
|
||||
{/* Card 1: 80% Savings */}
|
||||
<motion.div
|
||||
className="bg-[#EBF5F0] rounded-3xl p-8 border border-white flex flex-col justify-between h-[320px] relative overflow-hidden group shadow-sm"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
whileHover={{ y: -6 }}
|
||||
>
|
||||
<div className="flex justify-between items-start">
|
||||
<span className="text-5xl font-black text-[#1E2E38] font-elegant group-hover:scale-102 transition-transform">
|
||||
{istatistikler[0]?.deger || "80%"}
|
||||
</span>
|
||||
<span className="text-2xl font-light text-[#1E2E38]/30 shrink-0 select-none">+</span>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-xs font-black text-[#1E2E38] mb-2 uppercase tracking-wide">{t.statTitle1}</h4>
|
||||
<p className="text-[#1E2E38]/60 text-[11px] leading-relaxed font-semibold">
|
||||
{t.statDesc1}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Card 2: 40% Benefits */}
|
||||
<motion.div
|
||||
className="bg-[#1E2E38] rounded-3xl p-8 flex flex-col justify-between h-[320px] relative overflow-hidden group shadow-xl"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.15 }}
|
||||
whileHover={{ y: -6 }}
|
||||
>
|
||||
<div className="flex justify-between items-start">
|
||||
<span className="text-5xl font-black text-[#FAF7F2] font-elegant group-hover:scale-102 transition-transform">
|
||||
{istatistikler[1]?.deger || "40%"}
|
||||
</span>
|
||||
<span className="text-2xl font-light text-[#FAF7F2]/30 shrink-0 select-none">+</span>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-xs font-black text-[#FAF7F2] mb-2 uppercase tracking-wide">{t.statTitle2}</h4>
|
||||
<p className="text-[#FAF7F2]/60 text-[11px] leading-relaxed font-semibold">
|
||||
{t.statDesc2}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CORE SERVICES CARD ROW ── */}
|
||||
<section id="hizmetler" className="py-24 bg-white px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#1E2E38]/50 font-black text-[10px] uppercase tracking-widest block mb-2 font-elegant">{t.navServices}</span>
|
||||
<h2 className="font-elegant text-3xl lg:text-4xl font-black uppercase text-[#1E2E38] tracking-tight">
|
||||
{t.servicesHeader}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
{hizmetler.map((h, i) => {
|
||||
const item = getLocalizedServiceText(h.baslik);
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="bg-[#FAF7F2]/50 hover:bg-[#FAF7F2] rounded-3xl p-8 border border-gray-100 hover:border-[#1E2E38]/10 transition-all duration-300 flex flex-col justify-between h-80 group cursor-default"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: i * 0.1 }}
|
||||
whileHover={{ y: -4 }}
|
||||
>
|
||||
<div>
|
||||
<div className="w-12 h-12 rounded-2xl bg-white border border-[#1E2E38]/5 flex items-center justify-center mb-6 transition-transform group-hover:scale-105 shadow-sm">
|
||||
{getServiceIconSvg(h.ikon)}
|
||||
</div>
|
||||
<h3 className="font-elegant font-bold text-[#1E2E38] text-base mb-3 leading-snug">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-gray-400 text-xs leading-relaxed font-semibold">
|
||||
{item.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[#1E2E38] font-black text-[9px] tracking-[2.5px] uppercase flex items-center gap-1 cursor-pointer hover:text-opacity-80 transition-colors pt-4 border-t border-gray-100"
|
||||
>
|
||||
{lang === "tr" ? "DAHA FAZLA BİLGİ →" : "LEARN MORE →"}
|
||||
</button>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── SECTION 002: OUR WORKS / PORTFOLIO ── */}
|
||||
<section id="works" className="py-32 bg-[#EBF5F0] px-6 border-t border-[#1E2E38]/5">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
{/* Header */}
|
||||
<div className="flex flex-col md:flex-row md:items-end justify-between mb-16 gap-6">
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest text-[#1E2E38]/50 mb-4"
|
||||
>
|
||||
002 - Our Works
|
||||
</motion.span>
|
||||
<motion.h2
|
||||
variants={fadeUp}
|
||||
className="text-4xl lg:text-5xl font-elegant font-black text-[#1E2E38] leading-tight uppercase"
|
||||
>
|
||||
{t.worksHeader}
|
||||
</motion.h2>
|
||||
</motion.div>
|
||||
|
||||
{/* Spinning Circle badge and text details */}
|
||||
<motion.div
|
||||
className="flex items-center gap-6 max-w-sm font-semibold"
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7 }}
|
||||
>
|
||||
{/* Spinning Badge */}
|
||||
<div className="relative w-20 h-20 shrink-0 flex items-center justify-center select-none">
|
||||
<svg className="absolute w-full h-full spinning-text" viewBox="0 0 100 100">
|
||||
<path id="circlePath" d="M 50, 50 m -37, 0 a 37,37 0 1,1 74,0 a 37,37 0 1,1 -74,0" fill="none" />
|
||||
<text className="font-elegant font-black text-[8px] fill-[#1E2E38] tracking-[1px]">
|
||||
<textPath xlinkHref="#circlePath">
|
||||
{t.viewAllWorks}
|
||||
</textPath>
|
||||
</text>
|
||||
</svg>
|
||||
<span className="text-base text-[#1E2E38] font-bold">↗</span>
|
||||
</div>
|
||||
<p className="text-[#1E2E38]/70 text-xs leading-relaxed">
|
||||
{t.worksDesc}
|
||||
</p>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* 3 Column Image Cards Grid */}
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{projeler.map((p, i) => (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="flex flex-col group justify-between"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: i * 0.15 }}
|
||||
whileHover={{ y: -6 }}
|
||||
>
|
||||
<div>
|
||||
{/* Photo container */}
|
||||
<div className="h-[360px] rounded-3xl overflow-hidden mb-5 shadow-lg border border-white/20 relative">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={p.resim}
|
||||
alt={p.baslik}
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-1000"
|
||||
/>
|
||||
</div>
|
||||
{/* Text details */}
|
||||
<h3 className="font-elegant font-bold text-[#1E2E38] text-base mb-1 uppercase tracking-wide leading-tight">{p.baslik}</h3>
|
||||
<p className="text-gray-500 text-xs font-semibold">{lang === "tr" ? "Estetik ve Dayanıklı Sonuçlar" : "Impressive, high-durability smile aesthetics"}</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[#1E2E38] font-black text-[9px] tracking-[2px] uppercase flex items-center gap-1 cursor-pointer hover:text-opacity-80 transition-colors pt-4 shrink-0"
|
||||
>
|
||||
{lang === "tr" ? "VAKAYI İNCELE →" : "VIEW CASE →"}
|
||||
</button>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── YORUMLAR (TESTIMONIALS) ── */}
|
||||
<section id="yorumlar" className="py-24 bg-white px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="mb-16 text-center">
|
||||
<span className="inline-block text-[10px] font-black uppercase tracking-widest text-[#1E2E38]/50 mb-4 font-elegant">
|
||||
003 - Patient Stories
|
||||
</span>
|
||||
<h2 className="text-3xl lg:text-4xl font-elegant font-black text-[#1E2E38] uppercase">
|
||||
{t.reviewsHeader}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={activeYorum}
|
||||
className="bg-[#FAF7F2] border border-[#1E2E38]/5 rounded-3xl p-10 max-w-2xl mx-auto shadow-sm"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.95 }}
|
||||
transition={{ duration: 0.4 }}>
|
||||
<div className="flex gap-1.5 mb-6 justify-center">
|
||||
{[...Array(yorumlar[activeYorum]?.puan || 5)].map((_, i) => (
|
||||
<svg key={i} className="w-4.5 h-4.5 fill-[#1E2E38]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-[#1E2E38]/80 text-base leading-relaxed italic text-center mb-8 font-semibold">
|
||||
“{yorumlar[activeYorum]?.yorum}”
|
||||
</p>
|
||||
<div className="flex items-center gap-3.5 justify-center">
|
||||
<div className="w-10 h-10 rounded-full flex items-center justify-center text-sm bg-white shadow-sm border border-[#1E2E38]/5 font-bold font-elegant select-none">
|
||||
{yorumlar[activeYorum]?.yazar.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[#1E2E38] font-bold text-xs uppercase tracking-wide leading-tight">{yorumlar[activeYorum]?.yazar}</p>
|
||||
<p className="text-gray-400 text-[10px] uppercase font-black font-elegant tracking-wider mt-0.5">{yorumlar[activeYorum]?.tarih}</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
|
||||
<div className="flex justify-center gap-2.5 mt-8">
|
||||
{yorumlar.map((_, i) => (
|
||||
<button key={i} onClick={() => setActiveYorum(i)}
|
||||
className="w-2.5 h-2.5 rounded-full transition-all cursor-pointer"
|
||||
style={{ background: i === activeYorum ? "#1E2E38" : "rgba(30,46,56,0.15)",
|
||||
transform: i === activeYorum ? "scale(1.3)" : "scale(1)" }} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── RANDEVU AL (APPOINTMENT SECTION) ── */}
|
||||
<section id="randevu" className="py-24 bg-[#FAF7F2] px-6 border-t border-[#1E2E38]/5">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<div className="bg-white rounded-3xl p-8 md:p-12 shadow-premium border border-white">
|
||||
<div className="text-center mb-10">
|
||||
<span className="inline-block text-[10px] font-black uppercase tracking-widest text-[#1E2E38]/50 mb-4 font-elegant">
|
||||
004 - Online Appointment
|
||||
</span>
|
||||
<h2 className="text-3xl md:text-4xl font-elegant font-black text-[#1E2E38] uppercase tracking-tight">
|
||||
{t.bookingHeader}
|
||||
</h2>
|
||||
<p className="text-gray-400 text-xs mt-2 font-semibold">
|
||||
{t.bookingDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4 font-semibold">
|
||||
{[
|
||||
{ label: t.fieldsName, placeholder: lang === "tr" ? "Adınız Soyadınız" : "Your Full Name", type: "text", full: false },
|
||||
{ label: t.fieldsPhone, placeholder: "05xx xxx xx xx", type: "tel", full: false },
|
||||
{ label: t.fieldsEmail, placeholder: "ornek@mail.com", type: "email", full: false },
|
||||
{ label: t.fieldsService, placeholder: "", type: "select", full: false },
|
||||
{ label: t.fieldsDate, placeholder: "", type: "date", full: false },
|
||||
{ label: t.fieldsNotes, placeholder: t.fieldsNotesPlaceholder, type: "text", full: true },
|
||||
].map((field, i) => (
|
||||
<div key={i} className={field.full ? "col-span-2" : "col-span-2 sm:col-span-1"}>
|
||||
<label className="block text-[10px] font-black text-[#1E2E38]/60 mb-1.5 uppercase tracking-wider">{field.label}</label>
|
||||
{field.type === "select" ? (
|
||||
<select className="w-full px-4 py-3.5 rounded-xl border border-gray-200 text-xs text-slate-800 focus:outline-none focus:ring-2 focus:ring-[#1E2E38] bg-gray-50/50 transition-all font-semibold cursor-pointer">
|
||||
<option>{lang === "tr" ? "Diş Çürüklerini Önleme" : "Prevent Cavities & Disease"}</option>
|
||||
<option>{lang === "tr" ? "Işıldayan Temizlik" : "Teeth Sparkling Cleaning"}</option>
|
||||
<option>{lang === "tr" ? "Diş Düzeltme" : "Teeth Straightening"}</option>
|
||||
<option>{lang === "tr" ? "Diş İmplantı" : "Dental Implant"}</option>
|
||||
</select>
|
||||
) : (
|
||||
<input type={field.type} placeholder={field.placeholder}
|
||||
className="w-full px-4 py-3.5 rounded-xl border border-gray-200 text-xs focus:outline-none focus:ring-2 focus:ring-[#1E2E38] bg-gray-50/50 transition-all placeholder-[#1E2E38]/20 font-semibold" />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="mt-8 w-full py-4.5 rounded-xl text-[#FAF7F2] font-black text-xs bg-[#1E2E38] hover:bg-[#121C22] uppercase tracking-widest cursor-pointer shadow-[0_5px_15px_rgba(30,46,56,0.15)]"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
📅 {t.dispatchForm}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-[#121C22] border-t border-white/10 px-6 pt-24 pb-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
|
||||
<div className="md:col-span-2">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<svg className="w-5 h-5 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" />
|
||||
<path d="M12 6v12M6 12h12" />
|
||||
</svg>
|
||||
<span className="font-bold text-white text-lg font-elegant uppercase tracking-wide">{firma.adi}</span>
|
||||
</div>
|
||||
<p className="text-white/40 text-xs leading-relaxed max-w-sm mb-8 font-semibold">{t.footerDesc}</p>
|
||||
<div className="text-white/50 text-xs font-semibold space-y-3">
|
||||
<p className="flex items-center gap-2">📍 <span className="text-white/80">{firma.adres}</span></p>
|
||||
<p className="flex items-center gap-2">📞 <span className="text-white/80">{firma.telefon}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-elegant text-white font-bold text-xs uppercase tracking-wider mb-6">{t.navServices}</h4>
|
||||
{hizmetler.map((h, i) => {
|
||||
const s = getLocalizedServiceText(h.baslik);
|
||||
return (
|
||||
<a key={i} href="#hizmetler" className="block text-white/40 text-xs mb-3 hover:text-white transition-colors font-semibold">{s.title}</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-elegant text-white font-bold text-xs uppercase tracking-wider mb-6">Odentries</h4>
|
||||
{[t.navMembership, t.navServices, t.navWorks, t.navReviews].map((item) => (
|
||||
<a key={item} href="#" className="block text-white/40 text-xs mb-3 hover:text-white transition-colors font-semibold">{item}</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs font-semibold">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-white transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── BOOKING MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showBookingModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/60 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-white rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-gray-100"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center font-bold text-gray-500 hover:bg-gray-200 transition-colors cursor-pointer"
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
<h3 className="font-elegant font-black text-[#1E2E38] text-2xl mb-1 uppercase tracking-wide">{t.contactTitle}</h3>
|
||||
<p className="text-gray-400 text-xs mb-6 font-semibold">{t.contactDesc}</p>
|
||||
|
||||
<div className="space-y-4 font-semibold">
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-gray-500 mb-1.5 uppercase tracking-wider">{t.fieldsName}</label>
|
||||
<input type="text" className="w-full px-4 py-3.5 rounded-xl border bg-gray-50/50 text-xs focus:outline-none focus:ring-2 focus:ring-[#1E2E38]" placeholder="John Doe" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-gray-500 mb-1.5 uppercase tracking-wider">{t.fieldsPhone}</label>
|
||||
<input type="tel" className="w-full px-4 py-3.5 rounded-xl border bg-gray-50/50 text-xs focus:outline-none focus:ring-2 focus:ring-[#1E2E38]" placeholder="05xx xxx xx xx" />
|
||||
</div>
|
||||
<motion.button
|
||||
className="w-full py-4 rounded-xl bg-[#1E2E38] text-[#FAF7F2] font-black text-xs hover:bg-[#121C22] transition-colors mt-2 cursor-pointer shadow-[0_4px_12px_rgba(30,46,56,0.15)] uppercase tracking-widest"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
{t.submit}
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,845 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 35 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.75, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.1 } },
|
||||
};
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navBook: "Rezervasyon",
|
||||
navSuites: "Özel Süitler",
|
||||
navExp: "Deneyimler",
|
||||
navRev: "Yorumlar",
|
||||
badge: "BUTİK LÜKS RESORT",
|
||||
heroTail: "sizi bekliyor",
|
||||
heroDesc: "Cal Vestam'da eşsiz bir huzura dalın. Fethiye'nin nefes kesici mavi sırtlarının üzerinde, size özel cam kenarlı sonsuzluk havuzları ve organik zeytin yaprağı masaj terapileri sunuyoruz.",
|
||||
reserveNow: "Rezervasyon Yap",
|
||||
planEscape: "TATİLİ PLANLA",
|
||||
resortServices: "RESORT HİZMETLERİ",
|
||||
checkAvailability: "UYGUNLUK DURUMU",
|
||||
scheduleEscape: "RESORT TATİLİNİZİ PLANLAYIN",
|
||||
scheduleDesc: "Benzersiz deniz manzaralı teras süitinizde yerinizi ayırtmak için tarihlerinizi belirleyin.",
|
||||
checkin: "GİRİŞ TARİHİ",
|
||||
checkout: "ÇIKIŞ TARİHİ",
|
||||
adults: "YETİŞKİN",
|
||||
kids: "ÇOCUK (12 YAŞ ALTI)",
|
||||
guests: "Misafir",
|
||||
kidsLabel: "Çocuk",
|
||||
guarantee: "Rezervasyonlar, giriş esnasında taze toplanmış narenciye kokteyli ikramı ile en iyi fiyat garantisini kilitler.",
|
||||
confirmDetails: "TARİHLERİ ONAYLA",
|
||||
suitesTitle: "TERAS SÜİTLERİ",
|
||||
suitesHeader: "SEÇKİN SÜİTLER",
|
||||
suitesDesc: "Özel dokuma keten serimler, doğal zeytinyağlı sabunlar ve kesintisiz deniz panoraması ile mimari lüksü deneyimleyin.",
|
||||
secureRes: "REZERVASYON YAP →",
|
||||
diaries: "Misafir Defteri",
|
||||
lovedGuests: "LOVED BY GUESTS",
|
||||
lovedDesc: "Seçkin gezginlerin ve küresel mimari yazarlarının Cal Vestam deneyimlerini keşfedin.",
|
||||
vipCoords: "VIP KOORDİNATLAR",
|
||||
conciergeActive: "Resort Concierge Aktif",
|
||||
checkInOutDetails: "Giriş: 15:00 · Çıkış: 11:00",
|
||||
boutiqueLeisures: "BUTİK AYRICALIKLAR",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Konaklama Şartları",
|
||||
dismiss: "KAPAT",
|
||||
enquiryActive: "BAŞVURU ALINDI",
|
||||
ambassadorActive: "Cal Vestam Concierge Aktif",
|
||||
enquirySuccess: "Akdeniz resort rezervasyon koordinatlarınızı kaydettik. Özel misafir elçimiz giriş işlemlerinizi öncelikli olarak tamamlamak için sizinle iletişime geçecektir. Teşekkürler!",
|
||||
|
||||
// Suite details
|
||||
suite1Title: "PANORAMİK VESTAM SÜİT",
|
||||
suite1Desc: "Fethiye'nin mavi sırtlarına bakan özel havuzlu balkon ve premium pamuklu yatak tasarımı.",
|
||||
suite2Title: "NARENCİYE BAHÇE SÜİTİ",
|
||||
suite2Desc: "Çevreleyen zeytin ve limon bahçeleriyle entegre, gün ışığıyla dolu ferah konaklama deneyimi.",
|
||||
suite3Title: "AKDENİZ VİLLASI",
|
||||
suite3Desc: "Özel sonsuzluk havuzları, kişisel uşak hizmeti ve gün batımı terasları sunan tam villa kiralama.",
|
||||
|
||||
// Welcome orchards
|
||||
welcomeTitle: "Karşılama İkramları",
|
||||
welcomeDesc: "MİSAFİRLERİMİZ İÇİN TAZE NARENCİYE KOKTEYLLERİ",
|
||||
},
|
||||
en: {
|
||||
navBook: "Book stay",
|
||||
navSuites: "Exclusive suites",
|
||||
navExp: "Experiences",
|
||||
navRev: "Guest reviews",
|
||||
badge: "BOUTIQUE LUXURY RESORT",
|
||||
heroTail: "awaits your arrival",
|
||||
heroDesc: "Submerge into sheer tranquility at Cal Vestam. Situated directly above Muğla's gorgeous blue ridges, we stage exclusive glass-edge infinity pools and wellness stone therapy.",
|
||||
reserveNow: "Reserve Now",
|
||||
planEscape: "PLAN ESCAPE",
|
||||
resortServices: "RESORT SERVICES",
|
||||
checkAvailability: "Check availability",
|
||||
scheduleEscape: "SCHEDULE YOUR RESORT ESCAPE",
|
||||
scheduleDesc: "Allocate your exclusive sea-view panoramic terrace suite directly inside our luxury booking engine.",
|
||||
checkin: "CHECK-IN DATE",
|
||||
checkout: "CHECK-OUT DATE",
|
||||
adults: "ADULTS",
|
||||
kids: "KIDS (UNDER 12)",
|
||||
guests: "Guests",
|
||||
kidsLabel: "Kids",
|
||||
guarantee: "Reservations lock in our premium best-rate guarantee with local welcome orchard citrus cocktail packages upon check-in.",
|
||||
confirmDetails: "CONFIRM DETAILS",
|
||||
suitesTitle: "Terrace suites",
|
||||
suitesHeader: "EXCLUSIVE SUITES",
|
||||
suitesDesc: "Experience high-end architecture layered with bespoke linen, local natural olive oil soaps, and floor-to-ceiling sea panoramas.",
|
||||
secureRes: "SECURE RESERVATION →",
|
||||
diaries: "Guest Diaries",
|
||||
lovedGuests: "LOVED BY GUESTS",
|
||||
lovedDesc: "Hear what prominent travelers and global architecture writers experience inside Cal Vestam.",
|
||||
vipCoords: "VIP COORDINATES",
|
||||
conciergeActive: "Concierge 24 Hours Active",
|
||||
checkInOutDetails: "Check In: 3:00 PM · Check Out: 11:00 AM",
|
||||
boutiqueLeisures: "BOUTIQUE LEISURES",
|
||||
privacyRegs: "Privacy Regulations",
|
||||
termsStay: "Terms of Stay",
|
||||
dismiss: "DISMISS",
|
||||
enquiryActive: "ENQUIRY ACTIVE",
|
||||
ambassadorActive: "Cal Vestam Concierge Active",
|
||||
enquirySuccess: "We have registered your Mediterranean resort reservation coordinates. A personal guest ambassador has locked your priority check-in slot. Thank you!",
|
||||
|
||||
// Suite details
|
||||
suite1Title: "PANORAMIC VESTAM SUITE",
|
||||
suite1Desc: "Private pool balcony looking directly over Fethiye blue ridges with premium cotton layout.",
|
||||
suite2Title: "CITRUS GARDEN SUITE",
|
||||
suite2Desc: "Cozy light-filled suite integrated with surrounding organic welcome olive and lemon orchards.",
|
||||
suite3Title: "MEDITERRANEAN VILLA",
|
||||
suite3Desc: "Executive buyout layout offering private infinity pools, automated concierge, and sunset lounges.",
|
||||
|
||||
// Welcome orchards
|
||||
welcomeTitle: "Welcome Orchards",
|
||||
welcomeDesc: "CITRUS COCKTAILS FOR GUESTS",
|
||||
}
|
||||
};
|
||||
|
||||
export default function HotelTemplate1({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], yorumlar = [] } = data;
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [adults, setAdults] = useState(2);
|
||||
const [kids, setKids] = useState(0);
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// 1. Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// 2. Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Localized statistics
|
||||
const getLocalizedStat = (etiket: string) => {
|
||||
if (etiket.includes("Suites")) return lang === "tr" ? "İmza Deniz Süiti" : "Signature Sea Suites";
|
||||
if (etiket.includes("Pools")) return lang === "tr" ? "Panoramik Havuz" : "Panoramic Infinity Pools";
|
||||
if (etiket.includes("Experience")) return lang === "tr" ? "Misafir Memnuniyeti" : "Guest Experience Index";
|
||||
return lang === "tr" ? "Doğal Zeytinyağı Sabun & Spa" : "Natural Olive Oil Soap & Spa";
|
||||
};
|
||||
|
||||
// Localized services
|
||||
const getLocalizedService = (baslik: string, aciklama: string) => {
|
||||
if (baslik.includes("POOL")) {
|
||||
return {
|
||||
title: lang === "tr" ? "SONSUZLUK VESTAM HAVUZU" : "INFINITY VESTAM POOL",
|
||||
desc: lang === "tr" ? "Fethiye'nin mavi sırtlarına bakan cam kenarlı, ödüllü sonsuzluk havuzlarımızın keyfini çıkarın." : aciklama
|
||||
};
|
||||
}
|
||||
if (baslik.includes("SPA")) {
|
||||
return {
|
||||
title: lang === "tr" ? "REHIAL SPA TERAPİSİ" : "REHIAL SPA THERAPY",
|
||||
desc: lang === "tr" ? "Yerel uzmanlar tarafından tasarlanan organik zeytin yaprağı taş masajları ve mineral tuzlu hidroterapi ile yenilenin." : aciklama
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: lang === "tr" ? "AÇIK HAVA TERAS YEMEĞİ" : "AL-FRESCO TERRACE DINING",
|
||||
desc: lang === "tr" ? "Akdeniz zeytin ağaçlarının altında taze bahçe malzemeleri ve soğuk sıkım narenciye lezzetlerinin tadını çıkarın." : aciklama
|
||||
};
|
||||
};
|
||||
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
||||
|
||||
:root {
|
||||
--color-resort-teal: #14B8A6;
|
||||
--color-resort-sand: #FAF8F5;
|
||||
--color-resort-charcoal: #0F172A;
|
||||
--color-resort-gold: #D4AF37;
|
||||
}
|
||||
|
||||
.font-serif-editorial {
|
||||
font-family: 'Playfair Display', Georgia, serif;
|
||||
}
|
||||
|
||||
.font-sans-resort {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.bg-light-mesh {
|
||||
background-image:
|
||||
radial-gradient(circle at 0% 0%, rgba(20, 184, 166, 0.04) 0%, transparent 40%),
|
||||
radial-gradient(circle at 100% 100%, rgba(212, 175, 55, 0.03) 0%, transparent 50%);
|
||||
}
|
||||
|
||||
.shadow-premium {
|
||||
box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(38px, 6vw, 90px);
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 0.95;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#0F172A] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-black tracking-[4px] uppercase text-[#14B8A6] block"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
CAL VESTAM RESORT
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#14B8A6]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-serif-editorial text-white text-lg italic font-light tracking-wider"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
interactive prototype
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* MEDITERRANEAN RESORT LIGHT THEME */}
|
||||
<div className="bg-[#FAF8F5] text-[#0F172A] min-h-screen font-sans-resort selection:bg-[#14B8A6] selection:text-white overflow-hidden relative bg-light-mesh pb-20">
|
||||
|
||||
{/* Floating Ambient Orbs */}
|
||||
<div className="absolute top-[10%] left-[-15%] w-[600px] h-[600px] bg-[#14B8A6]/3 blur-[120px] rounded-full pointer-events-none z-0" />
|
||||
<div className="absolute bottom-[20%] right-[-15%] w-[600px] h-[600px] bg-[#D4AF37]/3 blur-[140px] rounded-full pointer-events-none z-0" />
|
||||
|
||||
{/* ── MANDATORY FLOATING DEMO BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#0F172A]/90 backdrop-blur-md border border-white/10 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#14B8A6] animate-pulse" />
|
||||
<span className="text-[9px] font-black uppercase tracking-[1.5px] text-white/90">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* ── PREMIUM FLOATING NAVBAR ── */}
|
||||
<motion.header
|
||||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||||
initial={{ y: -80, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.85, ease: [0.16, 1, 0.3, 1] }}
|
||||
>
|
||||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-white/80 backdrop-blur-xl border border-white/40 rounded-2xl shadow-[0_10px_30px_rgba(15,23,42,0.03)]">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2.5 group">
|
||||
<span className="text-xl font-bold tracking-[2px] text-[#0F172A] font-serif-editorial flex items-center gap-2.5 uppercase">
|
||||
<svg className="w-5 h-5 text-[#14B8A6]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M12 22V12" />
|
||||
<path d="M5 12h14" />
|
||||
<path d="M21 3H3l9 9Z" />
|
||||
<path d="M12 12H7.5" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Links */}
|
||||
<nav className="hidden lg:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navBook, href: "#booking-widget" },
|
||||
{ label: t.navSuites, href: "#suites-showcase" },
|
||||
{ label: t.navExp, href: "#experiences" },
|
||||
{ label: t.navRev, href: "#testimonials" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[10px] font-black tracking-[2px] uppercase text-[#0F172A]/70 hover:text-[#14B8A6] transition-colors relative py-1 cursor-pointer group"
|
||||
>
|
||||
{item.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#14B8A6] transition-all group-hover:w-full" />
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Language Selector + Booking Button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-[#0F172A]/5 border border-[#0F172A]/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-white text-slate-900 shadow-sm" : "text-[#0F172A]/60 hover:text-[#0F172A]"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-white text-slate-900 shadow-sm" : "text-[#0F172A]/60 hover:text-[#0F172A]"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="text-[10px] font-black tracking-[2.5px] uppercase text-white bg-[#14B8A6] hover:bg-[#0D9488] px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_4px_12px_rgba(20,184,166,0.15)] hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.reserveNow}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── HERO & SUITE QUICK LOOK ── */}
|
||||
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||||
|
||||
{/* Left Column: Typography Details */}
|
||||
<motion.div
|
||||
className="lg:col-span-6 z-20"
|
||||
variants={stagger}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="inline-flex items-center gap-2 text-[10px] font-black uppercase tracking-widest text-[#14B8A6] mb-6 bg-[#14B8A6]/5 border border-[#14B8A6]/15 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#14B8A6] animate-pulse" />
|
||||
{t.badge}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={fadeUp}
|
||||
className="font-serif-editorial font-bold text-[#0F172A] leading-[1.1] tracking-tight mb-8 hero-title-clamp"
|
||||
>
|
||||
{firma.slogan}
|
||||
<br />
|
||||
<span className="italic font-light text-[#14B8A6] lowercase">{t.heroTail}</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-[#0F172A]/60 text-xs lg:text-sm leading-relaxed max-w-md mb-12 font-medium"
|
||||
>
|
||||
{t.heroDesc}
|
||||
</motion.p>
|
||||
|
||||
{/* Statistics Grid */}
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="grid grid-cols-2 md:grid-cols-4 gap-6 mb-12"
|
||||
>
|
||||
{istatistikler.map((stat, idx) => (
|
||||
<div key={idx} className="border-l border-[#14B8A6]/30 pl-4 py-1">
|
||||
<h4 className="font-serif-editorial font-bold text-[#0F172A] text-base uppercase tracking-wider mb-1">
|
||||
{stat.deger}
|
||||
</h4>
|
||||
<p className="text-[#0F172A]/50 text-[10px] leading-snug font-bold">
|
||||
{getLocalizedStat(stat.etiket)}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
{/* CTA buttons */}
|
||||
<motion.div variants={fadeUp} className="flex gap-4">
|
||||
<a
|
||||
href="#booking-widget"
|
||||
className="inline-flex items-center gap-3 px-8 py-4 rounded-xl bg-[#14B8A6] hover:bg-[#0D9488] text-white font-black text-[10px] tracking-[2px] uppercase transition-all shadow-[0_5px_15px_rgba(20,184,166,0.2)] cursor-pointer"
|
||||
>
|
||||
{t.planEscape}
|
||||
</a>
|
||||
<a
|
||||
href="#experiences"
|
||||
className="inline-flex items-center gap-3 px-8 py-4 rounded-xl border border-[#0F172A]/10 bg-white/40 hover:bg-white/80 text-[#0F172A] font-black text-[10px] tracking-[2px] uppercase transition-all cursor-pointer"
|
||||
>
|
||||
{t.resortServices}
|
||||
</a>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: Layered Boutique Showcase */}
|
||||
<div className="lg:col-span-6 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-md lg:max-w-lg h-[460px] lg:h-[530px] rounded-3xl overflow-hidden shadow-premium border border-white/60 group"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
>
|
||||
{/* Outer delicate lines */}
|
||||
<div className="absolute inset-4 rounded-[20px] border border-dashed border-[#14B8A6]/10 animate-[spin_100s_linear_infinite] pointer-events-none" />
|
||||
|
||||
{/* Main Mediterranean Dining / Pool Setup */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/sicilia_hero_table.png"
|
||||
alt="Cal Vestam Panoramic Dining Terrace"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms]"
|
||||
/>
|
||||
|
||||
{/* Floating Citrus Welcome Badge Overlay */}
|
||||
<div className="absolute bottom-6 left-6 right-6 bg-white/90 backdrop-blur-xl border border-white/50 rounded-2xl p-5 shadow-2xl flex items-center gap-4">
|
||||
{/* Miniature citrus close-up */}
|
||||
<div className="w-12 h-12 rounded-xl overflow-hidden shrink-0 border border-white">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src="/sicilia_lemon_heritage.png" alt="Citrus welcome orchard" className="w-full h-full object-cover" />
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-[#14B8A6] text-[8px] font-black tracking-widest uppercase block mb-1">{t.welcomeTitle}</span>
|
||||
<h4 className="font-serif-editorial text-xs font-bold text-[#0F172A] uppercase">{t.welcomeDesc}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── INTERACTIVE BOOKING ENGINE ── */}
|
||||
<section id="booking-widget" className="py-24 relative z-10 px-6 bg-white/40 border-t border-white/60">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
|
||||
<div className="bg-white rounded-3xl border border-white p-8 md:p-12 shadow-premium relative">
|
||||
{/* Glowing Top Line */}
|
||||
<div className="absolute top-0 left-12 right-12 h-0.5 bg-gradient-to-r from-transparent via-[#14B8A6] to-transparent" />
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-12">
|
||||
<span className="text-[#14B8A6] font-serif-editorial italic font-bold text-[11px] tracking-[2px] uppercase block mb-2">{t.checkAvailability}</span>
|
||||
<h2 className="font-serif-editorial text-3xl font-bold uppercase text-[#0F172A] tracking-wide">
|
||||
{t.scheduleEscape}
|
||||
</h2>
|
||||
<p className="text-[#0F172A]/50 text-xs mt-2 font-medium">
|
||||
{t.scheduleDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Booking Fields Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{[
|
||||
{ label: t.checkin, type: "date" },
|
||||
{ label: t.checkout, type: "date" },
|
||||
].map((field, idx) => (
|
||||
<div key={idx} className="flex flex-col">
|
||||
<label className="text-[10px] font-black text-[#0F172A]/50 mb-1.5 uppercase tracking-widest">{field.label}</label>
|
||||
<input
|
||||
type={field.type}
|
||||
className="px-4 py-3.5 rounded-xl border border-gray-200 bg-[#FAF8F5] text-xs text-[#0F172A] focus:outline-none focus:border-[#14B8A6] focus:ring-1 focus:ring-[#14B8A6] transition-all font-semibold cursor-pointer"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Adults Count */}
|
||||
<div className="flex flex-col">
|
||||
<label className="text-[10px] font-black text-[#0F172A]/50 mb-1.5 uppercase tracking-widest">{t.adults}</label>
|
||||
<div className="flex items-center justify-between px-4 py-2.5 rounded-xl border border-gray-200 bg-[#FAF8F5]">
|
||||
<button
|
||||
onClick={() => setAdults(Math.max(1, adults - 1))}
|
||||
className="w-8 h-8 rounded-lg bg-white border border-gray-100 flex items-center justify-center font-bold text-xs text-[#0F172A] hover:bg-gray-50 cursor-pointer shadow-sm"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<span className="text-xs font-black text-[#0F172A]">{adults} {t.guests}</span>
|
||||
<button
|
||||
onClick={() => setAdults(adults + 1)}
|
||||
className="w-8 h-8 rounded-lg bg-white border border-gray-100 flex items-center justify-center font-bold text-xs text-[#0F172A] hover:bg-gray-50 cursor-pointer shadow-sm"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Kids Count */}
|
||||
<div className="flex flex-col">
|
||||
<label className="text-[10px] font-black text-[#0F172A]/50 mb-1.5 uppercase tracking-widest">{t.kids}</label>
|
||||
<div className="flex items-center justify-between px-4 py-2.5 rounded-xl border border-gray-200 bg-[#FAF8F5]">
|
||||
<button
|
||||
onClick={() => setKids(Math.max(0, kids - 1))}
|
||||
className="w-8 h-8 rounded-lg bg-white border border-gray-100 flex items-center justify-center font-bold text-xs text-[#0F172A] hover:bg-gray-50 cursor-pointer shadow-sm"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<span className="text-xs font-black text-[#0F172A]">{kids} {t.kidsLabel}</span>
|
||||
<button
|
||||
onClick={() => setKids(kids + 1)}
|
||||
className="w-8 h-8 rounded-lg bg-white border border-gray-100 flex items-center justify-center font-bold text-xs text-[#0F172A] hover:bg-gray-50 cursor-pointer shadow-sm"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action row */}
|
||||
<div className="mt-8 pt-4 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p className="text-[#0F172A]/40 text-xs font-medium max-w-md text-center md:text-left">
|
||||
{t.guarantee}
|
||||
</p>
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="w-full md:w-auto px-10 py-4 rounded-xl bg-[#14B8A6] hover:bg-[#0D9488] text-white font-black text-[10px] tracking-[2px] uppercase transition-all cursor-pointer shadow-[0_5px_15px_rgba(20,184,166,0.15)] shrink-0"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.confirmDetails}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── SUITES GALLERY ── */}
|
||||
<section id="suites-showcase" className="py-32 relative z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="flex flex-col md:flex-row md:items-end justify-between mb-16 gap-6">
|
||||
<div>
|
||||
<span className="text-[#14B8A6] font-serif-editorial italic font-bold text-sm tracking-[2px] uppercase block mb-3">{t.suitesTitle}</span>
|
||||
<h2 className="font-serif-editorial text-4xl lg:text-5xl font-bold tracking-tight text-[#0F172A] uppercase">
|
||||
{t.suitesHeader}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-[#0F172A]/50 text-xs max-w-sm font-semibold leading-relaxed">
|
||||
{t.suitesDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Gallery Columns */}
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{[
|
||||
{ title: t.suite1Title, img: "/sicilia_hero_table.png", desc: t.suite1Desc },
|
||||
{ title: t.suite2Title, img: "/sicilia_lemon_heritage.png", desc: t.suite2Desc },
|
||||
{ title: t.suite3Title, img: "/sicilia_hero_table.png", desc: t.suite3Desc },
|
||||
].map((suite, idx) => (
|
||||
<motion.div
|
||||
key={idx}
|
||||
className="bg-white rounded-3xl border border-white overflow-hidden transition-all duration-300 hover:border-[#14B8A6]/30 flex flex-col justify-between group shadow-premium"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: idx * 0.1 }}
|
||||
whileHover={{ y: -6 }}
|
||||
>
|
||||
<div className="h-56 overflow-hidden relative border-b border-gray-100">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={suite.img}
|
||||
alt={suite.title}
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-1000"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/5" />
|
||||
</div>
|
||||
|
||||
<div className="p-8 space-y-4">
|
||||
<h3 className="font-serif-editorial font-bold text-lg text-[#0F172A] tracking-wider uppercase leading-snug">
|
||||
{suite.title}
|
||||
</h3>
|
||||
<p className="text-[#0F172A]/50 text-[11px] leading-relaxed font-semibold">
|
||||
{suite.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="px-8 pb-8">
|
||||
<button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="text-[#14B8A6] font-black text-[10px] tracking-[2px] uppercase flex items-center gap-1.5 cursor-pointer hover:text-[#0D9488] transition-colors"
|
||||
>
|
||||
{t.secureRes}
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── RESORT EXPERIENCES ── */}
|
||||
<section id="experiences" className="py-24 relative z-10 px-6 bg-white/40 border-t border-white/60">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
{hizmetler.map((hizmet, idx) => {
|
||||
const locServ = getLocalizedService(hizmet.baslik, hizmet.aciklama);
|
||||
return (
|
||||
<div
|
||||
key={idx}
|
||||
className="bg-white p-8 rounded-3xl border border-white flex flex-col justify-between h-72 transition-all hover:shadow-premium group"
|
||||
>
|
||||
<div>
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#14B8A6]/5 border border-[#14B8A6]/10 flex items-center justify-center mb-6">
|
||||
<svg className="w-5 h-5 text-[#14B8A6]" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="m9 12 2 2 4-4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="font-serif-editorial font-bold text-lg text-[#0F172A] mb-2 uppercase">
|
||||
{locServ.title}
|
||||
</h3>
|
||||
<p className="text-[#0F172A]/60 text-[11px] leading-relaxed font-semibold">
|
||||
{locServ.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="text-[#14B8A6] font-black text-[9px] tracking-[2.5px] uppercase flex items-center gap-1 cursor-pointer hover:text-[#0D9488] transition-colors"
|
||||
>
|
||||
{lang === "tr" ? "DAHA FAZLA KEŞFET →" : "DISCOVER MORE →"}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── TESTIMONIALS ── */}
|
||||
<section id="testimonials" className="py-28 relative z-10 px-6 border-t border-white/60">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#14B8A6] font-serif-editorial italic font-bold text-sm tracking-[2px] uppercase block mb-2">{t.diaries}</span>
|
||||
<h2 className="font-serif-editorial font-bold text-3xl lg:text-4xl uppercase text-[#0F172A] tracking-wider">
|
||||
{t.lovedGuests}
|
||||
</h2>
|
||||
<p className="text-[#0F172A]/40 text-xs mt-2 font-medium">
|
||||
{t.lovedDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Testimonials 2-Column Grid */}
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{yorumlar.map((y, yIdx) => (
|
||||
<div
|
||||
key={yIdx}
|
||||
className="bg-white border border-white rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 hover:border-[#14B8A6]/30 group shadow-premium"
|
||||
>
|
||||
{/* Rating Stars SVG */}
|
||||
<div className="flex gap-1.5 mb-6">
|
||||
{[...Array(5)].map((_, starIdx) => (
|
||||
<svg key={starIdx} className="w-4 h-4 fill-[#14B8A6]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="text-[#0F172A]/70 text-xs leading-relaxed italic mb-8 font-medium font-serif-editorial">
|
||||
“{y.yorum}”
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full border border-gray-100 flex items-center justify-center text-lg bg-[#FAF8F5] select-none font-bold">
|
||||
{y.yazar.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-serif-editorial text-[#0F172A] text-xs font-bold uppercase tracking-wider">
|
||||
{y.yazar}
|
||||
</h4>
|
||||
<span className="text-[9px] text-[#0F172A]/40 uppercase tracking-widest font-black">
|
||||
{y.tarih}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-white border-t border-gray-100 pt-24 pb-8 px-6 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-gray-100">
|
||||
|
||||
{/* About Column */}
|
||||
<div className="md:col-span-2">
|
||||
<span className="font-serif-editorial text-2xl font-bold text-[#0F172A] tracking-wider uppercase mb-4 block">
|
||||
Cal<span className="text-[#14B8A6]">Vestam</span>
|
||||
</span>
|
||||
<p className="text-[#0F172A]/50 text-xs leading-relaxed max-w-sm mb-8 font-medium">
|
||||
{firma.slogan} — Exclusive boutique resort nestled inside Ölüdeniz heights. Handcrafted sea suites, infinity pools, and organic salt therapy.
|
||||
</p>
|
||||
<div className="text-[#0F172A]/60 text-xs font-medium space-y-3">
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#14B8A6] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
<span className="text-[#0F172A]/80">{firma.adres}</span>
|
||||
</p>
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#14B8A6] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect width="20" height="16" x="2" y="4" rx="2" />
|
||||
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" />
|
||||
</svg>
|
||||
<span className="text-[#0F172A]/80">{firma.email}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Coordinates Column */}
|
||||
<div>
|
||||
<h4 className="font-serif-editorial text-[#14B8A6] text-xs font-bold uppercase tracking-wider mb-6">
|
||||
{t.vipCoords}
|
||||
</h4>
|
||||
<div className="space-y-4 text-xs text-[#0F172A]/50 font-semibold">
|
||||
<p>{t.conciergeActive} <br /> <span className="text-[#0F172A]/80">24 Hours Active</span></p>
|
||||
<p>Check-In/Out <br /> <span className="text-[#0F172A]/80">{t.checkInOutDetails}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Leisure Services Column */}
|
||||
<div>
|
||||
<h4 className="font-serif-editorial text-[#14B8A6] text-xs font-bold uppercase tracking-wider mb-6">
|
||||
{t.boutiqueLeisures}
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{hizmetler.map((h, hIdx) => {
|
||||
const locS = getLocalizedService(h.baslik, h.aciklama);
|
||||
return (
|
||||
<a
|
||||
key={hIdx}
|
||||
href="#suites-showcase"
|
||||
className="block text-[#0F172A]/50 hover:text-[#14B8A6] text-xs transition-colors font-semibold"
|
||||
>
|
||||
{locS.title}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-[#0F172A]/30 text-xs font-semibold">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-[#0F172A] transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-[#0F172A] transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── CONFIRM SUCCESS MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/30 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-white rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-gray-100"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-[#FAF8F5] border border-gray-100 flex items-center justify-center text-[#0F172A]/40 hover:text-[#14B8A6] hover:border-[#14B8A6]/20 transition-all cursor-pointer font-bold"
|
||||
onClick={() => setShowModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
{/* Success check indicator */}
|
||||
<div className="w-16 h-16 rounded-2xl bg-[#14B8A6]/10 border border-[#14B8A6]/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-8 h-8 stroke-[#14B8A6] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 className="font-serif-editorial font-bold text-[#0F172A] text-2xl mb-1 uppercase tracking-wider">
|
||||
{t.enquiryActive}
|
||||
</h3>
|
||||
<p className="text-[#14B8A6] font-sans-resort text-[10px] mb-6 uppercase tracking-widest font-black">
|
||||
{t.ambassadorActive}
|
||||
</p>
|
||||
|
||||
<p className="text-[#0F172A]/60 text-xs leading-relaxed mb-8 font-semibold">
|
||||
{t.enquirySuccess}
|
||||
</p>
|
||||
|
||||
<motion.button
|
||||
className="w-full py-4 rounded-xl bg-[#14B8A6] hover:bg-[#0D9488] text-white font-black text-[10px] tracking-[2px] uppercase cursor-pointer shadow-md shadow-[#14B8A6]/15"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowModal(false)}
|
||||
>
|
||||
{t.dismiss}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,747 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 35 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.65, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.08 } },
|
||||
};
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navCabin: "Kulübemiz",
|
||||
navHosts: "Hizmetlerimiz",
|
||||
navChannels: "Rezervasyon",
|
||||
navReviews: "Misafir Günlüğü",
|
||||
bookWilderness: "Kulübeyi Ayırt",
|
||||
est: "2015'TEN BERİ",
|
||||
heroDesc: "Şebekeden bağımsız lüks dağ kulübesi inzivalarına dalın. Odun ateşinde taze ekmek fırın sabahları, rustik açık şömine salonları ve serin dağ nehrinde alabalık avı koordinatları.",
|
||||
secureCabin: "REZERVASYON YAP",
|
||||
cabinUnits: "Dağ Kulübeleri",
|
||||
cabinWood: "Darby Kırmızı Sedir",
|
||||
fireplaceUnit: "Tütsülü Şömine",
|
||||
fireplaceType: "Doğal Taş Ocak",
|
||||
aboutTitle: "Darby Dağ Yaşamı",
|
||||
aboutHeader: "KULÜBE HAKKINDA",
|
||||
aboutSub: "DOĞAL MT. LOGWOOD AKUSTİĞİ ALTINDA HUZUR",
|
||||
aboutDesc: "Bitterroot Bunkhouse, Darby milli orman koordinatlarının derinliklerinde el işçiliğiyle inşa edilmiş iki adet kırmızı sedir dağ kulübesi sunar. Her kulübe döküm demir mutfak gereçleri, kurutulmuş huş odunları ve yerel gölleri keşfetmeniz için dağ rehberleriyle donatılmıştır.",
|
||||
feat1Title: "YABANİ YÜRÜYÜŞ YOLLARI",
|
||||
feat1Desc: "Arka terasınızdan doğrudan yaban çiçeği orman yollarına adım atın.",
|
||||
feat2Title: "ODUN ATEŞİNDE SABAHLAR",
|
||||
feat2Desc: "Her gün ücretsiz temin edilen şömine odunlarının ve döküm fırın ikramlarının keyfini çıkarın.",
|
||||
channelsTitle: "Entegre Platformlar",
|
||||
channelsHeader: "REZERVASYON YÖNTEMLERİ",
|
||||
channelsDesc: "Senkronize edilmiş kanallarimizi aşağidan inceleyin. Komisyonsuz konaklamalar için Airbnb, VRBO veya doğrudan kurumsal web sitemiz üzerinden rezervasyon yapin.",
|
||||
chAirbnb: "AIRBNB İLE REZERVE ET",
|
||||
chVrbo: "VRBO İLE REZERVE ET",
|
||||
chDirect: "DOĞRUDAN REZERVE (%15 TASARRUF)",
|
||||
airbnbTitle: "Airbnb Superhost Kanalı",
|
||||
airbnbDesc: "Giriş ve konaklama takvimlerini doğrudan Superhost sayfamızdan anlık doğrulayın. Klasik platform güvencesi arayan gezginler için idealdir.",
|
||||
vrboTitle: "VRBO Premier Host Kanalı",
|
||||
vrboDesc: "Aileler veya geniş gruplar için Premier Host statüsünde listelemeler. Grup iptal ve iade ayrıcalıkları çıkış esnasında otomatik olarak uygulanır.",
|
||||
directTitle: "Doğrudan Kulübe Rezervasyonu",
|
||||
directDesc: "Rezervasyon hizmet bedellerini tamamen atlayın. Girişte size özel taze ekşi mayalı sabah ekmeği, ücretsiz şömine odunu ve doğrudan VIP mihmandar desteği alın.",
|
||||
launchPortal: "REZERVASYON PORTALINI BAŞLAT",
|
||||
diaries: "Yaban Günlükleri",
|
||||
lovedGuests: "MİSAFİRLERİMİZDEN KELİMELER",
|
||||
vipServices: "VIP HİZMETLER",
|
||||
mountainHelp: "Dağ Desteği",
|
||||
mountainActive: "Her Gün 08:00 - 20:00 Aktif",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Kulübe Şartları",
|
||||
dismiss: "KAPAT",
|
||||
enquiryActive: "REZERVASYON ALINDI",
|
||||
ambassadorActive: "Yaban Concierge Aktif",
|
||||
enquirySuccess: "Darby dağ kulübesi rezervasyon talebinizi kaydettik. Sertifikalı yaban mihmandarımız geliş, sıcak ekmek ve kano yolları detaylarını planlamak için sizinle iletişime geçecektir. Teşekkürler!",
|
||||
},
|
||||
en: {
|
||||
navCabin: "Our cabin",
|
||||
navHosts: "Host guides",
|
||||
navChannels: "Book channels",
|
||||
navReviews: "Guest diaries",
|
||||
bookWilderness: "Book wilderness",
|
||||
est: "ESTABLISHED IN 2015",
|
||||
heroDesc: "Immerse in off-grid luxury cabin retreats. Wood-fired bakery mornings, rustic open fireplace lounges, and cold mountain river trout coordinates.",
|
||||
secureCabin: "SECURE CABIN SLOTS",
|
||||
cabinUnits: "A-frame lodges",
|
||||
cabinWood: "Darby Cedar Wood",
|
||||
fireplaceUnit: "Stocked fireplace",
|
||||
fireplaceType: "Open Stone Hearth",
|
||||
aboutTitle: "Darby Mountain Life",
|
||||
aboutHeader: "ABOUT THE CABIN",
|
||||
aboutSub: "OFF-GRID HEAVEN UNDER MT. LOGWOOD ACOUSTICS",
|
||||
aboutDesc: "Bitterroot Bunkhouse provides two hand-crafted A-frame cedar lodges deep in the Darby forest coordinates. Each lodge is stocked with cast-iron cookware, seasoned logwood reserves, and local guides to explore hidden mountain lakes.",
|
||||
feat1Title: "WILDERNESS TRAIL PATHS",
|
||||
feat1Desc: "Walk directly from your back deck onto wildflower forest lines.",
|
||||
feat2Title: "WOOD-FIRED MORNINGS",
|
||||
feat2Desc: "Enjoy complimentary firewood logs and hot stone iron bakers daily.",
|
||||
channelsTitle: "Integrated Platforms",
|
||||
channelsHeader: "HOW TO SECURE BOOKINGS",
|
||||
channelsDesc: "Toggle our synced channels below. Syncing Airbnb, VRBO, or our premium Direct reservation for commission-free stays.",
|
||||
chAirbnb: "BOOK ON AIRBNB",
|
||||
chVrbo: "BOOK ON VRBO",
|
||||
chDirect: "BOOK DIRECT (SAVE 15%)",
|
||||
airbnbTitle: "Airbnb Superhost Channel",
|
||||
airbnbDesc: "Verify lodging calendars dynamically directly on our superhost page listing. Perfect for travelers seeking classic platform protection.",
|
||||
vrboTitle: "VRBO Premier Host Channel",
|
||||
vrboDesc: "Premier hosts status listings for families or large groups. All group cancellation benefits apply automatically upon checkout.",
|
||||
directTitle: "Bunkhouse Direct Booking",
|
||||
directDesc: "Skip booking service fees completely. Receive customized fresh morning sourdough, complimentary firewood, and direct VIP coordination.",
|
||||
launchPortal: "LAUNCH RESERVATION PORTAL",
|
||||
diaries: "Wilderness Diaries",
|
||||
lovedGuests: "KIND WORDS FROM PAST GUESTS",
|
||||
vipServices: "VIP SERVICES",
|
||||
mountainHelp: "Mountain Help",
|
||||
mountainActive: "Available 8 AM - 8 PM",
|
||||
privacyRegs: "Privacy Regulations",
|
||||
termsStay: "Terms of Cabin",
|
||||
dismiss: "DISMISS",
|
||||
enquiryActive: "CABIN REQUEST FILED",
|
||||
ambassadorActive: "Wilderness Concierge Active",
|
||||
enquirySuccess: "We have registered your Darby wilderness cabin coordinate request. A certified somatic host will contact you shortly to coordinate arrival, hot bread baking, and kayak paths. Thank you!",
|
||||
}
|
||||
};
|
||||
|
||||
export default function HotelTemplate2({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], yorumlar = [] } = data;
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [channel, setChannel] = useState<string>("direct");
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// 1. Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// 2. Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Localized services
|
||||
const getLocalizedService = (baslik: string, aciklama: string) => {
|
||||
if (baslik.includes("HOSTS")) {
|
||||
return {
|
||||
title: lang === "tr" ? "EV SAHİBİ REHBERLİĞİ" : "MEET YOUR HOSTS",
|
||||
desc: lang === "tr" ? "Yerel dağ rehberlerimiz; alabalık avı yolları, yaban çiçeği rotaları ve gizli nehir haritaları koordinasyonunu üstlenir." : aciklama
|
||||
};
|
||||
}
|
||||
if (baslik.includes("POLICIES")) {
|
||||
return {
|
||||
title: lang === "tr" ? "KULÜBE KURALLARI" : "CABIN POLICIES",
|
||||
desc: lang === "tr" ? "Evcil hayvan dostu konaklama koşulları. Döküm demir tava ve her zaman dolu odunluk güvenceleri." : aciklama
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: lang === "tr" ? "DOĞRUDAN REZERVE" : "DIRECT RESERVATION",
|
||||
desc: lang === "tr" ? "Airbnb veya VRBO ile anlık takvim senkronizasyonu; dilerseniz komisyonsuz doğrudan rezervasyon avantajı." : aciklama
|
||||
};
|
||||
};
|
||||
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
||||
|
||||
:root {
|
||||
--color-bunkhouse-gold: #854D0E;
|
||||
--color-bunkhouse-sand: #F5F2EB;
|
||||
--color-bunkhouse-stone: #1C1917;
|
||||
--color-bunkhouse-card: #FAF8F5;
|
||||
}
|
||||
|
||||
.font-serif-bunkhouse {
|
||||
font-family: 'Playfair Display', Georgia, serif;
|
||||
}
|
||||
|
||||
.font-industrial-bunkhouse {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.font-sans-bunkhouse {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.bg-rustic-mesh {
|
||||
background-image:
|
||||
radial-gradient(circle at 10% 10%, rgba(133, 77, 14, 0.02) 0%, transparent 40%),
|
||||
radial-gradient(circle at 90% 90%, rgba(28, 25, 23, 0.02) 0%, transparent 50%),
|
||||
linear-gradient(rgba(28, 25, 23, 0.005) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(28, 25, 23, 0.005) 1px, transparent 1px);
|
||||
background-size: 100% 100%, 100% 100%, 30px 30px, 30px 30px;
|
||||
}
|
||||
|
||||
.border-bunkhouse {
|
||||
border-color: rgba(28, 25, 23, 0.15);
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(34px, 5vw, 85px);
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 0.95;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#1C1917] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-black tracking-[4px] uppercase text-[#854D0E] block font-sans-bunkhouse"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
BITTERROOT BUNKHOUSE
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#854D0E]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-serif-bunkhouse text-white text-lg italic font-light tracking-wider"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
wilderness sanctuary
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* COZY RUSTIC WILDERNESS LODGE THEME */}
|
||||
<div className="bg-[#F5F2EB] text-[#1C1917] min-h-screen font-sans-bunkhouse selection:bg-[#854D0E] selection:text-white overflow-hidden relative bg-rustic-mesh pb-24">
|
||||
|
||||
{/* Floating Woody Ambience Orbs */}
|
||||
<div className="absolute top-[20%] left-[-10%] w-[500px] h-[500px] bg-[#854D0E]/2 blur-[130px] rounded-full pointer-events-none z-0" />
|
||||
<div className="absolute bottom-[20%] right-[-10%] w-[500px] h-[500px] bg-[#854D0E]/1 blur-[150px] rounded-full pointer-events-none z-0" />
|
||||
|
||||
{/* ── MANDATORY FLOATING DEMO BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#1C1917]/95 backdrop-blur-md border border-white/10 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#854D0E] animate-pulse" />
|
||||
<span className="text-[9px] font-black uppercase tracking-[1.5px] text-white/90">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{/* ── COZY HEADER ── */}
|
||||
<motion.header
|
||||
className="w-full border-b border-[#1C1917]/10 px-8 py-6 relative z-50 bg-[#F5F2EB]/90 backdrop-blur-xl"
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
>
|
||||
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2.5 group">
|
||||
<span className="text-lg font-bold tracking-[2px] text-[#1C1917] font-serif-bunkhouse flex items-center gap-2 uppercase">
|
||||
<svg className="w-5 h-5 text-[#854D0E]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="m8 3 4 8 5-5 5 15H2L8 3Z" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Links */}
|
||||
<nav className="hidden md:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navCabin, href: "#about-cabin" },
|
||||
{ label: t.navHosts, href: "#host-details" },
|
||||
{ label: t.navChannels, href: "#booking-channels" },
|
||||
{ label: t.navReviews, href: "#testimonials" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[9px] font-bold tracking-[2.5px] uppercase text-[#1C1917]/70 hover:text-[#854D0E] transition-colors relative py-1 cursor-pointer"
|
||||
>
|
||||
{item.label}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Language Selector + Booking Button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-[#1C1917]/5 border border-[#1C1917]/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-[#1C1917] text-white shadow-sm" : "text-[#1C1917]/60 hover:text-[#1C1917]"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-[#1C1917] text-white shadow-sm" : "text-[#1C1917]/60 hover:text-[#1C1917]"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="text-[9px] font-bold tracking-[2.5px] uppercase text-white bg-[#1C1917] hover:bg-[#854D0E] px-6 py-3.5 rounded-lg transition-all cursor-pointer shadow-md hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.bookWilderness}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── COZY HERO BANNER (DARK CONTRAST) ── */}
|
||||
<section className="relative z-10 max-w-7xl mx-auto px-6 mt-8">
|
||||
<motion.div
|
||||
className="w-full min-h-[500px] rounded-3xl bg-[#1C1917] text-[#FAF8F5] p-8 md:p-16 flex flex-col justify-between relative overflow-hidden shadow-2xl"
|
||||
initial={{ opacity: 0, scale: 0.98 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
{/* Ambient fire glow background */}
|
||||
<div className="absolute top-0 right-0 w-[450px] h-[450px] bg-[#854D0E]/20 blur-[100px] rounded-full pointer-events-none" />
|
||||
|
||||
{/* Banner top */}
|
||||
<div className="flex justify-between items-start z-10">
|
||||
<span className="text-[9px] font-bold uppercase tracking-[3px] text-[#FAF8F5]/50 border border-white/10 px-3 py-1.5 rounded-full">
|
||||
BITTERROOT VALLEY · MONTANA
|
||||
</span>
|
||||
<span className="text-[9px] font-bold uppercase tracking-[3px] text-[#FAF8F5]/50">
|
||||
{t.est}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Banner headings */}
|
||||
<div className="max-w-2xl my-16 z-10">
|
||||
<h1 className="font-serif-bunkhouse text-4xl md:text-6xl font-normal leading-[1.08] tracking-wider mb-6 text-white uppercase">
|
||||
{firma.slogan}
|
||||
</h1>
|
||||
<p className="text-[#FAF8F5]/60 text-xs md:text-sm leading-relaxed font-normal max-w-md">
|
||||
{t.heroDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Banner bottom details */}
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6 border-t border-white/10 pt-8 z-10">
|
||||
<div className="flex gap-12">
|
||||
<div>
|
||||
<span className="text-[#FAF8F5]/40 text-[9px] uppercase tracking-widest font-bold block mb-1">{t.cabinUnits}</span>
|
||||
<span className="font-industrial-bunkhouse text-lg font-bold">{t.cabinWood}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-[#FAF8F5]/40 text-[9px] uppercase tracking-widest font-bold block mb-1">{t.fireplaceUnit}</span>
|
||||
<span className="font-industrial-bunkhouse text-lg font-bold">{t.fireplaceType}</span>
|
||||
</div>
|
||||
</div>
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="px-8 py-4 bg-[#854D0E] hover:bg-white hover:text-[#1C1917] text-white font-bold text-[9px] tracking-[2.5px] uppercase rounded-xl transition-all cursor-pointer shadow-lg"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
>
|
||||
{t.secureCabin}
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
{/* ── ABOUT THE CABIN WITH LAYERED GRAPHICS ── */}
|
||||
<section id="about-cabin" className="py-28 relative z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#854D0E] font-serif-bunkhouse italic text-sm tracking-[2px] block mb-2">{t.aboutTitle}</span>
|
||||
<h2 className="font-serif-bunkhouse text-3xl md:text-4xl uppercase tracking-wider text-[#1C1917]">
|
||||
{t.aboutHeader}
|
||||
</h2>
|
||||
<div className="w-16 h-0.5 bg-[#854D0E]/20 mx-auto mt-4" />
|
||||
</div>
|
||||
|
||||
{/* Layered images grid */}
|
||||
<div className="grid lg:grid-cols-12 gap-12 items-center">
|
||||
|
||||
{/* Left Column: 3 detailed pictures layered */}
|
||||
<div className="lg:col-span-7 grid grid-cols-12 gap-4 items-center">
|
||||
{/* 1st image: Sourdough fresh bakery */}
|
||||
<div className="col-span-5 rounded-2xl overflow-hidden shadow-lg border border-[#1C1917]/10 aspect-[3/4] group">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/bakery_heritage.png"
|
||||
alt="Wilderness breakfast sourdough bakery"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-1000"
|
||||
/>
|
||||
</div>
|
||||
{/* 2nd image: Cozy fireside cooking */}
|
||||
<div className="col-span-7 rounded-2xl overflow-hidden shadow-xl border border-[#1C1917]/10 aspect-square group">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/chef_plating_smoke.png"
|
||||
alt="Cozy lodge stone fireplace cooking"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-1000"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Cabin text details */}
|
||||
<div className="lg:col-span-5 space-y-8">
|
||||
<span className="text-[9px] font-bold tracking-[3px] text-[#854D0E] uppercase block">EXCLUSIVELY HAND-CRAFTED</span>
|
||||
<h3 className="font-serif-bunkhouse text-2xl md:text-3xl text-[#1C1917] leading-snug">
|
||||
{t.aboutSub}
|
||||
</h3>
|
||||
<p className="text-[#1C1917]/70 text-xs leading-relaxed font-medium">
|
||||
{t.aboutDesc}
|
||||
</p>
|
||||
|
||||
{/* Details list */}
|
||||
<div className="space-y-4 pt-4 border-t border-[#1C1917]/15">
|
||||
{[
|
||||
{ title: t.feat1Title, text: t.feat1Desc },
|
||||
{ title: t.feat2Title, text: t.feat2Desc },
|
||||
].map((feat, idx) => (
|
||||
<div key={idx} className="flex gap-4">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#854D0E] shrink-0 mt-1.5" />
|
||||
<div>
|
||||
<h4 className="text-[10px] font-black uppercase text-[#1C1917] tracking-wider mb-1">{feat.title}</h4>
|
||||
<p className="text-[#1C1917]/50 text-[10px] font-bold leading-relaxed">{feat.text}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CHANNELS & HOST GUIDES ── */}
|
||||
<section id="host-details" className="py-24 relative z-10 px-6 bg-[#FAF8F5] border-y border-[#1C1917]/10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid lg:grid-cols-3 gap-8">
|
||||
{hizmetler.map((hizmet, idx) => {
|
||||
const locServ = getLocalizedService(hizmet.baslik, hizmet.aciklama);
|
||||
return (
|
||||
<div
|
||||
key={idx}
|
||||
className="bg-[#F5F2EB] p-8 rounded-3xl border border-[#1C1917]/10 flex flex-col justify-between h-72 transition-all hover:shadow-premium group"
|
||||
>
|
||||
<div>
|
||||
<div className="w-12 h-12 rounded-2xl bg-white border border-[#1C1917]/10 flex items-center justify-center mb-6">
|
||||
<svg className="w-5 h-5 text-[#854D0E]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="m9 12 2 2 4-4" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="font-serif-bunkhouse text-lg font-black uppercase tracking-wider text-[#1C1917] mb-2">
|
||||
{locServ.title}
|
||||
</h3>
|
||||
<p className="text-[#1C1917]/60 text-[11px] leading-relaxed font-semibold">
|
||||
{locServ.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="text-[#854D0E] font-bold text-[9px] tracking-[2.5px] uppercase flex items-center gap-1 cursor-pointer hover:text-[#5F3507]"
|
||||
>
|
||||
{lang === "tr" ? "DAHA FAZLA KEŞFET →" : "DISCOVER MORE →"}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── CHANNEL BOOKING INTEGRATION ── */}
|
||||
<section id="booking-channels" className="py-32 relative z-10 px-6">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
|
||||
<div className="bg-[#1C1917] text-white rounded-3xl p-8 md:p-12 shadow-2xl relative border border-white/5">
|
||||
<div className="absolute top-0 left-12 right-12 h-0.5 bg-gradient-to-r from-transparent via-[#854D0E] to-transparent" />
|
||||
|
||||
<div className="text-center mb-12">
|
||||
<span className="text-[#854D0E] font-serif-bunkhouse uppercase tracking-widest text-xs block mb-2">{t.channelsTitle}</span>
|
||||
<h2 className="font-serif-bunkhouse text-3xl font-normal tracking-wide text-white uppercase">
|
||||
{t.channelsHeader}
|
||||
</h2>
|
||||
<p className="text-white/40 text-xs mt-2 max-w-md mx-auto leading-relaxed">
|
||||
{t.channelsDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Toggle channels buttons */}
|
||||
<div className="grid grid-cols-3 gap-3 mb-10">
|
||||
{[
|
||||
{ id: "airbnb", label: t.chAirbnb },
|
||||
{ id: "vrbo", label: t.chVrbo },
|
||||
{ id: "direct", label: t.chDirect },
|
||||
].map(item => (
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => setChannel(item.id)}
|
||||
className={`px-4 py-3.5 rounded-xl border text-[9px] font-bold uppercase tracking-widest transition-all cursor-pointer text-center ${
|
||||
channel === item.id
|
||||
? "bg-[#854D0E] border-[#854D0E] text-white shadow-md"
|
||||
: "bg-white/[0.02] border-white/5 text-white/50 hover:text-white hover:border-white/10"
|
||||
}`}
|
||||
>
|
||||
{item.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Active channel info */}
|
||||
<div className="bg-white/5 rounded-2xl p-6 border border-white/5">
|
||||
<h3 className="font-serif-bunkhouse text-white text-lg font-black uppercase tracking-wider mb-2">
|
||||
{channel === "airbnb" ? t.airbnbTitle : channel === "vrbo" ? t.vrboTitle : t.directTitle}
|
||||
</h3>
|
||||
<p className="text-white/50 text-[11px] leading-relaxed mb-6 font-medium">
|
||||
{channel === "airbnb"
|
||||
? t.airbnbDesc
|
||||
: channel === "vrbo"
|
||||
? t.vrboDesc
|
||||
: t.directDesc}
|
||||
</p>
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="w-full py-4.5 rounded-xl bg-[#854D0E] hover:bg-white hover:text-[#1C1917] text-white font-bold text-[9px] tracking-[2px] uppercase cursor-pointer transition-colors shadow-md"
|
||||
whileHover={{ scale: 1.01 }}
|
||||
>
|
||||
{t.launchPortal}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── TESTIMONIALS ── */}
|
||||
<section id="testimonials" className="py-24 relative z-10 px-6 bg-[#FAF8F5] border-t border-[#1C1917]/10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#854D0E] font-serif-bunkhouse text-xs uppercase tracking-widest block mb-2">{t.diaries}</span>
|
||||
<h2 className="font-serif-bunkhouse text-3xl font-black uppercase text-[#1C1917]">
|
||||
{t.lovedGuests}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Grid */}
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{yorumlar.map((y, yIdx) => (
|
||||
<div
|
||||
key={yIdx}
|
||||
className="bg-white border border-[#1C1917]/10 rounded-3xl p-8 flex flex-col justify-between transition-all hover:shadow-premium group"
|
||||
>
|
||||
<div className="flex gap-1.5 mb-6">
|
||||
{[...Array(5)].map((_, starIdx) => (
|
||||
<svg key={starIdx} className="w-4 h-4 fill-[#854D0E]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="text-[#1C1917]/70 text-xs leading-relaxed italic mb-8 font-medium font-serif-bunkhouse">
|
||||
“{y.yorum}”
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full border border-[#1C1917]/10 flex items-center justify-center text-lg bg-[#FAF8F5] select-none font-bold">
|
||||
{y.yazar.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-serif-bunkhouse text-[#1C1917] text-xs font-black uppercase tracking-wider">
|
||||
{y.yazar}
|
||||
</h4>
|
||||
<span className="text-[9px] text-[#1C1917]/40 uppercase tracking-widest font-black">
|
||||
{y.tarih}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-[#1C1917] text-white pt-24 pb-8 px-6 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/10">
|
||||
|
||||
{/* About Column */}
|
||||
<div className="md:col-span-2">
|
||||
<span className="font-serif-bunkhouse text-2xl font-black text-white tracking-wider uppercase mb-4 block">
|
||||
Bitterroot<span className="text-[#854D0E]">Bunkhouse</span>
|
||||
</span>
|
||||
<p className="text-white/50 text-xs leading-relaxed max-w-sm mb-8 font-medium">
|
||||
{firma.slogan} — Cozy hand-built rustic cedar cabins deep inside Darby forest valley. High-end off-grid luxury.
|
||||
</p>
|
||||
<div className="text-white/60 text-xs font-medium space-y-3">
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#854D0E] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
<span className="text-white/80">{firma.adres}</span>
|
||||
</p>
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#854D0E] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect width="20" height="16" x="2" y="4" rx="2" />
|
||||
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" />
|
||||
</svg>
|
||||
<span className="text-white/80">{firma.email}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Coordinates Column */}
|
||||
<div>
|
||||
<h4 className="font-serif-bunkhouse text-[#854D0E] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{lang === "tr" ? "KULÜBE KOORDİNATLARI" : "CABIN COORDINATES"}
|
||||
</h4>
|
||||
<div className="space-y-4 text-xs text-white/50 font-semibold">
|
||||
<p>{t.mountainHelp} <br /> <span className="text-white/80">{t.mountainActive}</span></p>
|
||||
<p>Check-In/Out <br /> <span className="text-white/80">{lang === "tr" ? "Giriş: 16:00 · Çıkış: 10:00" : "Check In: 4:00 PM · Check Out: 10:00 AM"}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Services Column */}
|
||||
<div>
|
||||
<h4 className="font-serif-bunkhouse text-[#854D0E] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{t.vipServices}
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{hizmetler.map((h, hIdx) => {
|
||||
const locS = getLocalizedService(h.baslik, h.aciklama);
|
||||
return (
|
||||
<a
|
||||
key={hIdx}
|
||||
href="#host-details"
|
||||
className="block text-white/50 hover:text-[#854D0E] text-xs transition-colors font-semibold"
|
||||
>
|
||||
{locS.title}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs font-semibold">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-white transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── BOOKING MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/40 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-white rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-gray-100 text-[#1C1917]"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-[#F5F2EB] border border-gray-100 flex items-center justify-center text-[#1C1917]/40 hover:text-[#854D0E] hover:border-[#854D0E]/20 transition-all cursor-pointer font-bold"
|
||||
onClick={() => setShowModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
{/* Success check indicator */}
|
||||
<div className="w-16 h-16 rounded-2xl bg-[#854D0E]/10 border border-[#854D0E]/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-8 h-8 stroke-[#854D0E] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 className="font-serif-bunkhouse font-black text-[#1C1917] text-2xl mb-1 uppercase tracking-wider">
|
||||
{t.enquiryActive}
|
||||
</h3>
|
||||
<p className="text-[#854D0E] font-sans-bunkhouse text-[10px] mb-6 uppercase tracking-widest font-black">
|
||||
{t.ambassadorActive}
|
||||
</p>
|
||||
|
||||
<p className="text-[#1C1917]/60 text-xs leading-relaxed mb-8 font-semibold">
|
||||
{t.enquirySuccess}
|
||||
</p>
|
||||
|
||||
<motion.button
|
||||
className="w-full py-4.5 rounded-xl bg-[#854D0E] hover:bg-[#1C1917] text-white font-bold text-[9px] tracking-[2.5px] uppercase cursor-pointer shadow-md shadow-[#854D0E]/15"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowModal(false)}
|
||||
>
|
||||
{t.dismiss}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,750 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 35 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.65, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.08 } },
|
||||
};
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navIdeology: "Tasarım Felsefesi",
|
||||
navServices: "Seçkin Hizmetler",
|
||||
navPortfolio: "Portföyümüz",
|
||||
navEnquire: "Ziyaret Başvurusu",
|
||||
scheduleAccess: "Giriş Planla",
|
||||
badge: "MİNİMAL MONOLİTİK VİLLA",
|
||||
sloganTail: "BRÜT BETON ÇİZGİLERİYLE",
|
||||
heroDesc: "Bodrum Yalıkavak kıyılarında saf yapısal lüksü yaşayın. Brüt monolitik beton formlar, sıfır kenar taşmalı sonsuzluk havuzları ve akıllı ev ses sistemleriyle tasarlandı.",
|
||||
scheduleVisit: "ZİYARET PLANLA",
|
||||
estatePortfolio: "VİLLA PORTFÖYÜ",
|
||||
statTitle1: "PARAMETRE 1",
|
||||
statTitle2: "PARAMETRE 2",
|
||||
statTitle3: "PARAMETRE 3",
|
||||
privateAmenities: "Özel Ayrıcalıklar",
|
||||
bespokeServices: "SEÇKİN VİLLA HİZMETLERİ",
|
||||
secureRes: "GİRİŞ BAŞVURUSU YAP →",
|
||||
privilegedRequest: "Ayrıcalıklı Talep",
|
||||
enquirePrivate: "ZİYARET VE EMLAK BAŞVURUSU",
|
||||
formDesc: "Özel mimari koordinatörlerimizle iletişime geçerek yapılandırılmış villa gezilerini planlayın.",
|
||||
fieldsName: "İsim Soyisim",
|
||||
fieldsEmail: "E-Posta Adresi",
|
||||
fieldsPhone: "İletişim Numarası",
|
||||
fieldsProperty: "Mülk Kategorisi",
|
||||
fieldsNotes: "Özel istekler",
|
||||
fieldsNotesPlaceholder: "Helikopter pisti talepleri, kişisel güvenlik önlemleri...",
|
||||
dispatchForm: "GÜVENLİK FORMUNU GÖNDER",
|
||||
diaries: "Görüşler",
|
||||
trustedOwners: "MÜLK SAHİPLERİNİN GÜVENCESİ",
|
||||
vipCoords: "VIP KOORDİNATLAR",
|
||||
securityHours: "Güvenlik Birimi",
|
||||
securityActive: "24 Saat Kesintisiz Aktif",
|
||||
heliport: "Özel Helikopter Pisti",
|
||||
heliportActive: "Otomatik rötar senkronizasyonu",
|
||||
estateServices: "VİLLA HİZMETLERİ",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Brüt Beton Koşulları",
|
||||
dismiss: "KAPAT",
|
||||
enquiryActive: "ZİYARET ONAYLANDI",
|
||||
ambassadorActive: "Güvenlik Doğrulaması Başlatıldı",
|
||||
enquirySuccess: "Yalıkavak brüt beton villa gezi talebinizi kaydettik. Güvenlik doğrulama koordinatörümüz, giriş detaylarını onaylamak için en kısa sürede sizinle iletişime geçecektir. Teşekkürler!",
|
||||
},
|
||||
en: {
|
||||
navIdeology: "Design ideology",
|
||||
navServices: "Bespoke services",
|
||||
navPortfolio: "Bento portfolio",
|
||||
navEnquire: "Enquire access",
|
||||
scheduleAccess: "Schedule Access",
|
||||
badge: "MINIMAL MONOLITHIC VILLA",
|
||||
sloganTail: "WITH CONCRETE LINES",
|
||||
heroDesc: "Indulge in sheer structural luxury at Bodrum Yalıkavak coast lines. Designed with raw monolithic architectural concrete forms, zero-edge pools, and smart voice systems.",
|
||||
scheduleVisit: "SCHEDULE VISIT",
|
||||
estatePortfolio: "ESTATE PORTFOLIO",
|
||||
statTitle1: "PARAMETER 1",
|
||||
statTitle2: "PARAMETER 2",
|
||||
statTitle3: "PARAMETER 3",
|
||||
privateAmenities: "Private Amenities",
|
||||
bespokeServices: "BESPOKE VILLA SERVICES",
|
||||
secureRes: "ENQUIRE ACCESS →",
|
||||
privilegedRequest: "Privileged Request",
|
||||
enquirePrivate: "ENQUIRE PRIVATE ACCESS",
|
||||
formDesc: "Connect with our somatic architectural coordinators to schedule structured property walkthroughs.",
|
||||
fieldsName: "Name",
|
||||
fieldsEmail: "Email",
|
||||
fieldsPhone: "Phone",
|
||||
fieldsProperty: "Property Category",
|
||||
fieldsNotes: "Special details",
|
||||
fieldsNotesPlaceholder: "Helipad requirements, personalized security levels...",
|
||||
dispatchForm: "DISPATCH SECURITY FORM",
|
||||
diaries: "Sommelier Reviews",
|
||||
trustedOwners: "TRUSTED BY OWNERS",
|
||||
vipCoords: "VIP COORDINATES",
|
||||
securityHours: "Security Hours",
|
||||
securityActive: "Active 24 Hours",
|
||||
heliport: "Lounge Heliport",
|
||||
heliportActive: "Automated delay syncing",
|
||||
estateServices: "ESTATE SERVICES",
|
||||
privacyRegs: "Privacy Regulations",
|
||||
termsStay: "Terms of Concrete",
|
||||
dismiss: "DISMISS",
|
||||
enquiryActive: "VISIT GRANTED",
|
||||
ambassadorActive: "Security Clearing Initiated",
|
||||
enquirySuccess: "We have registered your executive Yalıkavak concrete villa walkthrough request. A security clearance coordinator will contact you shortly to authorize access parameters. Thank you!",
|
||||
}
|
||||
};
|
||||
|
||||
export default function HotelTemplate3({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], yorumlar = [] } = data;
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// 1. Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// 2. Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Localized statistics
|
||||
const getLocalizedStat = (deger: string, etiket: string) => {
|
||||
if (deger.includes("Concrete")) {
|
||||
return {
|
||||
deger: lang === "tr" ? "Brüt Beton" : "Concrete",
|
||||
etiket: lang === "tr" ? "Tik ağacı zemin kaplamaları ile birleştirilmiş brüt monolitik beton formlar." : etiket
|
||||
};
|
||||
}
|
||||
if (deger.includes("Smart")) {
|
||||
return {
|
||||
deger: lang === "tr" ? "Akıllı Konut" : "Smart Estate",
|
||||
etiket: lang === "tr" ? "Tam entegre ses arayüzleri, otomatik havalandırma ve yedek güneş enerjisi." : etiket
|
||||
};
|
||||
}
|
||||
return {
|
||||
deger: lang === "tr" ? "Deniz Manzarası" : "Sea View",
|
||||
etiket: lang === "tr" ? "Yerden tavana kadar kesintisiz cam panellerle tasarlanmış konsol yatak odaları." : etiket
|
||||
};
|
||||
};
|
||||
|
||||
// Localized services
|
||||
const getLocalizedService = (baslik: string, aciklama: string) => {
|
||||
if (baslik.includes("ARCHITECTURAL")) {
|
||||
return {
|
||||
title: lang === "tr" ? "MİMARİ TURLAR" : "ARCHITECTURAL TOURS",
|
||||
desc: lang === "tr" ? "Karbon yapılar, brüt beton dokular ve taşmalı havuzları gösteren özel emlak turları." : aciklama
|
||||
};
|
||||
}
|
||||
if (baslik.includes("MASTERCLASSES")) {
|
||||
return {
|
||||
title: lang === "tr" ? "TASARIM EĞİTİMLERİ" : "DESIGN MASTERCLASSES",
|
||||
desc: lang === "tr" ? "Minimalist yaşam, özel mobilya yerleşimi ve sürdürülebilir brüt beton tasarımı atölyelerimiz." : aciklama
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: lang === "tr" ? "ÖZEL LÜKS VİLLA" : "EXECUTIVE LUXURY VILLA",
|
||||
desc: lang === "tr" ? "Kişisel sommelier desteği, otomatik helikopter pisti ve üst düzey güvenlik ile tam mülk kiralama." : aciklama
|
||||
};
|
||||
};
|
||||
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
||||
|
||||
:root {
|
||||
--color-apex-emerald: #059669;
|
||||
--color-apex-slate: #09090C;
|
||||
--color-apex-card: #14141A;
|
||||
--color-apex-white: #FAF8F5;
|
||||
--color-apex-muted: rgba(250, 248, 245, 0.5);
|
||||
}
|
||||
|
||||
.font-apex-heading {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
|
||||
.font-sans-apex {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.bg-apex-mesh {
|
||||
background-image:
|
||||
radial-gradient(circle at 10% 20%, rgba(5, 150, 105, 0.04) 0%, transparent 45%),
|
||||
radial-gradient(circle at 90% 80%, rgba(250, 248, 245, 0.01) 0%, transparent 50%),
|
||||
linear-gradient(rgba(255, 255, 255, 0.005) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(255, 255, 255, 0.005) 1px, transparent 1px);
|
||||
background-size: 100% 100%, 100% 100%, 40px 40px, 40px 40px;
|
||||
}
|
||||
|
||||
.emerald-glow {
|
||||
box-shadow: 0 0 25px rgba(5, 150, 105, 0.15);
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(34px, 5.5vw, 85px);
|
||||
line-height: 0.95;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#09090C] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-black tracking-[4px] uppercase text-[#059669] block font-sans-apex"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
APEX ARC MONOLITHIC
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#059669]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-apex-heading text-white text-lg font-light tracking-wider"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
brutalist villa estate
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
{/* SLEEK BRUTALIST ARCHITECTURAL ESTATE THEME */}
|
||||
<div className="bg-[#09090C] text-[#FAF8F5] min-h-screen font-sans-apex selection:bg-[#059669] selection:text-white overflow-hidden relative bg-apex-mesh pb-24">
|
||||
|
||||
{/* Floating Ambient Emerald Orbs */}
|
||||
<div className="absolute top-[15%] left-[-15%] w-[600px] h-[600px] bg-[#059669]/4 blur-[130px] rounded-full pointer-events-none z-0" />
|
||||
<div className="absolute bottom-[20%] right-[-15%] w-[600px] h-[600px] bg-[#FAF8F5]/1 blur-[140px] rounded-full pointer-events-none z-0" />
|
||||
|
||||
{/* ── MANDATORY FLOATING DEMO BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#14141A]/95 backdrop-blur-md border border-white/5 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#059669] animate-pulse" />
|
||||
<span className="text-[9px] font-black uppercase tracking-[1.5px] text-white/90">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{/* ── HIGH CONTRAST SLATE NAVBAR ── */}
|
||||
<motion.header
|
||||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||||
initial={{ y: -80, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.7, ease: "easeOut" }}
|
||||
>
|
||||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-[#14141A]/95 backdrop-blur-xl border border-white/5 rounded-2xl shadow-[0_15px_30px_rgba(0,0,0,0.5)]">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2 group">
|
||||
<span className="text-xl font-bold tracking-[1.5px] text-white font-apex-heading flex items-center gap-2.5 uppercase">
|
||||
<svg className="w-5 h-5 text-[#059669]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" />
|
||||
<path d="M9 3v18" />
|
||||
<path d="M15 3v18" />
|
||||
<path d="M3 9h18" />
|
||||
<path d="M3 15h18" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Links */}
|
||||
<nav className="hidden lg:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navIdeology, href: "#ideology" },
|
||||
{ label: t.navServices, href: "#services" },
|
||||
{ label: t.navPortfolio, href: "#portfolio" },
|
||||
{ label: t.navEnquire, href: "#booking-flow" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[10px] font-black tracking-[2px] uppercase text-[#FAF8F5]/70 hover:text-[#059669] transition-colors relative py-1 cursor-pointer group"
|
||||
>
|
||||
{item.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#059669] transition-all group-hover:w-full" />
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Language Selector + Booking Button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-white/5 border border-white/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-white text-slate-900 shadow-sm" : "text-white/60 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-white text-slate-900 shadow-sm" : "text-white/60 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="text-[10px] font-black tracking-[2.5px] uppercase text-white bg-[#059669] hover:bg-white hover:text-black px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_5px_15px_rgba(5,150,105,0.2)] hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.scheduleAccess}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── ARCHITECTURAL HERO BANNER ── */}
|
||||
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||||
|
||||
{/* Left Column: Heading and Brutalist descriptions */}
|
||||
<motion.div
|
||||
className="lg:col-span-7 z-20"
|
||||
variants={stagger}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="inline-flex items-center gap-2 text-[10px] font-black uppercase tracking-widest text-[#059669] mb-6 bg-[#059669]/10 border border-[#059669]/20 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#059669]" />
|
||||
{t.badge}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={fadeUp}
|
||||
className="font-apex-heading text-white leading-[0.95] tracking-tight mb-8 uppercase hero-title-clamp"
|
||||
>
|
||||
{firma.slogan}
|
||||
<br />
|
||||
<span className="text-[#059669]">{t.sloganTail}</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-[#FAF8F5]/60 text-xs lg:text-sm leading-relaxed max-w-xl mb-12 font-medium"
|
||||
>
|
||||
{t.heroDesc}
|
||||
</motion.p>
|
||||
|
||||
{/* Quick actions */}
|
||||
<motion.div variants={fadeUp} className="flex gap-4">
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="px-8 py-4 rounded-xl bg-[#059669] hover:bg-white hover:text-[#09090C] text-white font-black text-[10px] tracking-[2px] uppercase transition-all shadow-[0_5px_15px_rgba(5,150,105,0.25)] cursor-pointer"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
>
|
||||
{t.scheduleVisit}
|
||||
</motion.button>
|
||||
<a
|
||||
href="#portfolio"
|
||||
className="px-8 py-4 rounded-xl border border-white/10 bg-white/5 hover:bg-white/10 text-white font-black text-[10px] tracking-[2px] uppercase transition-all cursor-pointer text-center"
|
||||
>
|
||||
{t.estatePortfolio}
|
||||
</a>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: High-fidelity image (brutalist fireplace oven) */}
|
||||
<div className="lg:col-span-5 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-md lg:max-w-lg h-[430px] lg:h-[510px] rounded-3xl overflow-hidden shadow-2xl border border-white/5 group"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
>
|
||||
{/* Raw concrete fireplace oven representing structural concrete warmth */}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/sicilia_wood_oven.png"
|
||||
alt="Apex Arc Monolithic Architectural Fireplace"
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-[4000ms]"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-50" />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── IDEOLOGY STATISTICS BLOCK ── */}
|
||||
<section id="ideology" className="py-24 relative z-10 px-6 bg-[#14141A]/60 border-y border-white/5">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{istatistikler.map((stat, idx) => {
|
||||
const locStat = getLocalizedStat(stat.deger, stat.etiket);
|
||||
return (
|
||||
<div
|
||||
key={idx}
|
||||
className="bg-[#14141A] p-8 rounded-3xl border border-white/5 flex flex-col justify-between h-48 transition-all hover:border-[#059669]/30"
|
||||
>
|
||||
<span className="text-[10px] font-black tracking-[3px] text-[#059669] uppercase block mb-2">{idx === 0 ? t.statTitle1 : idx === 1 ? t.statTitle2 : t.statTitle3}</span>
|
||||
<h3 className="font-apex-heading text-2xl font-bold uppercase text-white tracking-wider">
|
||||
{locStat.deger}
|
||||
</h3>
|
||||
<p className="text-[#FAF8F5]/50 text-[10px] font-semibold leading-relaxed">
|
||||
{locStat.etiket}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── BESPOKE SERVICES ── */}
|
||||
<section id="services" className="py-28 relative z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#059669] font-apex-heading text-xs uppercase tracking-widest block mb-2">{t.privateAmenities}</span>
|
||||
<h2 className="font-apex-heading text-3xl lg:text-4xl font-bold uppercase text-white">
|
||||
{t.bespokeServices}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Bento services grid */}
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
{hizmetler.map((hizmet, idx) => {
|
||||
const locServ = getLocalizedService(hizmet.baslik, hizmet.aciklama);
|
||||
return (
|
||||
<motion.div
|
||||
key={idx}
|
||||
className="bg-[#14141A] rounded-3xl border border-white/5 overflow-hidden transition-all duration-300 hover:border-[#059669]/30 flex flex-col justify-between group shadow-sm"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: idx * 0.1 }}
|
||||
whileHover={{ y: -4 }}
|
||||
>
|
||||
{/* Cover image using dark upscale culinary smoke or organic lemon */}
|
||||
<div className="h-44 overflow-hidden relative border-b border-white/5">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={idx === 0 ? "/sicilia_wood_oven.png" : idx === 1 ? "/chef_plating_smoke.png" : "/sicilia_lemon_heritage.png"}
|
||||
alt={hizmet.baslik}
|
||||
className="w-full h-full object-cover scale-102 group-hover:scale-105 transition-transform duration-1000"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/40" />
|
||||
</div>
|
||||
|
||||
<div className="p-8 space-y-4">
|
||||
<h3 className="font-apex-heading font-bold text-lg text-white tracking-wider uppercase leading-snug">
|
||||
{locServ.title}
|
||||
</h3>
|
||||
<p className="text-[#FAF8F5]/50 text-[11px] leading-relaxed font-semibold">
|
||||
{locServ.desc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="px-8 pb-8">
|
||||
<button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="text-[#059669] group-hover:text-white transition-colors text-[10px] font-black tracking-[2px] uppercase flex items-center gap-1.5 cursor-pointer"
|
||||
>
|
||||
{t.secureRes}
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── RESERVATION FLOW ── */}
|
||||
<section id="booking-flow" className="py-24 relative z-10 px-6 border-t border-white/5 bg-[#14141A]/40">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
|
||||
<div className="bg-[#14141A] rounded-3xl p-8 md:p-12 shadow-2xl border border-white/5 relative">
|
||||
<div className="absolute top-0 left-12 right-12 h-0.5 bg-gradient-to-r from-transparent via-[#059669] to-transparent glowing-bar" />
|
||||
|
||||
<div className="text-center mb-10">
|
||||
<span className="text-[#059669] font-apex-heading text-xs uppercase tracking-widest block mb-2">{t.privilegedRequest}</span>
|
||||
<h2 className="font-apex-heading text-3xl md:text-4xl font-bold uppercase text-white">
|
||||
{t.enquirePrivate}
|
||||
</h2>
|
||||
<p className="text-[#FAF8F5]/40 text-xs mt-2 font-medium">
|
||||
{t.formDesc}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-5">
|
||||
{[
|
||||
{ label: t.fieldsName, placeholder: lang === "tr" ? "Adınız Soyadınız" : "Your Name", type: "text", full: false },
|
||||
{ label: t.fieldsEmail, placeholder: "you@company.com", type: "email", full: false },
|
||||
{ label: t.fieldsPhone, placeholder: lang === "tr" ? "İrtibat Numarası" : "Contact Number", type: "tel", full: false },
|
||||
{ label: t.fieldsProperty, placeholder: lang === "tr" ? "Yalıkavak Beton Villa" : "Yalıkavak Concrete Villa", type: "text", full: false },
|
||||
{ label: t.fieldsNotes, placeholder: t.fieldsNotesPlaceholder, type: "text", full: true },
|
||||
].map((field, idx) => (
|
||||
<div key={idx} className={field.full ? "col-span-2" : "col-span-1"}>
|
||||
<label className="block text-[10px] font-black text-[#FAF8F5]/50 mb-1.5 uppercase tracking-widest">{field.label}</label>
|
||||
<input
|
||||
type={field.type}
|
||||
placeholder={field.placeholder}
|
||||
className="w-full px-4 py-3.5 rounded-xl border border-white/5 bg-[#09090C] text-xs text-white placeholder-white/20 focus:outline-none focus:border-[#059669] focus:ring-1 focus:ring-[#059669] transition-all font-semibold"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowModal(true)}
|
||||
className="mt-8 w-full py-4 rounded-xl bg-[#059669] hover:bg-white hover:text-[#09090C] text-white font-bold text-[10px] tracking-[2.5px] uppercase transition-colors cursor-pointer"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.dispatchForm}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── TESTIMONIALS ── */}
|
||||
<section id="testimonials" className="py-28 relative z-10 px-6 border-t border-white/5">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="text-center max-w-xl mx-auto mb-20">
|
||||
<span className="text-[#059669] font-apex-heading text-xs uppercase tracking-widest block mb-2">{t.diaries}</span>
|
||||
<h2 className="font-apex-heading text-3xl lg:text-4xl font-bold uppercase text-white">
|
||||
{t.trustedOwners}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Testimonials */}
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{yorumlar.map((y, yIdx) => (
|
||||
<motion.div
|
||||
key={yIdx}
|
||||
className="bg-[#14141A] border border-white/5 rounded-3xl p-8 flex flex-col justify-between transition-all duration-300 hover:border-[#059669]/30 group"
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: yIdx * 0.1 }}
|
||||
whileHover={{ y: -4 }}
|
||||
>
|
||||
<div className="flex gap-1.5 mb-6">
|
||||
{[...Array(5)].map((_, starIdx) => (
|
||||
<svg key={starIdx} className="w-4 h-4 fill-[#059669]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="text-[#FAF8F5]/70 text-xs leading-relaxed italic mb-8 font-medium font-serif-bunkhouse">
|
||||
“{y.yorum}”
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full border border-white/10 flex items-center justify-center text-lg bg-[#09090C] select-none font-bold">
|
||||
{y.yazar.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-apex-heading text-white text-xs font-black uppercase tracking-wider">
|
||||
{y.yazar}
|
||||
</h4>
|
||||
<span className="text-[9px] text-[#FAF8F5]/40 uppercase tracking-widest font-black">
|
||||
{y.tarih}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-[#14141A] border-t border-white/5 pt-24 pb-8 px-6 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
|
||||
|
||||
{/* About Column */}
|
||||
<div className="md:col-span-2">
|
||||
<span className="font-apex-heading text-2xl font-black text-white tracking-wider uppercase mb-4 block">
|
||||
Apex<span className="text-[#059669]">Arc</span>
|
||||
</span>
|
||||
<p className="text-[#FAF8F5]/50 text-xs leading-relaxed max-w-sm mb-8 font-medium">
|
||||
{firma.slogan} — Monolithic concrete-Teak luxury estates looking over Muğla coastlines. High-end voice smart interfaces.
|
||||
</p>
|
||||
<div className="text-[#FAF8F5]/60 text-xs font-medium space-y-3">
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#059669] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
</svg>
|
||||
<span className="text-[#FAF8F5]/80">{firma.adres}</span>
|
||||
</p>
|
||||
<p className="flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-[#059669] shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||
<rect width="20" height="16" x="2" y="4" rx="2" />
|
||||
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" />
|
||||
</svg>
|
||||
<span className="text-[#FAF8F5]/80">{firma.email}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Coordinates Column */}
|
||||
<div>
|
||||
<h4 className="font-apex-heading text-[#059669] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{t.vipCoords}
|
||||
</h4>
|
||||
<div className="space-y-4 text-xs text-[#FAF8F5]/50 font-semibold">
|
||||
<p>{t.securityHours} <br /> <span className="text-white/80">{t.securityActive}</span></p>
|
||||
<p>{t.heliport} <br /> <span className="text-white/80">{t.heliportActive}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Services Column */}
|
||||
<div>
|
||||
<h4 className="font-apex-heading text-[#059669] text-xs font-black uppercase tracking-wider mb-6">
|
||||
{t.estateServices}
|
||||
</h4>
|
||||
<div className="space-y-4">
|
||||
{hizmetler.map((h, hIdx) => {
|
||||
const locS = getLocalizedService(h.baslik, h.aciklama);
|
||||
return (
|
||||
<a
|
||||
key={hIdx}
|
||||
href="#services"
|
||||
className="block text-[#FAF8F5]/50 hover:text-[#059669] text-xs transition-colors font-semibold"
|
||||
>
|
||||
{locS.title}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-[#FAF8F5]/30 text-xs font-semibold">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-white transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── ENQUIRY MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/80 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-[#14141A] rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-[#059669]/20 text-white"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-[#09090C] border border-white/5 flex items-center justify-center text-white/40 hover:text-[#059669] hover:border-[#059669]/20 transition-all cursor-pointer font-bold"
|
||||
onClick={() => setShowModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
{/* Success check indicator */}
|
||||
<div className="w-16 h-16 rounded-2xl bg-[#059669]/10 border border-[#059669]/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-8 h-8 stroke-[#059669] fill-none" viewBox="0 0 24 24" strokeWidth="1.5">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h3 className="font-apex-heading font-black text-white text-2xl mb-1 uppercase tracking-wider">
|
||||
{t.enquiryActive}
|
||||
</h3>
|
||||
<p className="text-[#059669] font-sans-apex text-[10px] mb-6 uppercase tracking-widest font-black">
|
||||
{t.ambassadorActive}
|
||||
</p>
|
||||
|
||||
<p className="text-[#FAF8F5]/60 text-xs leading-relaxed mb-8 font-semibold">
|
||||
{t.enquirySuccess}
|
||||
</p>
|
||||
|
||||
<motion.button
|
||||
className="w-full py-4.5 rounded-xl bg-[#059669] hover:bg-black hover:text-white text-white font-bold text-[9px] tracking-[2.5px] uppercase cursor-pointer shadow-md shadow-[#059669]/15"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowModal(false)}
|
||||
>
|
||||
{t.dismiss}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,945 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 35 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.75, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.1 } },
|
||||
};
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navServices: "Hizmetlerimiz",
|
||||
navDoctors: "Uzman Kadromuz",
|
||||
navReviews: "Hasta Yorumları",
|
||||
navContact: "İletişim",
|
||||
navBooking: "Randevu Al",
|
||||
badge: "GÜVENİLİR SAĞLIK MERKEZİ",
|
||||
heroTitlePart1: "Sağlığınız İçin",
|
||||
heroTitlePart2: "En İyi Ellerde",
|
||||
heroTitlePart3: "Olun",
|
||||
heroDesc: "Uzman hekim kadromuz, modern tıbbi donanımımız ve kişiye özel tedavi yaklaşımlarımızla sağlığınızı korumak için buradayız. Doğan Tıp Merkezi güvenilir koordinatları.",
|
||||
appointmentsToday: "Bugünkü Randevular",
|
||||
saturday: "Cumartesi, 28 Mayıs 2026",
|
||||
appointmentList: [
|
||||
{ saat: "09:30", tip: "Genel Muayene", dolu: true },
|
||||
{ saat: "11:00", tip: "Check-Up Kontrolü", dolu: false },
|
||||
{ saat: "13:30", tip: "Kardiyoloji Muayenesi", dolu: true },
|
||||
{ saat: "15:00", tip: "Göz Muayenesi", dolu: false },
|
||||
],
|
||||
statusDolu: "Dolu",
|
||||
statusMusait: "Müsait",
|
||||
ratingText: "4.9 / 5 • 620+ Hasta Değerlendirmesi",
|
||||
smsReminder: "SMS Hatırlatma",
|
||||
smsDesc: "Randevularınızı asla kaçırmayın",
|
||||
servicesTitle: "Hizmetlerimiz",
|
||||
servicesHeader: "UZMAN KADROMUZLA HER ALANDA YANINIZDAYIZ",
|
||||
learnMore: "Detaylı Bilgi →",
|
||||
doctorsTitle: "Ekibimiz",
|
||||
doctorsHeader: "ALANINDA UZMAN DOKTORLARIMIZ",
|
||||
yearsExp: "Yıl Deneyim",
|
||||
patientsTreated: "Hasta Tedavisi",
|
||||
bookingTitle: "Online Randevu",
|
||||
bookingHeader: "HEMEN RANDEVU OLUŞTURUN",
|
||||
bookingDesc: "Formu doldurun, randevu koordinatörümüz sizi 15 dakika içinde arayıp gününüzü kesinleştirsin.",
|
||||
fieldsName: "Ad Soyad",
|
||||
fieldsPhone: "Telefon Numarası",
|
||||
fieldsEmail: "E-Posta Adresi",
|
||||
fieldsDepartment: "Bölüm / Klinik",
|
||||
fieldsDate: "Randevu Tarihi",
|
||||
fieldsNotes: "Notunuz / Şikayetiniz",
|
||||
fieldsNotesPlaceholder: "Belirtmek istediğiniz tıbbi şikayetler veya özel notlar...",
|
||||
dispatchForm: "RANDEVU TALEP ET",
|
||||
contactDetails: "İLETİŞİM BİLGİLERİMİZ",
|
||||
callCenter: "7/24 Çağrı Merkezi",
|
||||
addressLabel: "Klinik Adresi",
|
||||
emailLabel: "E-Posta",
|
||||
footerDesc: "İleri tanı ve tedavi yöntemleri, hasta odaklı hizmet anlayışı ve seçkin hekim kadrosuyla sağlığınız için en güvenilir koordinat.",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Kullanım Şartları",
|
||||
dismiss: "KAPAT",
|
||||
contactTitle: "Hızlı Danışma",
|
||||
contactDesc: "İletişim bilgilerinizi bırakın, tıbbi danışmanımız sizi hemen arasın.",
|
||||
submit: "Gönder",
|
||||
serviceDahiliye: "Dahiliye",
|
||||
serviceDahiliyeDesc: "Erişkin hastalıklarında kapsamlı tanı ve tedavi hizmetleri.",
|
||||
serviceKardiyoloji: "Kardiyoloji",
|
||||
serviceKardiyolojiDesc: "Kalp ve damar sağlığı için ileri tanı ve tedavi yöntemleri.",
|
||||
serviceDis: "Diş Hekimliği",
|
||||
serviceDisDesc: "İmplant, ortodonti ve estetik gülüş tasarımı uygulamaları.",
|
||||
serviceGoz: "Göz Sağlığı",
|
||||
serviceGozDesc: "Lazer tedavileri, katarakt ve mikro cerrahi operasyonları.",
|
||||
serviceLab: "Laboratuvar",
|
||||
serviceLabDesc: "Hızlı, güvenilir ve tam kapsamlı tahlil sonuçları.",
|
||||
serviceRad: "Radyoloji",
|
||||
serviceRadDesc: "MR, bilgisayarlı tomografi ve ileri ultrason görüntüleme.",
|
||||
},
|
||||
en: {
|
||||
navServices: "Our Services",
|
||||
navDoctors: "Our Doctors",
|
||||
navReviews: "Testimonials",
|
||||
navContact: "Contact",
|
||||
navBooking: "Book Appointment",
|
||||
badge: "TRUSTED MEDICAL CENTER",
|
||||
heroTitlePart1: "Your Health",
|
||||
heroTitlePart2: "In The Safest Hands",
|
||||
heroTitlePart3: "Always",
|
||||
heroDesc: "We protect your health with our expert physicians, state-of-the-art diagnostic systems, and customized treatment plans. Trusted coordinates of Doğan Medical Center.",
|
||||
appointmentsToday: "Today's Schedule",
|
||||
saturday: "Saturday, May 28, 2026",
|
||||
appointmentList: [
|
||||
{ saat: "09:30", tip: "General Checkup", dolu: true },
|
||||
{ saat: "11:00", tip: "Prevention Review", dolu: false },
|
||||
{ saat: "13:30", tip: "Cardiology Consult", dolu: true },
|
||||
{ saat: "15:00", tip: "Ophthalmology Exam", dolu: false },
|
||||
],
|
||||
statusDolu: "Booked",
|
||||
statusMusait: "Available",
|
||||
ratingText: "4.9 / 5 • 620+ Patient Feedbacks",
|
||||
smsReminder: "SMS Reminder",
|
||||
smsDesc: "Never miss your medical checks",
|
||||
servicesTitle: "Our Services",
|
||||
servicesHeader: "COMPREHENSIVE MEDICAL CARE IN EVERY SPECIALTY",
|
||||
learnMore: "Learn More →",
|
||||
doctorsTitle: "Our Team",
|
||||
doctorsHeader: "MEET OUR ACCOMPLISHED PHYSICIANS",
|
||||
yearsExp: "Years Experience",
|
||||
patientsTreated: "Patients Treated",
|
||||
bookingTitle: "Online Booking",
|
||||
bookingHeader: "SCHEDULE A MEDICAL APPOINTMENT",
|
||||
bookingDesc: "Fill in the details and our patient representative will call you back within 15 minutes to lock your slot.",
|
||||
fieldsName: "Full Name",
|
||||
fieldsPhone: "Phone Number",
|
||||
fieldsEmail: "Email Address",
|
||||
fieldsDepartment: "Specialty / Department",
|
||||
fieldsDate: "Preferred Date",
|
||||
fieldsNotes: "Symptoms / Clinical Notes",
|
||||
fieldsNotesPlaceholder: "Briefly describe your symptoms or specific notes for the doctor...",
|
||||
dispatchForm: "REQUEST APPOINTMENT",
|
||||
contactDetails: "CONTACT CHANNELS",
|
||||
callCenter: "24/7 Call Center",
|
||||
addressLabel: "Clinic Coordinates",
|
||||
emailLabel: "Support Email",
|
||||
footerDesc: "Trusted medical hub offering comprehensive diagnosis and advanced therapy protocols utilizing the latest patient care systems.",
|
||||
privacyRegs: "Privacy Policy",
|
||||
termsStay: "Terms of Service",
|
||||
dismiss: "DISMISS",
|
||||
contactTitle: "Quick Consultation",
|
||||
contactDesc: "Leave your contact coordinates and our medical coordinator will call you back shortly.",
|
||||
submit: "Submit",
|
||||
serviceDahiliye: "Internal Medicine",
|
||||
serviceDahiliyeDesc: "Comprehensive diagnostics and advanced therapies for adult diseases.",
|
||||
serviceKardiyoloji: "Cardiology",
|
||||
serviceKardiyolojiDesc: "Advanced diagnostics and treatment plans for cardiovascular wellness.",
|
||||
serviceDis: "Dentistry",
|
||||
serviceDisDesc: "Modern implants, clear aligners, and aesthetic smile design applications.",
|
||||
serviceGoz: "Ophthalmology",
|
||||
serviceGozDesc: "State-of-the-art laser corrections, cataract surgeries, and microsurgery.",
|
||||
serviceLab: "Medical Laboratory",
|
||||
serviceLabDesc: "Ultra-fast, certified, and fully automated biological analysis protocols.",
|
||||
serviceRad: "Advanced Radiology",
|
||||
serviceRadDesc: "High-resolution MRI, computerized tomography, and diagnostic ultrasound.",
|
||||
}
|
||||
};
|
||||
|
||||
export default function KlinikTemplate({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], doktorlar = [], yorumlar = [] } = data;
|
||||
const [showBookingModal, setShowBookingModal] = useState(false);
|
||||
const [activeYorum, setActiveYorum] = useState(0);
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (x: number) => Math.min(1, 1.001 - Math.pow(2, -10 * x)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Localized statistics labels
|
||||
const getLocalizedStatLabel = (deger: string) => {
|
||||
if (deger === "4200") return lang === "tr" ? "Mutlu Hasta" : "Happy Patients";
|
||||
if (deger === "14") return lang === "tr" ? "Uzman Hekim" : "Expert Physicians";
|
||||
if (deger === "12") return lang === "tr" ? "Yıl Deneyim" : "Years of Experience";
|
||||
return lang === "tr" ? "Hasta Yorumu" : "Patient Reviews";
|
||||
};
|
||||
|
||||
// Maps services text based on data
|
||||
const getLocalizedServiceText = (baslik: string) => {
|
||||
if (baslik.includes("Dahiliye")) return { title: t.serviceDahiliye, desc: t.serviceDahiliyeDesc };
|
||||
if (baslik.includes("Kardiyoloji")) return { title: t.serviceKardiyoloji, desc: t.serviceKardiyolojiDesc };
|
||||
if (baslik.includes("Diş")) return { title: t.serviceDis, desc: t.serviceDisDesc };
|
||||
if (baslik.includes("Göz")) return { title: t.serviceGoz, desc: t.serviceGozDesc };
|
||||
if (baslik.includes("Laboratuvar")) return { title: t.serviceLab, desc: t.serviceLabDesc };
|
||||
return { title: t.serviceRad, desc: t.serviceRadDesc };
|
||||
};
|
||||
|
||||
// Maps service icons
|
||||
const getServiceIconSvg = (baslik: string) => {
|
||||
if (baslik.includes("Dahiliye")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#0ea5e9] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("Kardiyoloji")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#0ea5e9] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("Diş")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#0ea5e9] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9s2.015-9 4.5-9" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("Göz")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#0ea5e9] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("Laboratuvar")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#0ea5e9] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#0ea5e9] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z" />
|
||||
<circle cx="12" cy="13" r="3" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const getLocalizedDoctor = (ad: string) => {
|
||||
if (ad.includes("Ahmet")) {
|
||||
return {
|
||||
name: lang === "tr" ? "Dr. Ahmet Yılmaz" : "Dr. Ahmet Yilmaz",
|
||||
title: lang === "tr" ? "Dahiliye Uzmanı" : "Internal Medicine Specialist",
|
||||
};
|
||||
}
|
||||
if (ad.includes("Ayşe")) {
|
||||
return {
|
||||
name: lang === "tr" ? "Dr. Ayşe Kaya" : "Dr. Ayse Kaya",
|
||||
title: lang === "tr" ? "Kardiyolog" : "Cardiologist",
|
||||
};
|
||||
}
|
||||
if (ad.includes("Mehmet")) {
|
||||
return {
|
||||
name: lang === "tr" ? "Dr. Mehmet Demir" : "Dr. Mehmet Demir",
|
||||
title: lang === "tr" ? "Göz Sağlığı Uzmanı" : "Ophthalmology Specialist",
|
||||
};
|
||||
}
|
||||
return {
|
||||
name: lang === "tr" ? "Dr. Zeynep Arslan" : "Dr. Zeynep Arslan",
|
||||
title: lang === "tr" ? "Estetik Diş Hekimi" : "Aesthetic Dentist",
|
||||
};
|
||||
};
|
||||
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700;800;900&family=Sora:wght@300;400;500;600;700;800&display=swap');
|
||||
|
||||
:root {
|
||||
--color-klinik-sky: #0ea5e9;
|
||||
--color-klinik-sky-dark: #0284c7;
|
||||
--color-klinik-sky-light: #e0f2fe;
|
||||
--color-klinik-charcoal: #0F172A;
|
||||
--color-klinik-sand: #FAF8F5;
|
||||
}
|
||||
|
||||
.font-sora-editorial {
|
||||
font-family: 'Sora', sans-serif;
|
||||
}
|
||||
|
||||
.font-sans-clean {
|
||||
font-family: 'DM Sans', sans-serif;
|
||||
}
|
||||
|
||||
.shadow-premium {
|
||||
box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(38px, 6vw, 85px);
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 0.95;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#0F172A] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-sora-editorial tracking-[4px] uppercase text-[#0ea5e9] block"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
DOĞAN TIP MERKEZİ
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#0ea5e9]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-sora-editorial text-white/50 text-xs tracking-wider uppercase"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
interactive prototype
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<div className="bg-[#FAF8F5] text-[#0F172A] min-h-screen font-sans-clean selection:bg-[#0ea5e9] selection:text-white overflow-hidden relative pb-20">
|
||||
|
||||
{/* Floating Ambient Orbs */}
|
||||
<div className="absolute top-[10%] left-[-15%] w-[600px] h-[600px] bg-[#0ea5e9]/3 blur-[120px] rounded-full pointer-events-none z-0" />
|
||||
<div className="absolute bottom-[20%] right-[-15%] w-[600px] h-[600px] bg-[#0284c7]/3 blur-[140px] rounded-full pointer-events-none z-0" />
|
||||
|
||||
{/* ── FLOATING CONCEPT BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#0F172A]/90 backdrop-blur-md border border-white/10 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#0ea5e9] animate-pulse" />
|
||||
<span className="text-[9px] font-sora-editorial uppercase tracking-[1.5px] text-white/90">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* ── PREMIUM NAVBAR ── */}
|
||||
<motion.header
|
||||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||||
initial={{ y: -80, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.85, ease: [0.16, 1, 0.3, 1] }}
|
||||
>
|
||||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-white/80 backdrop-blur-xl border border-white/40 rounded-2xl shadow-[0_10px_30px_rgba(15,23,42,0.03)]">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2.5 group">
|
||||
<span className="text-lg font-black tracking-tight text-[#0F172A] font-sora-editorial flex items-center gap-2.5 uppercase">
|
||||
<svg className="w-5 h-5 text-[#0ea5e9]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" />
|
||||
<path d="M12 6v12M6 12h12" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Links */}
|
||||
<nav className="hidden lg:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navServices, href: "#hizmetler" },
|
||||
{ label: t.navDoctors, href: "#doktorlar" },
|
||||
{ label: t.navReviews, href: "#testimonials" },
|
||||
{ label: t.navContact, href: "#randevu" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[10px] font-black tracking-[2px] uppercase text-[#0F172A]/70 hover:text-[#0ea5e9] transition-colors relative py-1 cursor-pointer group"
|
||||
>
|
||||
{item.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#0ea5e9] transition-all group-hover:w-full" />
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Language Selector + Booking Button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-[#0F172A]/5 border border-[#0F172A]/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-sora-editorial px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-white text-slate-900 shadow-sm" : "text-[#0F172A]/60 hover:text-[#0F172A]"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-sora-editorial px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-white text-slate-900 shadow-sm" : "text-[#0F172A]/60 hover:text-[#0F172A]"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[10px] font-black tracking-[2.5px] uppercase text-white bg-[#0ea5e9] hover:bg-[#0284c7] px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_4px_12px_rgba(14,165,233,0.15)] hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.navBooking}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── HERO & INTERACTIVE APPOINTMENT TRACKER ── */}
|
||||
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||||
|
||||
{/* Left Column: Heading and clinic stats */}
|
||||
<motion.div
|
||||
className="lg:col-span-6 z-20"
|
||||
variants={stagger}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="inline-flex items-center gap-2 text-[10px] font-black uppercase tracking-widest text-[#0ea5e9] mb-6 bg-[#0ea5e9]/5 border border-[#0ea5e9]/10 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#0ea5e9] animate-pulse" />
|
||||
{t.badge}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={fadeUp}
|
||||
className="font-sora-editorial font-black text-[#0F172A] leading-[1.1] mb-8 hero-title-clamp uppercase"
|
||||
>
|
||||
{t.heroTitlePart1}
|
||||
<br />
|
||||
<span className="italic font-light text-[#0ea5e9] lowercase">{t.heroTitlePart2}</span>
|
||||
<br />
|
||||
{t.heroTitlePart3}
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-[#0F172A]/60 text-xs lg:text-sm leading-relaxed max-w-md mb-12 font-semibold"
|
||||
>
|
||||
{t.heroDesc}
|
||||
</motion.p>
|
||||
|
||||
{/* Statistics Grid */}
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="grid grid-cols-2 sm:grid-cols-4 gap-6 mb-12 font-semibold"
|
||||
>
|
||||
{istatistikler.map((stat, idx) => (
|
||||
<div key={idx} className="border-l border-[#0ea5e9]/30 pl-4 py-1">
|
||||
<h4 className="font-sora-editorial font-black text-[#0F172A] text-lg uppercase tracking-wider mb-1 leading-none">
|
||||
{stat.deger === "4200" || stat.deger === "620" ? `${stat.deger}+` : stat.deger}
|
||||
</h4>
|
||||
<p className="text-[#0F172A]/50 text-[10px] leading-snug">
|
||||
{getLocalizedStatLabel(stat.deger)}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
{/* CTA buttons */}
|
||||
<motion.div variants={fadeUp} className="flex gap-4">
|
||||
<a
|
||||
href="#randevu"
|
||||
className="inline-flex items-center gap-3 px-8 py-4.5 rounded-xl bg-[#0ea5e9] hover:bg-[#0284c7] text-white font-black text-[10px] tracking-[2px] uppercase transition-all shadow-[0_5px_15px_rgba(14,165,233,0.2)] cursor-pointer"
|
||||
>
|
||||
📅 {t.navBooking}
|
||||
</a>
|
||||
<a
|
||||
href="#hizmetler"
|
||||
className="inline-flex items-center gap-3 px-8 py-4.5 rounded-xl border border-[#0F172A]/10 bg-white/40 hover:bg-white/80 text-[#0F172A] font-black text-[10px] tracking-[2px] uppercase transition-all cursor-pointer"
|
||||
>
|
||||
{t.navServices}
|
||||
</a>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: Layered Live Tracker Mockup */}
|
||||
<div className="lg:col-span-6 relative flex justify-center lg:justify-end">
|
||||
<motion.div
|
||||
className="relative w-full max-w-md bg-white rounded-3xl p-8 border border-white shadow-premium z-10"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-6 pb-4 border-b border-gray-100">
|
||||
<div>
|
||||
<h4 className="font-sora-editorial font-black text-[#0F172A] text-sm uppercase leading-tight">{t.appointmentsToday}</h4>
|
||||
<span className="text-[10px] text-[#0F172A]/40 uppercase tracking-widest font-black mt-1.5 block">{t.saturday}</span>
|
||||
</div>
|
||||
<div className="w-10 h-10 rounded-xl bg-[#0ea5e9]/10 flex items-center justify-center shrink-0">
|
||||
<svg className="w-5 h-5 text-[#0ea5e9]" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3 font-semibold">
|
||||
{t.appointmentList.map((r, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="flex items-center justify-between p-3.5 rounded-2xl bg-gray-50 border border-gray-100/50 hover:bg-[#0ea5e9]/5 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`w-2 h-2 rounded-full ${r.dolu ? "bg-red-500 animate-pulse" : "bg-emerald-500"}`} />
|
||||
<div>
|
||||
<h5 className="text-[12px] font-black text-[#0F172A]">{r.saat}</h5>
|
||||
<span className="text-[10px] text-[#0F172A]/50 mt-0.5 block">{r.tip}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className={`text-[9px] font-black uppercase tracking-wider px-2.5 py-1 rounded-full ${r.dolu ? "bg-red-500/10 text-red-500" : "bg-emerald-500/10 text-emerald-500"}`}>
|
||||
{r.dolu ? t.statusDolu : t.statusMusait}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Rating Badge Overlay */}
|
||||
<motion.div
|
||||
className="absolute -top-6 -right-6 bg-white border border-gray-100 rounded-2xl px-5 py-3.5 shadow-2xl flex items-center gap-3 select-none"
|
||||
animate={{ y: [0, -6, 0] }}
|
||||
transition={{ duration: 4, repeat: Infinity, ease: "easeInOut" }}
|
||||
>
|
||||
<span className="text-xl">⭐</span>
|
||||
<div>
|
||||
<h5 className="font-sora-editorial font-black text-slate-800 text-[13px] uppercase leading-none">{t.ratingText.split("•")[0]}</h5>
|
||||
<span className="text-[9px] text-[#0F172A]/40 uppercase tracking-widest font-black mt-1 block">{t.ratingText.split("•")[1]}</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* SMS Reminder Overlay */}
|
||||
<motion.div
|
||||
className="absolute -bottom-6 -left-6 bg-white border border-gray-100 rounded-2xl px-5 py-3.5 shadow-2xl flex items-center gap-3 select-none"
|
||||
animate={{ y: [0, 6, 0] }}
|
||||
transition={{ duration: 4.5, repeat: Infinity, ease: "easeInOut", delay: 0.5 }}
|
||||
>
|
||||
<span className="text-xl">🔔</span>
|
||||
<div>
|
||||
<h5 className="font-sora-editorial font-black text-slate-800 text-[13px] uppercase leading-none">{t.smsReminder}</h5>
|
||||
<span className="text-[9px] text-[#0F172A]/40 uppercase tracking-widest font-black mt-1 block">{t.smsDesc}</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── HİZMETLER ── */}
|
||||
<section id="hizmetler" className="py-32 bg-white px-6 border-t border-[#0f172a]/5">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<motion.div
|
||||
className="mb-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-[#0ea5e9]/5 text-[#0ea5e9] border border-[#0ea5e9]/10"
|
||||
>
|
||||
{t.servicesTitle}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-sora-premium font-black text-gray-900 leading-tight uppercase">
|
||||
{t.servicesHeader}
|
||||
</motion.h2>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
{hizmetler.map((h, i) => {
|
||||
const item = getLocalizedServiceText(h.baslik);
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
variants={fadeUp}
|
||||
className="group p-8 rounded-3xl border border-gray-100 hover:border-transparent transition-all duration-300 cursor-default bg-white flex flex-col justify-between h-80"
|
||||
whileHover={{ y: -6, boxShadow: `0 24px 60px rgba(14,165,233,0.1)` }}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className="w-14 h-14 rounded-2xl flex items-center justify-center mb-6 transition-transform group-hover:scale-105 shadow-sm border border-gray-100 bg-gray-50"
|
||||
>
|
||||
{getServiceIconSvg(h.baslik)}
|
||||
</div>
|
||||
<h3 className="font-sora-premium font-bold text-base text-gray-900 mb-2 leading-snug uppercase tracking-wide">{item.title}</h3>
|
||||
<p className="text-gray-500 text-xs leading-relaxed font-semibold">{item.desc}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[#0ea5e9] font-black text-[9px] tracking-[2.5px] uppercase flex items-center gap-1 cursor-pointer hover:text-opacity-80 transition-colors pt-4 border-t border-gray-100 shrink-0"
|
||||
>
|
||||
{t.learnMore}
|
||||
</button>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── DOKTORLAR ── */}
|
||||
<section id="doktorlar" className="py-32 px-6 bg-[#f8fafc] border-t border-gray-100">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<motion.div
|
||||
className="mb-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-[#0ea5e9]/5 text-[#0ea5e9] border border-[#0ea5e9]/10"
|
||||
>
|
||||
{t.doctorsTitle}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-sora-premium font-black text-gray-900 uppercase">
|
||||
{t.doctorsHeader}
|
||||
</motion.h2>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="grid sm:grid-cols-2 lg:grid-cols-4 gap-6 font-semibold"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
{doktorlar.map((d, i) => {
|
||||
const doc = getLocalizedDoctor(d.ad);
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
variants={fadeUp}
|
||||
className="bg-white rounded-3xl overflow-hidden border border-gray-100/60 shadow-premium flex flex-col justify-between"
|
||||
whileHover={{ y: -8 }}
|
||||
>
|
||||
<div
|
||||
className="h-48 flex items-center justify-center text-7xl relative overflow-hidden select-none"
|
||||
style={{ background: `linear-gradient(135deg, ${firma.renkAcik}, rgba(14,165,233,0.15))` }}
|
||||
>
|
||||
<motion.span whileHover={{ scale: 1.15 }} transition={{ type: "spring", stiffness: 300 }}>
|
||||
{d.emoji}
|
||||
</motion.span>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<h3 className="font-sora-premium font-black text-gray-900 text-sm uppercase leading-tight">{doc.name}</h3>
|
||||
<p className="text-[11px] font-bold mt-1.5 mb-4 text-[#0ea5e9] uppercase tracking-wide">{doc.title}</p>
|
||||
<div className="flex items-center justify-between text-[9px] text-gray-500 border-t border-gray-100 pt-3 font-black uppercase tracking-widest">
|
||||
<span>⭐ {d.puan}</span>
|
||||
<span>🏥 {d.yil} {lang === "tr" ? "YIL" : "YRS"}</span>
|
||||
<span>👥 {d.hasta}+ {lang === "tr" ? "HASTA" : "PATS"}</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── ONLINE APPOINTMENT FORM ── */}
|
||||
<section id="randevu" className="py-32 px-6 relative overflow-hidden"
|
||||
style={{ background: `linear-gradient(135deg, ${firma.renkKoyu} 0%, ${firma.renkAna} 100%)` }}>
|
||||
|
||||
{/* Subtle cosmic grid layout */}
|
||||
<div className="absolute inset-0 opacity-[0.03] pointer-events-none"
|
||||
style={{ backgroundImage: "linear-gradient(#fff 1px,transparent 1px),linear-gradient(90deg,#fff 1px,transparent 1px)", backgroundSize: "40px 40px" }} />
|
||||
|
||||
<div className="max-w-7xl mx-auto relative z-10">
|
||||
<div className="grid lg:grid-cols-2 gap-16 items-start">
|
||||
|
||||
{/* Left Column: Contact details */}
|
||||
<motion.div initial="hidden" whileInView="show" viewport={{ once: true }} variants={stagger}>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[9px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-white/20 text-white border border-white/10"
|
||||
>
|
||||
{t.bookingTitle}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-sora-premium font-black text-white leading-tight mb-6 uppercase">
|
||||
{t.bookingHeader}
|
||||
</motion.h2>
|
||||
<motion.p variants={fadeUp} className="text-white/70 text-xs lg:text-sm mb-10 font-semibold leading-relaxed">
|
||||
{t.bookingDesc}
|
||||
</motion.p>
|
||||
|
||||
<motion.div variants={fadeUp} className="space-y-4 font-semibold">
|
||||
{[
|
||||
{ ikon: "📞", baslik: t.callCenter, aciklama: firma.telefon },
|
||||
{ ikon: "📍", baslik: t.addressLabel, aciklama: firma.adres },
|
||||
{ ikon: "✉️", baslik: t.emailLabel, aciklama: firma.email },
|
||||
].map((item) => (
|
||||
<div key={item.baslik} className="flex items-start gap-4 bg-white/10 rounded-2xl p-4 border border-white/5">
|
||||
<span className="text-xl mt-0.5 shrink-0 select-none">{item.ikon}</span>
|
||||
<div>
|
||||
<p className="text-white/60 text-[9px] font-black uppercase tracking-wider">{item.baslik}</p>
|
||||
<p className="text-white text-xs mt-1 leading-snug">{item.aciklama}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: Appointment Form */}
|
||||
<motion.div
|
||||
className="bg-white rounded-3xl p-8 shadow-2xl border border-white/10"
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7, delay: 0.2 }}
|
||||
>
|
||||
<h3 className="font-sora-premium font-black text-gray-900 text-lg mb-6 uppercase tracking-wide">{t.bookingTitle}</h3>
|
||||
<div className="grid grid-cols-2 gap-4 font-semibold">
|
||||
{[
|
||||
{ label: t.fieldsName, placeholder: lang === "tr" ? "Adınız Soyadınız" : "Your Full Name", type: "text", full: false },
|
||||
{ label: t.fieldsPhone, placeholder: "05xx xxx xx xx", type: "tel", full: false },
|
||||
{ label: t.fieldsEmail, placeholder: "ornek@mail.com", type: "email", full: false },
|
||||
{ label: t.fieldsDepartment, placeholder: "", type: "select", full: false },
|
||||
{ label: t.fieldsDate, placeholder: "", type: "date", full: false },
|
||||
{ label: t.fieldsNotes, placeholder: t.fieldsNotesPlaceholder, type: "text", full: true },
|
||||
].map((field, i) => (
|
||||
<div key={i} className={field.full ? "col-span-2" : "col-span-2 sm:col-span-1"}>
|
||||
<label className="block text-[10px] font-black text-gray-700 mb-1.5 uppercase tracking-wider">{field.label}</label>
|
||||
{field.type === "select" ? (
|
||||
<select className="w-full px-4 py-3.5 rounded-xl border border-gray-200 text-xs text-slate-800 focus:outline-none focus:ring-2 focus:ring-[#0ea5e9] bg-gray-50/50 transition-all font-semibold cursor-pointer">
|
||||
<option>{t.serviceDahiliye}</option>
|
||||
<option>{t.serviceKardiyoloji}</option>
|
||||
<option>{t.serviceDis}</option>
|
||||
<option>{t.serviceGoz}</option>
|
||||
<option>{t.serviceLab}</option>
|
||||
</select>
|
||||
) : (
|
||||
<input type={field.type} placeholder={field.placeholder}
|
||||
className="w-full px-4 py-3.5 rounded-xl border border-gray-200 text-xs focus:outline-none focus:ring-2 focus:ring-[#0ea5e9] bg-gray-50/50 transition-all placeholder-slate-300 font-semibold" />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="mt-6 w-full py-4.5 rounded-xl text-white font-black text-xs uppercase tracking-widest cursor-pointer shadow-[0_5px_15px_rgba(14,165,233,0.2)]"
|
||||
style={{ background: `linear-gradient(135deg, ${firma.renkAna}, ${firma.renkKoyu})` }}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
📅 {t.dispatchForm}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── TESTIMONIALS ── */}
|
||||
<section id="testimonials" className="py-32 px-6 bg-gray-950 border-t border-white/5 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<motion.div
|
||||
className="mb-20 text-center"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-white/5 text-[#0ea5e9] border border-white/10"
|
||||
>
|
||||
{t.navReviews}
|
||||
</motion.span>
|
||||
<h2 className="text-3xl lg:text-4xl font-sora-premium font-black text-white uppercase tracking-tight">
|
||||
{t.bookingTitle}
|
||||
</h2>
|
||||
</motion.div>
|
||||
|
||||
<div className="relative">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={activeYorum}
|
||||
className="bg-white/5 backdrop-blur-xl border border-white/10 rounded-3xl p-10 max-w-2xl mx-auto shadow-2xl"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.95 }}
|
||||
transition={{ duration: 0.4 }}
|
||||
>
|
||||
<div className="flex gap-1.5 mb-6 justify-center">
|
||||
{[...Array(yorumlar[activeYorum]?.puan || 5)].map((_, i) => (
|
||||
<svg key={i} className="w-4 h-4 fill-[#0ea5e9]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-white/80 text-base leading-relaxed italic text-center mb-8 font-semibold">
|
||||
“{yorumlar[activeYorum]?.yorum}”
|
||||
</p>
|
||||
<div className="flex items-center gap-3.5 justify-center font-semibold">
|
||||
<div className="w-10 h-10 rounded-full flex items-center justify-center text-sm bg-white/10 border border-white/10 font-bold select-none text-white">
|
||||
{yorumlar[activeYorum]?.yazar.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-white font-bold text-xs uppercase tracking-wide leading-tight">{yorumlar[activeYorum]?.yazar}</p>
|
||||
<p className="text-gray-500 text-[9px] uppercase tracking-wider font-black font-sora-premium mt-0.5">{yorumlar[activeYorum]?.tarih}</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
|
||||
<div className="flex justify-center gap-2.5 mt-8">
|
||||
{yorumlar.map((_, i) => (
|
||||
<button key={i} onClick={() => setActiveYorum(i)}
|
||||
className="w-2.5 h-2.5 rounded-full transition-all cursor-pointer"
|
||||
style={{ background: i === activeYorum ? "#0ea5e9" : "rgba(255,255,255,0.15)",
|
||||
transform: i === activeYorum ? "scale(1.3)" : "scale(1)" }} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-gray-950 border-t border-white/5 px-6 pt-24 pb-8 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
|
||||
<div className="md:col-span-2">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<svg className="w-5 h-5 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" />
|
||||
<path d="M12 6v12M6 12h12" />
|
||||
</svg>
|
||||
<span className="font-bold text-white text-lg font-sora-premium uppercase tracking-wide">{firma.adi}</span>
|
||||
</div>
|
||||
<p className="text-white/40 text-xs leading-relaxed max-w-sm mb-8 font-semibold">{t.footerDesc}</p>
|
||||
<div className="text-white/50 text-xs font-semibold space-y-3">
|
||||
<p className="flex items-center gap-2">📍 <span className="text-white/80">{firma.adres}</span></p>
|
||||
<p className="flex items-center gap-2">📞 <span className="text-white/80">{firma.telefon}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-sora-premium text-white font-bold text-xs uppercase tracking-wider mb-6">{t.navServices}</h4>
|
||||
{hizmetler.slice(0, 4).map((h, i) => {
|
||||
const s = getLocalizedServiceText(h.baslik);
|
||||
return (
|
||||
<a key={i} href="#hizmetler" className="block text-white/40 text-xs mb-3 hover:text-white transition-colors font-semibold">{s.title}</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-sora-premium text-white font-bold text-xs uppercase tracking-wider mb-6">Klinik</h4>
|
||||
{[t.navServices, t.navDoctors, t.navReviews, t.navContact].map((item) => (
|
||||
<a key={item} href="#" className="block text-white/40 text-xs mb-3 hover:text-white transition-colors font-semibold">{item}</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs font-semibold">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-white transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── BOOKING MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showBookingModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/60 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-white rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-gray-100"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center font-bold text-gray-500 hover:bg-gray-200 transition-colors cursor-pointer"
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
<h3 className="font-sora-premium font-black text-[#0F172A] text-2xl mb-1 uppercase tracking-wide">{t.contactTitle}</h3>
|
||||
<p className="text-gray-400 text-xs mb-6 font-semibold">{t.contactDesc}</p>
|
||||
|
||||
<div className="space-y-4 font-semibold">
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-gray-500 mb-1.5 uppercase tracking-wider">{t.fieldsName}</label>
|
||||
<input type="text" className="w-full px-4 py-3.5 rounded-xl border bg-gray-50/50 text-xs focus:outline-none focus:ring-2 focus:ring-[#0ea5e9]" placeholder="John Doe" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-gray-500 mb-1.5 uppercase tracking-wider">{t.fieldsPhone}</label>
|
||||
<input type="tel" className="w-full px-4 py-3.5 rounded-xl border bg-gray-50/50 text-xs focus:outline-none focus:ring-2 focus:ring-[#0ea5e9]" placeholder="05xx xxx xx xx" />
|
||||
</div>
|
||||
<motion.button
|
||||
className="w-full py-4 rounded-xl bg-[#0ea5e9] text-white font-black text-xs hover:bg-[#0284c7] transition-colors mt-2 cursor-pointer shadow-[0_4px_12px_rgba(14,165,233,0.15)] uppercase tracking-widest"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
{t.submit}
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,964 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useState, useEffect } from "react";
|
||||
import type { DemoData } from "@/data/demos";
|
||||
|
||||
const fadeUp = {
|
||||
hidden: { opacity: 0, y: 35 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.75, ease: [0.25, 0.46, 0.45, 0.94] as [number, number, number, number] } },
|
||||
};
|
||||
|
||||
const stagger = {
|
||||
hidden: {},
|
||||
show: { transition: { staggerChildren: 0.08 } },
|
||||
};
|
||||
|
||||
const translations = {
|
||||
tr: {
|
||||
navServices: "Hizmetlerimiz",
|
||||
navProjects: "Referanslarımız",
|
||||
navTeam: "Ekibimiz",
|
||||
navReviews: "Görüşler",
|
||||
navBooking: "Teklif Al",
|
||||
badge: "PREMIUM LOJİSTİK OPERATÖRÜ",
|
||||
heroTitlePart1: "Lojistikte",
|
||||
heroTitlePart2: "Fark Yaratan",
|
||||
heroTitlePart3: "Çözümler",
|
||||
heroDesc: "Güvenli taşımacılık ve zamanında teslimat çözümleri. Teknoloji destekli operasyon yönetimi ve küresel tedarik zinciri entegrasyonu ile işinizi büyütüyoruz. Atlas Lojistik premium ağı.",
|
||||
getQuote: "Teklif Al",
|
||||
learnMore: "Referanslar",
|
||||
projectsTitle: "Referanslarımız",
|
||||
projectsHeader: "BİRLİKTE BÜYÜDÜĞÜMÜZ KÜRESEL MARKALAR",
|
||||
teamTitle: "Ekibimiz",
|
||||
teamHeader: "YÖNETİM VE OPERASYON KADROMUZ",
|
||||
reviewsTitle: "Müşteri Görüşleri",
|
||||
reviewsHeader: "GÜVENİLİR İŞ ORTAKLARIMIZ",
|
||||
bookingTitle: "Teklif Talebi",
|
||||
bookingHeader: "BİRLİKTE ÇALIŞALIM",
|
||||
bookingDesc: "Tedarik zincirinizi veya lojistik operasyonunuzu optimize etmek için bilgilerinizi bırakın, uzmanlarımız özel çalışma planıyla geri dönsün.",
|
||||
fieldsName: "Ad Soyad",
|
||||
fieldsPhone: "Telefon Numarası",
|
||||
fieldsEmail: "E-Posta Adresi",
|
||||
fieldsCategory: "Hizmet Kategorisi",
|
||||
fieldsDate: "Planlanan Tarih",
|
||||
fieldsNotes: "Operasyon Notları / Detaylar",
|
||||
fieldsNotesPlaceholder: "Yıllık sevkiyat hacmi, depo alanı veya özel taşıma ihtiyaçları...",
|
||||
dispatchForm: "TEKLİF TALEBİ GÖNDER",
|
||||
contactChannels: "İLETİŞİM KANALLARI",
|
||||
callCenter: "Destek Hattı",
|
||||
addressLabel: "Lojistik Merkezi",
|
||||
emailLabel: "Kurumsal E-Posta",
|
||||
footerDesc: "Tedarik zinciri yönetiminde JIT (Just-In-Time) modelleri, GDP sertifikalı soğuk zincir lojistiği ve 7/24 anlık takip güvencesi.",
|
||||
privacyRegs: "Gizlilik Sözleşmesi",
|
||||
termsStay: "Kullanım Şartları",
|
||||
dismiss: "KAPAT",
|
||||
contactTitle: "Hızlı Teklif Danışmanlığı",
|
||||
contactDesc: "Lojistik gereksinimlerinizi bırakın, operasyon yöneticimiz 15 dakika içinde arasın.",
|
||||
submit: "Gönder",
|
||||
statExp: "Yıl Deneyim",
|
||||
statClients: "Aktif Müşteri",
|
||||
statCities: "Şehir Ağı",
|
||||
statDelivery: "Zamanında Teslimat",
|
||||
|
||||
// Services Localized
|
||||
serviceKarayolu: "Karayolu Taşımacılığı",
|
||||
serviceKarayoluDesc: "Yurtiçi ve uluslararası karayolu ile güvenli ve hızlı komple/parsiyel taşımacılık.",
|
||||
serviceDepolama: "Depolama & Lojistik",
|
||||
serviceDepolamaDesc: "Modern antrepolarımızda güvenli stok yönetimi, etiketleme ve dağıtım.",
|
||||
serviceEticaret: "E-ticaret Lojistiği",
|
||||
serviceEticaretDesc: "Son mile teslimat, iade yönetimi ve tam entegre fulfillment çözümleri.",
|
||||
serviceUlusal: "Uluslararası Nakliye",
|
||||
serviceUlusalDesc: "Gümrükleme, evrak takibi dahil kapıdan kapıya uluslararası taşımacılık.",
|
||||
serviceSoguk: "Soğuk Zincir Lojistiği",
|
||||
serviceSogukDesc: "Gıda ve ilaç sektörü için kontrollü sıcaklıkta GDP sertifikalı taşıma.",
|
||||
serviceTakip: "7/24 Anlık Takip",
|
||||
serviceTakipDesc: "Yüklerinizi ve sevkiyat rotalarınızı uydu üzerinden anlık takip edin.",
|
||||
|
||||
// Projects Localized
|
||||
projMigros: "Migros Dağıtım Ağı",
|
||||
projMigrosDesc: "12 şehirde günlük 400+ perakende noktasına kesintisiz soğuk zincir dağıtım yönetimi.",
|
||||
projTrendyol: "Trendyol Fulfillment",
|
||||
projTrendyolDesc: "Günlük 8.000+ e-ticaret sipariş işleme, paketleme ve son mile hızlı teslimat.",
|
||||
projFord: "Ford Otosan Tedarik",
|
||||
projFordDesc: "JIT (Just-In-Time) metodolojisiyle otomotiv üretim fabrikasına parça tedarik zinciri lojistiği.",
|
||||
projPfizer: "Pfizer İlaç Dağıtımı",
|
||||
projPfizerDesc: "GDP standartlarında, tam ısı kontrollü soğuk zincir ile ilaç ve aşı lojistiği.",
|
||||
},
|
||||
en: {
|
||||
navServices: "Our Services",
|
||||
navProjects: "References",
|
||||
navTeam: "Our Team",
|
||||
navReviews: "Testimonials",
|
||||
navBooking: "Get Quote",
|
||||
badge: "PREMIUM LOGISTICS OPERATOR",
|
||||
heroTitlePart1: "Logistics",
|
||||
heroTitlePart2: "Redefined With",
|
||||
heroTitlePart3: "Precision",
|
||||
heroDesc: "Secured transportation and JIT delivery frameworks. We optimize your supply chain with modern tech tracking, integrated warehousing, and global networks. Premium Atlas logistics hub.",
|
||||
getQuote: "Get Quote",
|
||||
learnMore: "References",
|
||||
projectsTitle: "Our Works",
|
||||
projectsHeader: "GLOBAL PARTNERS WE ARE PROUD TO GROW WITH",
|
||||
teamTitle: "Our Team",
|
||||
teamHeader: "OUR EXECUTIVE AND OPERATIONS DIRECTORS",
|
||||
reviewsTitle: "Client Reviews",
|
||||
reviewsHeader: "TRUSTED BY SECTOR LEADERS",
|
||||
bookingTitle: "Quote Request",
|
||||
bookingHeader: "WORK WITH US",
|
||||
bookingDesc: "To optimize your supply chain or schedule specialized cargo coordination, leave your credentials and our managers will draft a customized execution plan.",
|
||||
fieldsName: "Full Name",
|
||||
fieldsPhone: "Phone Number",
|
||||
fieldsEmail: "Email Address",
|
||||
fieldsCategory: "Service Category",
|
||||
fieldsDate: "Target Date",
|
||||
fieldsNotes: "Operations Details",
|
||||
fieldsNotesPlaceholder: "Annual volume, cold storage requests, or specific cargo dimensions...",
|
||||
dispatchForm: "SEND QUOTE REQUEST",
|
||||
contactChannels: "CONTACT CHANNELS",
|
||||
callCenter: "Support Helpline",
|
||||
addressLabel: "Logistics Hub",
|
||||
emailLabel: "Corporate Email",
|
||||
footerDesc: "Just-In-Time (JIT) manufacturing workflows, GDP certified cold chain facilities, and 7/24 satellite tracking systems.",
|
||||
privacyRegs: "Privacy Policy",
|
||||
termsStay: "Terms of Service",
|
||||
dismiss: "DISMISS",
|
||||
contactTitle: "Quick Consultation",
|
||||
contactDesc: "Outline your logistics coordinates and our transport managers will reach back in 15 minutes.",
|
||||
submit: "Submit",
|
||||
statExp: "Years Experience",
|
||||
statClients: "Active Clients",
|
||||
statCities: "City Hubs",
|
||||
statDelivery: "On-Time Delivery",
|
||||
|
||||
// Services Localized
|
||||
serviceKarayolu: "Road Transportation",
|
||||
serviceKarayoluDesc: "Secured and rapid domestic/international full or partial truckload transport.",
|
||||
serviceDepolama: "Warehousing & Logistics",
|
||||
serviceDepolamaDesc: "Bespoke inventory management, labeling, and retail cross-docking.",
|
||||
serviceEticaret: "E-Commerce Fulfillment",
|
||||
serviceEticaretDesc: "Last-mile courier integration, automated return flows, and fulfillment.",
|
||||
serviceUlusal: "Global Air/Ocean Cargo",
|
||||
serviceUlusalDesc: "Door-to-door global shipping routes with integrated custom clearance clearance.",
|
||||
serviceSoguk: "Cold Chain Transport",
|
||||
serviceSogukDesc: "GDP certified multi-temp fleet specifically for food and pharmaceutical sectors.",
|
||||
serviceTakip: "7/24 Satellite Tracking",
|
||||
serviceTakipDesc: "Real-time satellite path tracking and automated delay coordination.",
|
||||
|
||||
// Projects Localized
|
||||
projMigros: "Migros Retail Supply",
|
||||
projMigrosDesc: "Daily cold chain distribution routing to over 400+ points across 12 cities.",
|
||||
projTrendyol: "Trendyol Fulfillment Hub",
|
||||
projTrendyolDesc: "Handling 8,000+ daily e-commerce order dispatches with priority last-mile courier lanes.",
|
||||
projFord: "Ford Otosan JIT Tedarik",
|
||||
projFordDesc: "JIT manufacturing line support, synchronizing auto parts arrival exactly within scheduled shifts.",
|
||||
projPfizer: "Pfizer Cold Chain Pharma",
|
||||
projPfizerDesc: "GDP certified pharmaceutical transport using automated multi-temperature thermal cargo.",
|
||||
}
|
||||
};
|
||||
|
||||
export default function KurumsalTemplate({ data }: { data: DemoData }) {
|
||||
const { firma, istatistikler = [], hizmetler = [], yorumlar = [], projeler = [], ekip = [] } = data;
|
||||
const [showBookingModal, setShowBookingModal] = useState(false);
|
||||
const [lang, setLang] = useState<"tr" | "en">("tr");
|
||||
const [preloader, setPreloader] = useState(true);
|
||||
|
||||
const t = translations[lang];
|
||||
|
||||
// Lenis Smooth Scroll Integration
|
||||
useEffect(() => {
|
||||
let lenis: any;
|
||||
import("@studio-freight/lenis").then(({ default: Lenis }) => {
|
||||
lenis = new Lenis({ duration: 1.2, easing: (x: number) => Math.min(1, 1.001 - Math.pow(2, -10 * x)) });
|
||||
function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); }
|
||||
requestAnimationFrame(raf);
|
||||
});
|
||||
return () => lenis?.destroy();
|
||||
}, []);
|
||||
|
||||
// Preloader Curtain Timer
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setPreloader(false);
|
||||
}, 1500);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Localized stats label mappings
|
||||
const getLocalizedStatLabel = (etiket: string) => {
|
||||
if (etiket.includes("Deneyim")) return t.statExp;
|
||||
if (etiket.includes("Müşteri")) return t.statClients;
|
||||
if (etiket.includes("Şehir")) return t.statCities;
|
||||
return t.statDelivery;
|
||||
};
|
||||
|
||||
// Localized services text mappings
|
||||
const getLocalizedServiceText = (baslik: string) => {
|
||||
if (baslik.includes("Karayolu")) return { title: t.serviceKarayolu, desc: t.serviceKarayoluDesc };
|
||||
if (baslik.includes("Depolama")) return { title: t.serviceDepolama, desc: t.serviceDepolamaDesc };
|
||||
if (baslik.includes("E-ticaret")) return { title: t.serviceEticaret, desc: t.serviceEticaretDesc };
|
||||
if (baslik.includes("Uluslararası")) return { title: t.serviceUlusal, desc: t.serviceUlusalDesc };
|
||||
if (baslik.includes("Soğuk")) return { title: t.serviceSoguk, desc: t.serviceSogukDesc };
|
||||
return { title: t.serviceTakip, desc: t.serviceTakipDesc };
|
||||
};
|
||||
|
||||
// Localized projects text mappings
|
||||
const getLocalizedProjectText = (baslik: string) => {
|
||||
if (baslik.includes("Migros")) return { title: t.projMigros, desc: t.projMigrosDesc, sector: lang === "tr" ? "Perakende" : "Retail" };
|
||||
if (baslik.includes("Trendyol")) return { title: t.projTrendyol, desc: t.projTrendyolDesc, sector: lang === "tr" ? "E-Ticaret" : "E-Commerce" };
|
||||
if (baslik.includes("Ford")) return { title: t.projFord, desc: t.projFordDesc, sector: lang === "tr" ? "Otomotiv" : "Automotive" };
|
||||
return { title: t.projPfizer, desc: t.projPfizerDesc, sector: lang === "tr" ? "İlaç" : "Pharmaceutical" };
|
||||
};
|
||||
|
||||
// Custom vector icons for services (No generic emojis)
|
||||
const getServiceIconSvg = (baslik: string) => {
|
||||
if (baslik.includes("Karayolu")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#6366f1] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1M21 16V10a1 1 0 00-1-1h-7m8 7h-1m-6 0h-2" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("Depolama")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#6366f1] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("E-ticaret")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#6366f1] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("Uluslararası")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#6366f1] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 002 2h2.945M12 2a10 10 0 110 20 10 10 0 010-20z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (baslik.includes("Soğuk")) {
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#6366f1] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M12 3v18M3 12h18m-3-3l3 3-3 3M6 9l-3 3 3 3M9 6l3-3 3 3m-6 12l3 3 3-3" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<svg className="w-6 h-6 stroke-[#6366f1] fill-none" viewBox="0 0 24 24" strokeWidth="2">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const getLocalizedTeam = (ad: string) => {
|
||||
if (ad.includes("Murat")) return { name: "Murat Yıldız", role: lang === "tr" ? "Genel Müdür" : "Managing Director" };
|
||||
if (ad.includes("Hande")) return { name: "Hande Çelik", role: lang === "tr" ? "Operasyon Direktörü" : "Operations Director" };
|
||||
if (ad.includes("Serkan")) return { name: "Serkan Aydın", role: lang === "tr" ? "Teknoloji Müdürü" : "Technology Director" };
|
||||
return { name: "Neslihan Kara", role: lang === "tr" ? "Müşteri Deneyimi Yöneticisi" : "Customer Success Lead" };
|
||||
};
|
||||
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
|
||||
|
||||
:root {
|
||||
--color-kurumsal-indigo: #6366f1;
|
||||
--color-kurumsal-indigo-dark: #4f46e5;
|
||||
--color-kurumsal-indigo-light: #eef2ff;
|
||||
--color-kurumsal-charcoal: #0F172A;
|
||||
--color-kurumsal-sand: #FAF8F5;
|
||||
}
|
||||
|
||||
.font-heavy-sans {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.font-sans-clean {
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.shadow-premium {
|
||||
box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.hero-title-clamp {
|
||||
font-size: clamp(38px, 6vw, 90px);
|
||||
letter-spacing: -0.03em;
|
||||
line-height: 0.95;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{css}</style>
|
||||
|
||||
{/* ── IMZA AN: CURTAIN REVEAL PRELOADER ── */}
|
||||
<AnimatePresence>
|
||||
{preloader && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 bg-[#0F172A] flex flex-col items-center justify-center p-6"
|
||||
exit={{
|
||||
clipPath: "polygon(0 0, 100% 0, 100% 0, 0 0)",
|
||||
transition: { duration: 0.85, ease: [0.16, 1, 0.3, 1] }
|
||||
}}
|
||||
>
|
||||
<div className="max-w-md text-center space-y-6">
|
||||
<motion.span
|
||||
className="text-[9px] font-heavy-sans tracking-[4px] uppercase text-[#6366f1] block"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
ATLAS LOGISTICS
|
||||
</motion.span>
|
||||
<div className="h-[1px] w-48 bg-white/10 mx-auto relative overflow-hidden">
|
||||
<motion.div
|
||||
className="absolute inset-y-0 left-0 bg-[#6366f1]"
|
||||
initial={{ width: "0%" }}
|
||||
animate={{ width: "100%" }}
|
||||
transition={{ duration: 1.2, ease: "easeInOut" }}
|
||||
/>
|
||||
</div>
|
||||
<motion.h2
|
||||
className="font-sans-clean text-white/50 text-xs tracking-wider uppercase font-semibold"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
interactive prototype
|
||||
</motion.h2>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<div className="bg-[#FAF8F5] text-[#0F172A] min-h-screen font-sans-clean selection:bg-[#6366f1] selection:text-white overflow-hidden relative pb-20">
|
||||
|
||||
{/* Floating Ambient Orbs */}
|
||||
<div className="absolute top-[10%] left-[-15%] w-[600px] h-[600px] bg-[#6366f1]/3 blur-[120px] rounded-full pointer-events-none z-0" />
|
||||
<div className="absolute bottom-[20%] right-[-15%] w-[600px] h-[600px] bg-[#4f46e5]/3 blur-[140px] rounded-full pointer-events-none z-0" />
|
||||
|
||||
{/* ── FLOATING CONCEPT BANNER ── */}
|
||||
<div className="fixed bottom-4 left-4 z-40 bg-[#0F172A]/90 backdrop-blur-md border border-white/10 px-4 py-2.5 rounded-xl shadow-2xl flex items-center gap-2.5 max-w-sm pointer-events-none select-none">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-[#6366f1] animate-pulse" />
|
||||
<span className="text-[9px] font-sans-clean uppercase tracking-[1.5px] text-white/90 font-bold">
|
||||
{lang === "tr" ? "Bu web sitesi Ayris Tech tarafından hazırlanmış bir konsept çalışmasıdır." : "This website is a premium concept prototype designed by Ayris Tech."}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* ── PREMIUM HEADER ── */}
|
||||
<motion.header
|
||||
className="fixed top-4 left-4 right-4 z-50 px-4"
|
||||
initial={{ y: -80, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{ duration: 0.85, ease: [0.16, 1, 0.3, 1] }}
|
||||
>
|
||||
<div className="mx-auto max-w-7xl h-20 flex items-center justify-between px-8 bg-white/80 backdrop-blur-xl border border-white/40 rounded-2xl shadow-[0_10px_30px_rgba(15,23,42,0.03)]">
|
||||
{/* Logo */}
|
||||
<a href="#" className="flex items-center gap-2.5 group">
|
||||
<span className="text-lg font-black tracking-tight text-[#0F172A] font-heavy-sans flex items-center gap-2.5 uppercase">
|
||||
<svg className="w-5 h-5 text-[#6366f1]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" />
|
||||
<path d="M12 6v12M6 12h12" />
|
||||
</svg>
|
||||
{firma.adi}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{/* Links */}
|
||||
<nav className="hidden lg:flex items-center gap-8">
|
||||
{[
|
||||
{ label: t.navServices, href: "#hizmetler" },
|
||||
{ label: t.navProjects, href: "#projeler" },
|
||||
{ label: t.navTeam, href: "#ekip" },
|
||||
{ label: t.navReviews, href: "#testimonials" }
|
||||
].map(item => (
|
||||
<a
|
||||
key={item.label}
|
||||
href={item.href}
|
||||
className="text-[10px] font-black tracking-[2px] uppercase text-[#0F172A]/70 hover:text-[#6366f1] transition-colors relative py-1 cursor-pointer group"
|
||||
>
|
||||
{item.label}
|
||||
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-[#6366f1] transition-all group-hover:w-full" />
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Language Selector + Quote Button */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Language Switcher */}
|
||||
<div className="flex items-center gap-1 bg-[#0F172A]/5 border border-[#0F172A]/10 rounded-xl p-1 shrink-0">
|
||||
<button
|
||||
onClick={() => setLang("tr")}
|
||||
className={`text-[9px] font-sans-clean font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "tr" ? "bg-white text-slate-900 shadow-sm" : "text-[#0F172A]/60 hover:text-[#0F172A]"
|
||||
}`}
|
||||
>
|
||||
TR
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLang("en")}
|
||||
className={`text-[9px] font-sans-clean font-black px-2 py-1.5 rounded-lg transition-all cursor-pointer ${
|
||||
lang === "en" ? "bg-white text-slate-900 shadow-sm" : "text-[#0F172A]/60 hover:text-[#0F172A]"
|
||||
}`}
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[10px] font-black tracking-[2.5px] uppercase text-white bg-[#6366f1] hover:bg-[#4f46e5] px-6 py-3.5 rounded-xl transition-all cursor-pointer shadow-[0_4px_12px_rgba(99,102,241,0.15)] hidden sm:block"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
{t.navBooking}
|
||||
</motion.button>
|
||||
</div>
|
||||
</div>
|
||||
</motion.header>
|
||||
|
||||
{/* ── HERO & BENTO HIGHLIGHTS ── */}
|
||||
<section className="relative min-h-screen pt-32 pb-20 flex items-center z-10 px-6">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
<div className="grid lg:grid-cols-12 gap-16 items-center">
|
||||
|
||||
{/* Left Column: Heavy typography and stats */}
|
||||
<motion.div
|
||||
className="lg:col-span-6 z-20"
|
||||
variants={stagger}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="inline-flex items-center gap-2 text-[10px] font-black uppercase tracking-widest text-[#6366f1] mb-6 bg-[#6366f1]/5 border border-[#6366f1]/10 px-4 py-2 rounded-full"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-[#6366f1] animate-pulse" />
|
||||
{t.badge}
|
||||
</motion.div>
|
||||
|
||||
<motion.h1
|
||||
variants={fadeUp}
|
||||
className="font-heavy-sans text-[#0F172A] leading-[1.1] mb-8 hero-title-clamp uppercase"
|
||||
>
|
||||
{t.heroTitlePart1}
|
||||
<br />
|
||||
<span className="text-[#6366f1] font-light italic">{t.heroTitlePart2}</span>
|
||||
<br />
|
||||
{t.heroTitlePart3}
|
||||
</motion.h1>
|
||||
|
||||
<motion.p
|
||||
variants={fadeUp}
|
||||
className="text-[#0F172A]/60 text-xs lg:text-sm leading-relaxed max-w-md mb-12 font-semibold"
|
||||
>
|
||||
{t.heroDesc}
|
||||
</motion.p>
|
||||
|
||||
{/* Statistics Grid */}
|
||||
<motion.div
|
||||
variants={fadeUp}
|
||||
className="grid grid-cols-2 sm:grid-cols-4 gap-6 mb-12 font-semibold"
|
||||
>
|
||||
{istatistikler.map((stat, idx) => (
|
||||
<div key={idx} className="border-l border-[#6366f1]/30 pl-4 py-1">
|
||||
<h4 className="font-heavy-sans text-[#0F172A] text-lg uppercase tracking-wider mb-1 leading-none">
|
||||
{stat.deger}
|
||||
</h4>
|
||||
<p className="text-[#0F172A]/50 text-[10px] leading-snug">
|
||||
{getLocalizedStatLabel(stat.etiket)}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
{/* CTA buttons */}
|
||||
<motion.div variants={fadeUp} className="flex gap-4">
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="inline-flex items-center gap-3 px-8 py-4.5 rounded-xl bg-[#6366f1] hover:bg-[#4f46e5] text-white font-black text-[10px] tracking-[2px] uppercase transition-all shadow-[0_5px_15px_rgba(99,102,241,0.2)] cursor-pointer"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
>
|
||||
📅 {t.getQuote}
|
||||
</motion.button>
|
||||
<a
|
||||
href="#projeler"
|
||||
className="inline-flex items-center gap-3 px-8 py-4.5 rounded-xl border border-[#0F172A]/10 bg-white/40 hover:bg-white/80 text-[#0F172A] font-black text-[10px] tracking-[2px] uppercase transition-all cursor-pointer"
|
||||
>
|
||||
{t.learnMore}
|
||||
</a>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: Bento style highlights preview */}
|
||||
<div className="lg:col-span-6 grid sm:grid-cols-2 gap-4 w-full">
|
||||
{hizmetler.slice(0, 4).map((h, i) => {
|
||||
const s = getLocalizedServiceText(h.baslik);
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="bg-white rounded-3xl p-6 shadow-premium border border-white hover:border-[#6366f1]/30 transition-all duration-300 flex flex-col justify-between group h-64"
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
transition={{ duration: 0.5, delay: i * 0.1 }}
|
||||
whileHover={{ y: -4 }}
|
||||
>
|
||||
<div className="w-12 h-12 rounded-2xl flex items-center justify-center transition-transform group-hover:scale-105 shadow-sm border border-gray-100 bg-gray-50 shrink-0">
|
||||
{getServiceIconSvg(h.baslik)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-heavy-sans text-gray-900 text-xs uppercase tracking-wide leading-tight mb-2">{s.title}</h4>
|
||||
<p className="text-gray-400 text-[10px] leading-relaxed font-semibold">{s.desc}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── HİZMETLER FULL BENTO GRID ── */}
|
||||
<section id="hizmetler" className="py-32 bg-white px-6 border-t border-gray-100 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<motion.div
|
||||
className="mb-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-[#6366f1]/5 text-[#6366f1] border border-[#6366f1]/10"
|
||||
>
|
||||
{t.navServices}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-heavy-sans text-gray-900 leading-tight uppercase">
|
||||
{lang === "tr" ? "Kapsamlı Lojistik Çözüm Paketi" : "Comprehensive Logistics Solutions"}
|
||||
</motion.h2>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
{hizmetler.map((h, i) => {
|
||||
const s = getLocalizedServiceText(h.baslik);
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
variants={fadeUp}
|
||||
className="bg-white rounded-3xl p-8 border border-gray-100 group flex flex-col justify-between h-80 transition-all duration-300"
|
||||
whileHover={{ y: -6, boxShadow: `0 24px 60px rgba(99,102,241,0.08)`, borderColor: `${firma.renkAna}30` }}
|
||||
>
|
||||
<div>
|
||||
<div className="w-14 h-14 rounded-2xl flex items-center justify-center transition-transform group-hover:scale-105 shadow-sm border border-gray-100 bg-gray-50 mb-6 shrink-0">
|
||||
{getServiceIconSvg(h.baslik)}
|
||||
</div>
|
||||
<h3 className="font-heavy-sans text-gray-900 text-sm uppercase tracking-wide leading-tight mb-3">{s.title}</h3>
|
||||
<p className="text-gray-500 text-xs leading-relaxed font-semibold">{s.desc}</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-[#6366f1] font-black text-[9px] tracking-[2.5px] uppercase flex items-center gap-1 cursor-pointer hover:text-opacity-80 transition-colors pt-4 border-t border-gray-100 shrink-0"
|
||||
>
|
||||
{lang === "tr" ? "DETAYLI BİLGİ →" : "MORE DETAILS →"}
|
||||
</button>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── REFERANSLAR (PROJELER) ── */}
|
||||
<section id="projeler" className="py-32 px-6 bg-gray-950 border-t border-white/5 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<motion.div
|
||||
className="mb-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-white/5 text-[#6366f1] border border-white/10"
|
||||
>
|
||||
{t.projectsTitle}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-heavy-sans text-white uppercase">
|
||||
{t.projectsHeader}
|
||||
</motion.h2>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="grid sm:grid-cols-2 gap-6"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
{projeler.map((p, i) => {
|
||||
const proj = getLocalizedProjectText(p.baslik);
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
variants={fadeUp}
|
||||
className="bg-white/5 border border-white/10 rounded-3xl p-8 group flex flex-col justify-between h-56 transition-all duration-300"
|
||||
whileHover={{ y: -4, background: "rgba(255,255,255,0.08)", borderColor: "rgba(255,255,255,0.2)" }}
|
||||
>
|
||||
<div className="flex items-start gap-5">
|
||||
<div className="w-14 h-14 rounded-2xl flex items-center justify-center text-xl shrink-0"
|
||||
style={{ background: `${p.renk}20` }}>
|
||||
<span className="select-none text-2xl">{p.ikon}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-2 flex-wrap">
|
||||
<h3 className="font-heavy-sans text-white text-[15px] uppercase tracking-wide">{proj.title}</h3>
|
||||
<span className="text-[9px] font-black uppercase tracking-widest px-2.5 py-1 rounded-full border border-white/10"
|
||||
style={{ background: `${p.renk}20`, color: p.renk }}>
|
||||
{proj.sector}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-white/50 text-xs leading-relaxed font-semibold">{proj.desc}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="text-white/80 font-black text-[9px] tracking-[2.5px] uppercase flex items-center gap-1 cursor-pointer hover:text-white transition-colors pt-4 border-t border-white/5 shrink-0"
|
||||
>
|
||||
{lang === "tr" ? "VAKAYI İNCELE →" : "VIEW CASE STUDY →"}
|
||||
</button>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── EKİP (TEAM) ── */}
|
||||
{ekip.length > 0 && (
|
||||
<section id="ekip" className="py-32 px-6 bg-[#f8fafc] border-t border-gray-100 relative z-10">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
<motion.div
|
||||
className="mb-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-[#6366f1]/5 text-[#6366f1] border border-[#6366f1]/10"
|
||||
>
|
||||
{t.teamTitle}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-heavy-sans text-gray-900 uppercase">
|
||||
{t.teamHeader}
|
||||
</motion.h2>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="grid sm:grid-cols-2 lg:grid-cols-4 gap-6 font-semibold"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
{ekip.map((k, i) => {
|
||||
const member = getLocalizedTeam(k.ad);
|
||||
return (
|
||||
<motion.div
|
||||
key={i}
|
||||
variants={fadeUp}
|
||||
className="bg-white rounded-3xl overflow-hidden border border-gray-100/60 shadow-premium flex flex-col justify-between"
|
||||
whileHover={{ y: -6 }}
|
||||
>
|
||||
<div
|
||||
className="h-44 flex items-center justify-center text-6xl select-none"
|
||||
style={{ background: `linear-gradient(135deg, ${firma.renkAcik}, rgba(99,102,241,0.15))` }}
|
||||
>
|
||||
<motion.span whileHover={{ scale: 1.15 }} transition={{ type: "spring", stiffness: 300 }}>
|
||||
{k.emoji}
|
||||
</motion.span>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<h3 className="font-heavy-sans text-gray-900 text-sm uppercase leading-tight">{member.name}</h3>
|
||||
<p className="text-[11px] font-bold mt-1.5 text-[#6366f1] uppercase tracking-wide">{member.role}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{/* ── YORUMLAR (TESTIMONIALS) ── */}
|
||||
<section id="testimonials" className="py-32 px-6 bg-white border-t border-gray-100 relative z-10">
|
||||
<div className="max-w-7xl mx-auto font-semibold">
|
||||
|
||||
<motion.div
|
||||
className="mb-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[10px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-[#6366f1]/5 text-[#6366f1] border border-[#6366f1]/10"
|
||||
>
|
||||
{t.reviewsTitle}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-heavy-sans text-gray-900 uppercase">
|
||||
{t.reviewsHeader}
|
||||
</motion.h2>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="grid md:grid-cols-3 gap-6"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={{ once: true }}
|
||||
variants={stagger}
|
||||
>
|
||||
{yorumlar.map((y, i) => (
|
||||
<motion.div
|
||||
key={i}
|
||||
variants={fadeUp}
|
||||
className="bg-gray-50 rounded-3xl p-8 border border-gray-100 flex flex-col justify-between h-80"
|
||||
whileHover={{ y: -4, boxShadow: `0 20px 40px rgba(99,102,241,0.06)`, borderColor: `${firma.renkAna}30` }}
|
||||
>
|
||||
<div>
|
||||
<div className="flex gap-1.5 mb-5">
|
||||
{[...Array(y.puan || 5)].map((_, j) => (
|
||||
<svg key={j} className="w-4.5 h-4.5 fill-[#6366f1]" viewBox="0 0 24 24">
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-gray-600 text-xs leading-relaxed italic mb-6">“{y.yorum}”</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3.5 pt-4 border-t border-gray-200/60 shrink-0">
|
||||
<div className="w-9 h-9 rounded-full flex items-center justify-center text-base bg-white shadow-sm border border-gray-100 select-none">
|
||||
{y.emoji}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-900 font-bold text-xs uppercase tracking-wide leading-tight">{y.yazar.split("—")[0]}</p>
|
||||
<p className="text-gray-400 text-[9px] uppercase tracking-widest font-black mt-0.5">{y.yazar.split("—")[1] || t.reviewsTitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── İLETİŞİM / TEKLİF AL ── */}
|
||||
<section id="iletisim" className="py-32 px-6 relative overflow-hidden"
|
||||
style={{ background: `linear-gradient(135deg, ${firma.renkKoyu} 0%, ${firma.renkAna} 100%)` }}>
|
||||
|
||||
{/* Subtle cosmic grid layout */}
|
||||
<div className="absolute inset-0 opacity-[0.03] pointer-events-none"
|
||||
style={{ backgroundImage: "linear-gradient(#fff 1px,transparent 1px),linear-gradient(90deg,#fff 1px,transparent 1px)", backgroundSize: "40px 40px" }} />
|
||||
|
||||
<div className="max-w-7xl mx-auto relative z-10">
|
||||
<div className="grid lg:grid-cols-2 gap-16 items-start">
|
||||
|
||||
{/* Left Column: contact information */}
|
||||
<motion.div initial="hidden" whileInView="show" viewport={{ once: true }} variants={stagger}>
|
||||
<motion.span
|
||||
variants={fadeUp}
|
||||
className="inline-block text-[9px] font-black uppercase tracking-widest px-4 py-2 rounded-full mb-4 bg-white/20 text-white border border-white/10"
|
||||
>
|
||||
{t.bookingTitle}
|
||||
</motion.span>
|
||||
<motion.h2 variants={fadeUp} className="text-4xl lg:text-5xl font-heavy-sans text-white leading-tight mb-6 uppercase">
|
||||
{t.bookingHeader}
|
||||
</motion.h2>
|
||||
<motion.p variants={fadeUp} className="text-white/70 text-xs lg:text-sm mb-10 font-semibold leading-relaxed">
|
||||
{t.bookingDesc}
|
||||
</motion.p>
|
||||
|
||||
<motion.div variants={fadeUp} className="space-y-4 font-semibold">
|
||||
{[
|
||||
{ ikon: "📞", baslik: t.callCenter, aciklama: firma.telefon },
|
||||
{ ikon: "📍", baslik: t.addressLabel, aciklama: firma.adres },
|
||||
{ ikon: "✉️", baslik: t.emailLabel, aciklama: firma.email },
|
||||
].map((item) => (
|
||||
<div key={item.baslik} className="flex items-start gap-4 bg-white/10 rounded-2xl p-4 border border-white/5">
|
||||
<span className="text-xl mt-0.5 shrink-0 select-none">{item.ikon}</span>
|
||||
<div>
|
||||
<p className="text-white/60 text-[9px] font-black uppercase tracking-wider">{item.baslik}</p>
|
||||
<p className="text-white text-xs mt-1 leading-snug">{item.aciklama}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Column: Quote Form */}
|
||||
<motion.div
|
||||
className="bg-white rounded-3xl p-8 shadow-2xl border border-white/10"
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7, delay: 0.2 }}
|
||||
>
|
||||
<h3 className="font-heavy-sans text-gray-900 text-lg mb-6 uppercase tracking-wide">{t.bookingTitle}</h3>
|
||||
<div className="grid grid-cols-2 gap-4 font-semibold">
|
||||
{[
|
||||
{ label: t.fieldsName, placeholder: lang === "tr" ? "Adınız Soyadınız" : "Your Full Name", type: "text", full: false },
|
||||
{ label: t.fieldsPhone, placeholder: "05xx xxx xx xx", type: "tel", full: false },
|
||||
{ label: t.fieldsEmail, placeholder: "ornek@mail.com", type: "email", full: false },
|
||||
{ label: t.fieldsCategory, placeholder: "", type: "select", full: false },
|
||||
{ label: t.fieldsDate, placeholder: "", type: "date", full: false },
|
||||
{ label: t.fieldsNotes, placeholder: t.fieldsNotesPlaceholder, type: "text", full: true },
|
||||
].map((field, i) => (
|
||||
<div key={i} className={field.full ? "col-span-2" : "col-span-2 sm:col-span-1"}>
|
||||
<label className="block text-[10px] font-black text-gray-700 mb-1.5 uppercase tracking-wider">{field.label}</label>
|
||||
{field.type === "select" ? (
|
||||
<select className="w-full px-4 py-3.5 rounded-xl border border-gray-200 text-xs text-slate-800 focus:outline-none focus:ring-2 focus:ring-[#6366f1] bg-gray-50/50 transition-all font-semibold cursor-pointer">
|
||||
<option>{t.serviceKarayolu}</option>
|
||||
<option>{t.serviceDepolama}</option>
|
||||
<option>{t.serviceEticaret}</option>
|
||||
<option>{t.serviceUlusal}</option>
|
||||
<option>{t.serviceSoguk}</option>
|
||||
</select>
|
||||
) : (
|
||||
<input type={field.type} placeholder={field.placeholder}
|
||||
className="w-full px-4 py-3.5 rounded-xl border border-gray-200 text-xs focus:outline-none focus:ring-2 focus:ring-[#6366f1] bg-gray-50/50 transition-all placeholder-slate-300 font-semibold" />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<motion.button
|
||||
onClick={() => setShowBookingModal(true)}
|
||||
className="mt-6 w-full py-4.5 rounded-xl text-white font-black text-xs uppercase tracking-widest cursor-pointer shadow-[0_5px_15px_rgba(99,102,241,0.2)]"
|
||||
style={{ background: `linear-gradient(135deg, ${firma.renkAna}, ${firma.renkKoyu})` }}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
📅 {t.dispatchForm}
|
||||
</motion.button>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── FOOTER ── */}
|
||||
<footer className="bg-gray-950 border-t border-white/5 px-6 pt-24 pb-8 relative z-10">
|
||||
<div className="max-w-7xl mx-auto font-semibold">
|
||||
<div className="grid md:grid-cols-4 gap-12 pb-16 border-b border-white/5">
|
||||
<div className="md:col-span-2">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<svg className="w-5 h-5 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
||||
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" />
|
||||
<path d="M12 6v12M6 12h12" />
|
||||
</svg>
|
||||
<span className="font-bold text-white text-lg font-heavy-sans uppercase tracking-wide">{firma.adi}</span>
|
||||
</div>
|
||||
<p className="text-white/40 text-xs leading-relaxed max-w-sm mb-8">{firma.slogan} — {t.footerDesc}</p>
|
||||
<div className="text-white/50 text-xs space-y-3">
|
||||
<p className="flex items-center gap-2">📍 <span className="text-white/80">{firma.adres}</span></p>
|
||||
<p className="flex items-center gap-2">📞 <span className="text-white/80">{firma.telefon}</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-heavy-sans text-white font-bold text-xs uppercase tracking-wider mb-6">{t.navServices}</h4>
|
||||
{hizmetler.slice(0, 4).map((h, i) => {
|
||||
const s = getLocalizedServiceText(h.baslik);
|
||||
return (
|
||||
<a key={i} href="#hizmetler" className="block text-white/40 text-xs mb-3 hover:text-white transition-colors">{s.title}</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-heavy-sans text-white font-bold text-xs uppercase tracking-wider mb-6">Company</h4>
|
||||
{[t.navServices, t.navProjects, t.navTeam, t.navReviews].map((item) => (
|
||||
<a key={item} href="#" className="block text-white/40 text-xs mb-3 hover:text-white transition-colors">{item}</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/30 text-xs">
|
||||
<p>© 2026 {firma.adi}. All rights reserved.</p>
|
||||
<div className="flex gap-4">
|
||||
<a href="#" className="hover:text-white transition-colors">{t.privacyRegs}</a>
|
||||
<span>·</span>
|
||||
<a href="#" className="hover:text-white transition-colors">{t.termsStay}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{/* ── CONSULTATION SUCCESS MODAL ── */}
|
||||
<AnimatePresence>
|
||||
{showBookingModal && (
|
||||
<motion.div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/60 backdrop-blur-sm"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-white rounded-3xl p-8 max-w-md w-full relative shadow-2xl border border-gray-100"
|
||||
initial={{ scale: 0.95, y: 20 }}
|
||||
animate={{ scale: 1, y: 0 }}
|
||||
exit={{ scale: 0.95, y: 20 }}
|
||||
>
|
||||
<button
|
||||
className="absolute top-6 right-6 w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center font-bold text-gray-500 hover:bg-gray-200 transition-colors cursor-pointer"
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
<h3 className="font-heavy-sans text-[#0F172A] text-2xl mb-1 uppercase tracking-wide leading-none">{t.contactTitle}</h3>
|
||||
<p className="text-gray-400 text-xs mb-6 font-semibold">{t.contactDesc}</p>
|
||||
|
||||
<div className="space-y-4 font-semibold">
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-gray-500 mb-1.5 uppercase tracking-wider">{t.fieldsName}</label>
|
||||
<input type="text" className="w-full px-4 py-3.5 rounded-xl border bg-gray-50/50 text-xs focus:outline-none focus:ring-2 focus:ring-[#6366f1]" placeholder="John Doe" />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[10px] font-black text-gray-500 mb-1.5 uppercase tracking-wider">{t.fieldsPhone}</label>
|
||||
<input type="tel" className="w-full px-4 py-3.5 rounded-xl border bg-gray-50/50 text-xs focus:outline-none focus:ring-2 focus:ring-[#6366f1]" placeholder="05xx xxx xx xx" />
|
||||
</div>
|
||||
<motion.button
|
||||
className="w-full py-4 rounded-xl bg-[#6366f1] text-white font-black text-xs hover:bg-[#4f46e5] transition-colors mt-2 cursor-pointer shadow-[0_4px_12px_rgba(99,102,241,0.15)] uppercase tracking-widest"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
onClick={() => setShowBookingModal(false)}
|
||||
>
|
||||
{t.submit}
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
"use client";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useInView } from "framer-motion";
|
||||
|
||||
export default function AnimatedCounter({ target, suffix = "" }: { target: number; suffix?: string }) {
|
||||
const [count, setCount] = useState(0);
|
||||
const ref = useRef(null);
|
||||
const inView = useInView(ref, { once: true });
|
||||
|
||||
useEffect(() => {
|
||||
if (!inView) return;
|
||||
const duration = 1800;
|
||||
const steps = 60;
|
||||
const increment = target / steps;
|
||||
let current = 0;
|
||||
const timer = setInterval(() => {
|
||||
current += increment;
|
||||
if (current >= target) {
|
||||
setCount(target);
|
||||
clearInterval(timer);
|
||||
} else {
|
||||
setCount(Math.floor(current));
|
||||
}
|
||||
}, duration / steps);
|
||||
return () => clearInterval(timer);
|
||||
}, [inView, target]);
|
||||
|
||||
return (
|
||||
<span ref={ref}>
|
||||
{count.toLocaleString("tr-TR")}
|
||||
{suffix}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user