Files
2026-05-30 18:23:21 +03:00

475 lines
22 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { motion, useScroll, useTransform, AnimatePresence } from "framer-motion";
import { useRef, useState } from "react";
import type { DemoData } from "@/data/demos";
import AnimatedCounter from "@/components/ui/AnimatedCounter";
const easeOutExpo = [0.16, 1, 0.3, 1] as [number, number, number, number];
const fadeUp = {
hidden: { opacity: 0, y: 40 },
show: { opacity: 1, y: 0, transition: { duration: 0.7, ease: easeOutExpo } },
};
const stagger = {
hidden: {},
show: { transition: { staggerChildren: 0.1 } },
};
export default function DentalTemplate({ data }: { data: DemoData }) {
const { firma, istatistikler, hizmetler, projeler = [], yorumlar = [] } = data;
const heroRef = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({ target: heroRef, offset: ["start start", "end start"] });
const heroY = useTransform(scrollYProgress, [0, 1], ["0%", "20%"]);
const heroOpacity = useTransform(scrollYProgress, [0, 0.8], [1, 0]);
const [activeYorum, setActiveYorum] = useState(0);
const [menuOpen, setMenuOpen] = useState(false);
const [showBookingModal, setShowBookingModal] = useState(false);
return (
<div className="bg-[#FAF7F2] text-[#1E2E38] font-body">
{/* ── HEADER ── */}
<motion.header
className="fixed top-0 left-0 right-0 z-50 px-6 py-4"
initial={{ y: -80 }}
animate={{ y: 0 }}
transition={{ duration: 0.6, ease: easeOutExpo }}
>
<div className="mx-auto max-w-6xl flex items-center justify-between h-16 px-6 bg-white/40 backdrop-blur-md rounded-3xl border border-white/20 shadow-sm">
<div className="flex items-center gap-2.5">
<span className="text-xl font-bold tracking-tight text-[#1E2E38] font-display flex items-center gap-1.5 uppercase">
<span className="text-2xl">🦷</span> {firma.adi}
</span>
</div>
<div className="flex items-center gap-8">
<button
className="flex flex-col gap-1.5 p-2 bg-[#1E2E38]/5 hover:bg-[#1E2E38]/10 transition-colors rounded-xl"
onClick={() => setMenuOpen(!menuOpen)}
>
<div className="w-5 h-0.5 bg-[#1E2E38]" />
<div className="w-3 h-0.5 bg-[#1E2E38]" />
</button>
</div>
<div className="hidden md:flex items-center gap-6">
<a href={`tel:${firma.telefon}`} className="text-xs font-bold text-[#1E2E38]/80 hover:text-[#1E2E38] transition-colors">
📞 {firma.telefon}
</a>
<motion.button
onClick={() => setShowBookingModal(true)}
className="text-xs font-black text-[#FAF7F2] bg-[#1E2E38] px-5 py-2.5 rounded-full hover:bg-[#121C22] transition-colors"
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.97 }}
>
Contact Us
</motion.button>
</div>
</div>
{/* Dropdown Menu */}
<AnimatePresence>
{menuOpen && (
<motion.div
className="absolute top-24 left-6 right-6 bg-white/95 backdrop-blur-xl border border-gray-100 rounded-3xl p-6 shadow-2xl flex flex-col gap-4 z-50 md:max-w-md md:left-auto md:right-6"
initial={{ opacity: 0, y: -20, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: -20, scale: 0.95 }}
transition={{ duration: 0.25 }}
>
<h4 className="text-xs font-black uppercase tracking-widest text-gray-400 border-b pb-2 mb-2">Navigasyon</h4>
{[
{ label: "001 - Uyelik Programı", href: "#uyelik" },
{ label: "002 - Hizmetler", href: "#hizmetler" },
{ label: "003 - Portfolyo (Works)", href: "#works" },
{ label: "004 - Yorumlar", href: "#yorumlar" },
{ label: "005 - Randevu Al", href: "#randevu" }
].map(item => (
<a
key={item.href}
href={item.href}
onClick={() => setMenuOpen(false)}
className="font-display font-bold text-[#1E2E38] hover:text-[#D4AF37] transition-colors text-base"
>
{item.label}
</a>
))}
</motion.div>
)}
</AnimatePresence>
</motion.header>
{/* ── HERO SECTION ── */}
<section ref={heroRef} className="relative min-h-screen flex items-center overflow-hidden bg-[#FAF7F2] pt-24">
<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 bottom-[20%] left-[28%] text-[#1E2E38]/20 text-3xl font-light select-none">+</div>
<div className="absolute bottom-[35%] right-[5%] text-[#1E2E38]/30 text-3xl font-light select-none">+</div>
</div>
<div className="relative z-10 max-w-6xl mx-auto px-6 w-full py-12">
<div className="grid lg:grid-cols-12 gap-12 items-center">
<motion.div
className="lg:col-span-12 z-20 text-center"
variants={stagger}
initial="hidden"
animate="show"
>
<motion.div
variants={fadeUp}
className="inline-flex items-center gap-2 text-[11px] font-black uppercase tracking-widest text-[#1E2E38]/60 mb-6"
>
<span className="w-1.5 h-1.5 rounded-full bg-[#1E2E38]" />
{firma.slogan}
</motion.div>
<motion.h1
variants={fadeUp}
className="text-6xl md:text-7xl font-display font-black text-[#1E2E38] leading-[1.05] tracking-tight mb-8"
>
Seamless 🦷
<br />
<span className="italic font-light opacity-90 text-[#3C5A48]">Dental Care</span>
</motion.h1>
<motion.p
variants={fadeUp}
className="text-[#1E2E38]/70 text-lg leading-relaxed max-w-md mx-auto mb-10 font-medium"
>
A smooth and hassle-free dental care experience for a healthy and confident smile.
</motion.p>
<motion.div variants={fadeUp}>
<motion.button
onClick={() => setShowBookingModal(true)}
className="inline-flex items-center gap-3 px-8 py-4 rounded-full bg-[#1E2E38] hover:bg-[#121C22] text-[#FAF7F2] font-black text-sm transition-all"
whileHover={{ scale: 1.04, boxShadow: "0 10px 30px rgba(30, 46, 56, 0.15)" }}
whileTap={{ scale: 0.97 }}
>
Book Now <span className="text-xs"></span>
</motion.button>
</motion.div>
</motion.div>
</div>
</div>
</section>
{/* ── SECTION 001: SAVINGS BENTO ── */}
<section id="uyelik" className="py-24 bg-[#FAF7F2] px-6 border-t border-[#1E2E38]/5">
<div className="max-w-6xl mx-auto">
<div className="grid lg:grid-cols-12 gap-16 items-start">
<motion.div
className="lg:col-span-5"
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.2 }}
variants={stagger}
>
<span className="inline-block text-[11px] font-black uppercase tracking-widest text-[#1E2E38]/60 mb-4">
001 - Join Membership
</span>
<h2 className="text-4xl lg:text-5xl font-display font-black text-[#1E2E38] leading-tight mb-6">
Affordable Dental Care for Your Family
</h2>
<p className="text-[#1E2E38]/70 text-base leading-relaxed mb-10">
Unlock optimal dental wellness for your loved ones. Get massive savings on check-ups, cleaning, and specialized cosmetic treatments.
</p>
<motion.button
onClick={() => setShowBookingModal(true)}
className="px-7 py-3.5 rounded-full bg-[#1E2E38] hover:bg-[#121C22] text-[#FAF7F2] font-black text-xs transition-colors"
whileHover={{ scale: 1.04 }}
whileTap={{ scale: 0.97 }}
>
Join Membership <span className="text-[10px]"></span>
</motion.button>
</motion.div>
<div className="lg:col-span-7 grid md:grid-cols-2 gap-6 w-full">
<motion.div
className="bg-[#EBF5F0] rounded-[36px] p-8 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-display">
{istatistikler[0]?.deger}
</span>
<span className="text-3xl font-light text-[#1E2E38]/50 shrink-0 select-none">+</span>
</div>
<p className="text-[#1E2E38]/80 text-[13px] leading-relaxed font-medium">
{istatistikler[0]?.etiket}
</p>
</motion.div>
<motion.div
className="bg-[#1E2E38] rounded-[36px] 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-display">
{istatistikler[1]?.deger}
</span>
<span className="text-3xl font-light text-[#FAF7F2]/50 shrink-0 select-none">+</span>
</div>
<p className="text-[#FAF7F2]/80 text-[13px] leading-relaxed font-medium">
{istatistikler[1]?.etiket}
</p>
</motion.div>
</div>
</div>
</div>
</section>
{/* ── CORE SERVICES CARD ROW ── */}
<section id="hizmetler" className="py-16 bg-white px-6">
<div className="max-w-6xl mx-auto">
<div className="grid md:grid-cols-3 gap-6">
{hizmetler.map((h, i) => (
<motion.div
key={i}
className="bg-[#FAF7F2]/60 hover:bg-[#FAF7F2] rounded-[28px] p-8 border border-gray-100 hover:border-[#1E2E38]/10 transition-all duration-300 flex flex-col items-center text-center 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 className="w-14 h-14 rounded-full bg-white flex items-center justify-center text-2xl shadow-sm mb-5 transition-transform group-hover:scale-110">
{h.ikon}
</div>
<h3 className="font-display font-bold text-[#1E2E38] text-base mb-3 leading-snug">
{h.baslik}
</h3>
<p className="text-gray-400 text-xs leading-relaxed">
{h.aciklama}
</p>
</motion.div>
))}
</div>
</div>
</section>
{/* ── SECTION 002: OUR WORKS ── */}
<section id="works" className="py-24 bg-[#EBF5F0] px-6">
<div className="max-w-6xl mx-auto">
<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}
>
<span className="inline-block text-[11px] font-black uppercase tracking-widest text-[#1E2E38]/60 mb-4">
002 - Our Works
</span>
<h2 className="text-4xl lg:text-5xl font-display font-black text-[#1E2E38] leading-tight">
A Healthy Smile<br />Starts Here
</h2>
</motion.div>
</div>
<div className="grid md:grid-cols-3 gap-8">
{projeler.map((p, i) => (
<motion.div
key={i}
className="bg-[#FAF7F2] border border-[#E7E5E4] rounded-3xl p-6 hover:border-[#1E2E38] transition-colors"
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 className="w-10 h-10 rounded-xl bg-[#1E2E38]/5 flex items-center justify-center mb-6 text-xl">
{p.ikon}
</div>
<h3 className="font-display font-bold text-[#1E2E38] text-lg mb-1">{p.baslik}</h3>
<p className="text-gray-500 text-xs font-semibold">{p.aciklama}</p>
</motion.div>
))}
</div>
</div>
</section>
{/* ── YORUMLAR ── */}
<section id="yorumlar" className="py-24 bg-white px-6">
<div className="max-w-6xl mx-auto">
<div className="mb-16 text-center">
<span className="inline-block text-[11px] font-black uppercase tracking-widest text-[#1E2E38]/60 mb-4">
003 - Patient Stories
</span>
<h2 className="text-4xl font-display font-black text-[#1E2E38]">
Patient Experiences
</h2>
</div>
<div className="relative">
<AnimatePresence mode="wait">
<motion.div
key={activeYorum}
className="bg-[#FAF7F2] border border-[#1E2E38]/5 rounded-[36px] 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 mb-6 justify-center">
{[...Array(yorumlar[activeYorum]?.puan)].map((_, i) => (
<span key={i} className="text-[#1E2E38] text-xl"></span>
))}
</div>
<p className="text-[#1E2E38]/80 text-lg leading-relaxed italic text-center mb-8 font-medium">
&ldquo;{yorumlar[activeYorum]?.yorum}&rdquo;
</p>
<div className="flex items-center gap-4 justify-center">
<div className="w-12 h-12 rounded-full flex items-center justify-center text-2xl bg-white shadow-sm border border-[#1E2E38]/5">
{yorumlar[activeYorum]?.emoji}
</div>
<div>
<p className="text-[#1E2E38] font-bold text-sm">{yorumlar[activeYorum]?.yazar}</p>
<p className="text-gray-400 text-xs">{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"
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 ── */}
<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-[40px] p-8 md:p-12 shadow-2xl border border-gray-100">
<div className="text-center mb-10">
<span className="inline-block text-[11px] font-black uppercase tracking-widest text-[#1E2E38]/60 mb-4">
004 - Online Appointment
</span>
<h2 className="text-3xl md:text-4xl font-display font-black text-[#1E2E38]">
Appointment Request
</h2>
<p className="text-gray-400 text-sm mt-2">
Hayalinizdeki sağlıklı gülüşe kavuşmak için formu doldurun, sizi arayalım.
</p>
</div>
<div className="grid grid-cols-2 gap-4">
{[
{ label: "Ad Soyad", placeholder: "Adınız Soyadınız", type: "text", full: false },
{ label: "Telefon", placeholder: "05xx xxx xx xx", type: "tel", full: false },
{ label: "E-posta", placeholder: "ornek@mail.com", type: "email", full: false },
{ label: "Hizmet Türü", placeholder: "", type: "select", full: false },
{ label: "Tercih Edilen Tarih", placeholder: "", type: "date", full: false },
{ label: "Şikayetiniz / Notunuz", placeholder: "Belirtmek istediğiniz detaylar...", type: "text", full: true },
].map((field, i) => (
<div key={i} className={field.full ? "col-span-2" : "col-span-1"}>
<label className="block text-[11px] font-bold text-[#1E2E38]/80 mb-1.5 uppercase tracking-wider">{field.label}</label>
{field.type === "select" ? (
<select className="w-full px-4 py-3 rounded-xl border border-gray-200 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-[#1E2E38] bg-gray-50/50 transition-all">
<option>Prevent Cavities & Disease</option>
<option>Teeth Sparkling Cleaning</option>
<option>Teeth Straightening</option>
<option>Dental Implant</option>
</select>
) : (
<input type={field.type} placeholder={field.placeholder}
className="w-full px-4 py-3 rounded-xl border border-gray-200 text-sm focus:outline-none focus:ring-2 focus:ring-[#1E2E38] bg-gray-50/50 transition-all" />
)}
</div>
))}
</div>
<motion.button
className="mt-8 w-full py-4 rounded-full text-[#FAF7F2] font-black text-sm bg-[#1E2E38] hover:bg-[#121C22]"
whileHover={{ scale: 1.02, boxShadow: "0 10px 30px rgba(30, 46, 56, 0.2)" }}
whileTap={{ scale: 0.98 }}
>
📅 Randevu Talep Et
</motion.button>
</div>
</div>
</section>
{/* ── FOOTER ── */}
<footer className="bg-[#121C22] border-t border-white/10 px-6 pt-16 pb-8">
<div className="max-w-6xl mx-auto">
<div className="flex flex-col md:flex-row justify-between items-center pt-8 gap-4 text-white/40">
<p className="text-xs">© 2026 {firma.adi}. Tüm hakları saklıdır.</p>
<p className="text-[10px]">Gizlilik Politikası · Çerez Ayarları</p>
</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-[36px] p-8 max-w-lg w-full relative shadow-2xl"
initial={{ scale: 0.9, y: 20 }}
animate={{ scale: 1, y: 0 }}
exit={{ scale: 0.9, 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"
onClick={() => setShowBookingModal(false)}
>
</button>
<h3 className="font-display font-black text-[#1E2E38] text-2xl mb-2">Hızlı İletişim</h3>
<p className="text-gray-400 text-xs mb-6">İletişim bilgilerinizi bırakın, en kısa sürede geri dönelim.</p>
<div className="space-y-4">
<div>
<label className="block text-[10px] font-bold text-gray-500 mb-1 uppercase">Ad Soyad</label>
<input type="text" className="w-full px-4 py-3 rounded-xl border bg-gray-50/50 text-sm focus:outline-none focus:ring-2 focus:ring-[#1E2E38]" placeholder="Adınız Soyadınız" />
</div>
<div>
<label className="block text-[10px] font-bold text-gray-500 mb-1 uppercase">Telefon Numarası</label>
<input type="tel" className="w-full px-4 py-3 rounded-xl border bg-gray-50/50 text-sm focus:outline-none focus:ring-2 focus:ring-[#1E2E38]" placeholder="05xx xxx xx xx" />
</div>
<motion.button
className="w-full py-4 rounded-full bg-[#1E2E38] text-[#FAF7F2] font-black text-sm hover:bg-[#121C22] transition-colors mt-2"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
onClick={() => setShowBookingModal(false)}
>
Gönder
</motion.button>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</div>
);
}