feat: add project files

This commit is contained in:
mstfyldz
2026-06-03 17:31:50 +03:00
parent 8050d67b18
commit a952f571b9
26 changed files with 1661 additions and 113 deletions
+78
View File
@@ -0,0 +1,78 @@
"use client";
import { motion } from "framer-motion";
import Image from "next/image";
export default function About({ dict }: { dict: any }) {
const stats = [
{ value: "5+", label: dict.about.stats.years },
{ value: "10K+", label: dict.about.stats.guests },
{ value: "4.8★", label: dict.about.stats.rating },
];
return (
<section id="about" className="py-24 bg-sand-light text-sea-dark overflow-hidden">
<div className="container mx-auto px-6 max-w-6xl">
<div className="grid md:grid-cols-2 gap-16 items-center">
{/* Text side */}
<motion.div
initial={{ opacity: 0, x: -50 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.8 }}
className="space-y-6"
>
{/* Label with decorative lines */}
<div className="flex items-center gap-3">
<span className="w-8 h-px bg-coral" />
<h2 className="text-sm font-bold tracking-widest uppercase text-coral">{dict.about.title}</h2>
<span className="w-8 h-px bg-coral" />
</div>
<h3 className="text-4xl md:text-5xl font-serif leading-tight" dangerouslySetInnerHTML={{ __html: dict.about.heading }}></h3>
<p className="text-base opacity-75 leading-relaxed">
{dict.about.p1}
</p>
<p className="text-base opacity-75 leading-relaxed">
{dict.about.p2}
</p>
{/* Stats row */}
<div className="grid grid-cols-3 gap-6 pt-6 border-t border-sand-dark/40">
{stats.map((stat) => (
<div key={stat.label} className="text-center">
<div className="text-2xl md:text-3xl font-serif font-bold text-sea-dark">{stat.value}</div>
<div className="text-xs text-gray-500 uppercase tracking-wide mt-1">{stat.label}</div>
</div>
))}
</div>
</motion.div>
{/* Image side */}
<motion.div
initial={{ opacity: 0, x: 50 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.8, delay: 0.2 }}
className="relative h-[520px] w-full"
>
{/* Shadow shape behind */}
<div className="absolute inset-0 bg-sand-dark/25 rounded-t-full rounded-br-full transform translate-x-5 translate-y-5" />
{/* Image clipped to shape */}
<div className="absolute inset-0 rounded-t-full rounded-br-full overflow-hidden shadow-2xl">
<Image
src="/moy-beach.jpg"
alt="Moy Beach Atmosphere"
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
</motion.div>
</div>
</div>
</section>
);
}
+86
View File
@@ -0,0 +1,86 @@
"use client";
import { MapPin, Phone, Mail, Clock } from "lucide-react";
export default function Contact({ dict }: { dict: any }) {
return (
<section id="contact" className="py-24 bg-sand-light text-sea-dark relative">
<div className="container mx-auto px-6 max-w-7xl">
<div className="text-center mb-16">
<h2 className="text-sm font-bold tracking-widest uppercase text-coral mb-4">{dict.contact.title}</h2>
<h3 className="text-4xl md:text-5xl font-serif">{dict.contact.heading}</h3>
</div>
<div className="grid lg:grid-cols-2 gap-12 items-start">
{/* İletişim Bilgileri */}
<div className="space-y-8">
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-white rounded-full flex items-center justify-center shrink-0 shadow-md">
<MapPin className="text-coral w-6 h-6" />
</div>
<div>
<h4 className="font-bold text-xl mb-2 font-serif">{dict.contact.address.title}</h4>
<p className="text-gray-600 leading-relaxed">
{dict.contact.address.text1}<br />
{dict.contact.address.text2}
</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-white rounded-full flex items-center justify-center shrink-0 shadow-md">
<Phone className="text-coral w-6 h-6" />
</div>
<div>
<h4 className="font-bold text-xl mb-2 font-serif">{dict.contact.phone}</h4>
<p className="text-gray-600">
<a href="tel:+905344656235" className="hover:text-coral transition-colors">+90 534 465 62 35</a>
</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-white rounded-full flex items-center justify-center shrink-0 shadow-md">
<Mail className="text-coral w-6 h-6" />
</div>
<div>
<h4 className="font-bold text-xl mb-2 font-serif">{dict.contact.email}</h4>
<p className="text-gray-600">
<a href="mailto:info@moybeachakyaka.com" className="hover:text-coral transition-colors">info@moybeachakyaka.com</a>
</p>
</div>
</div>
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-white rounded-full flex items-center justify-center shrink-0 shadow-md">
<Clock className="text-coral w-6 h-6" />
</div>
<div>
<h4 className="font-bold text-xl mb-2 font-serif">{dict.contact.hours.title}</h4>
<p className="text-gray-600">
{dict.contact.hours.text}
</p>
</div>
</div>
</div>
{/* Google Maps Embed */}
<div className="w-full h-[400px] lg:h-full min-h-[400px] bg-gray-200 rounded-2xl overflow-hidden shadow-lg border-4 border-white">
<iframe
src="https://maps.google.com/maps?hl=tr&gl=TR&cid=17585469489776666725&output=embed"
width="100%"
height="100%"
style={{ border: 0 }}
allowFullScreen={false}
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
title="Moy Beach Konum"
/>
</div>
</div>
</div>
</section>
);
}
+163
View File
@@ -0,0 +1,163 @@
"use client";
const socials = [
{
label: "Instagram",
href: "https://instagram.com/moybeachakyaka",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} className="w-5 h-5">
<rect x="2" y="2" width="20" height="20" rx="5" ry="5" />
<circle cx="12" cy="12" r="4" />
<circle cx="17.5" cy="6.5" r="0.5" fill="currentColor" stroke="none" />
</svg>
),
},
{
label: "Facebook",
href: "https://facebook.com/moybeachakyaka",
icon: (
<svg viewBox="0 0 24 24" fill="currentColor" className="w-5 h-5">
<path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
</svg>
),
},
{
label: "YouTube",
href: "https://youtube.com/@moybeach",
icon: (
<svg viewBox="0 0 24 24" fill="currentColor" className="w-5 h-5">
<path d="M22.54 6.42a2.78 2.78 0 0 0-1.95-1.96C18.88 4 12 4 12 4s-6.88 0-8.59.46A2.78 2.78 0 0 0 1.46 6.42 29 29 0 0 0 1 12a29 29 0 0 0 .46 5.58 2.78 2.78 0 0 0 1.95 1.96C5.12 20 12 20 12 20s6.88 0 8.59-.46a2.78 2.78 0 0 0 1.96-1.96A29 29 0 0 0 23 12a29 29 0 0 0-.46-5.58z" />
<polygon points="9.75 15.02 15.5 12 9.75 8.98 9.75 15.02" fill="white" />
</svg>
),
},
];
export default function Footer({ dict }: { dict: any }) {
const links = [
{ label: dict.nav.about, href: "#about" },
{ label: dict.nav.services, href: "#services" },
{ label: dict.nav.gallery, href: "#gallery" },
{ label: dict.nav.contact, href: "#contact" },
];
return (
<footer className="relative bg-sea-dark text-sand-light overflow-hidden">
{/* Large decorative brand name — background texture */}
<div className="absolute inset-x-0 top-0 flex items-start justify-center pointer-events-none select-none overflow-hidden">
<span className="text-[clamp(6rem,20vw,18rem)] font-serif text-white/[0.03] leading-none tracking-tight whitespace-nowrap">
MOY BEACH
</span>
</div>
<div className="relative z-10">
{/* Top section */}
<div className="container mx-auto px-6 max-w-6xl pt-20 pb-14">
<div className="grid md:grid-cols-3 gap-12 items-start">
{/* Brand column */}
<div className="md:col-span-1">
<p className="text-2xl md:text-3xl font-serif text-white tracking-wide mb-3">MOY BEACH</p>
<p className="text-xs uppercase tracking-[0.3em] text-coral mb-6">Akyaka · Muğla</p>
<p className="text-sm text-sand-light/60 leading-relaxed mb-8">
{dict.footer.desc}
</p>
{/* Social icons */}
<div className="flex gap-3">
{socials.map((s) => (
<a
key={s.label}
href={s.href}
target="_blank"
rel="noreferrer"
aria-label={s.label}
className="w-10 h-10 rounded-full border border-white/10 flex items-center justify-center text-sand-light/60 hover:text-white hover:border-coral hover:bg-coral/10 transition-all duration-300"
>
{s.icon}
</a>
))}
</div>
</div>
{/* Navigation column */}
<div>
<h4 className="text-[11px] uppercase tracking-[0.25em] text-sand-dark mb-5">{dict.footer.pages}</h4>
<ul className="space-y-3">
{links.map((l) => (
<li key={l.label}>
<a
href={l.href}
className="text-sm text-sand-light/65 hover:text-white transition-colors duration-200 flex items-center gap-2 group"
>
<span className="w-0 group-hover:w-3 h-px bg-coral transition-all duration-300 shrink-0" />
{l.label}
</a>
</li>
))}
</ul>
</div>
{/* Contact column */}
<div>
<h4 className="text-[11px] uppercase tracking-[0.25em] text-sand-dark mb-5">{dict.footer.contact}</h4>
<ul className="space-y-4 text-sm text-sand-light/65">
<li className="leading-relaxed">
{dict.contact.address.text1}<br />
{dict.contact.address.text2}
</li>
<li>
<a href="tel:+905344656235" className="hover:text-white transition-colors">
+90 534 465 62 35
</a>
</li>
<li>
<a href="mailto:info@moybeachakyaka.com" className="hover:text-white transition-colors">
info@moybeachakyaka.com
</a>
</li>
<li className="text-sand-light/45">{dict.contact.hours.text}</li>
</ul>
</div>
</div>
</div>
{/* Divider */}
<div className="border-t border-white/[0.07]" />
{/* Bottom bar */}
<div className="container mx-auto px-6 max-w-6xl py-6 flex flex-col sm:flex-row justify-between items-center gap-3 text-[11px] text-sand-light/35">
<p>&copy; {new Date().getFullYear()} {dict.footer.rights}</p>
<div className="flex items-center gap-4">
<span>{dict.footer.created_by}</span>
<a
href="https://ayris.tech"
target="_blank"
rel="noreferrer"
className="hover:text-sand-light/70 transition-colors underline underline-offset-4"
>
ayris.tech
</a>
</div>
</div>
</div>
{/* Floating WhatsApp Button */}
<a
href="https://wa.me/905344656235"
target="_blank"
rel="noreferrer"
className="fixed bottom-6 right-6 z-50 bg-[#25D366] text-white p-3.5 rounded-full shadow-xl hover:scale-110 transition-transform"
aria-label="WhatsApp ile iletişime geçin"
>
<svg viewBox="0 0 24 24" className="w-6 h-6 fill-current">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a12.8 12.8 0 0 0-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413Z" />
</svg>
</a>
</footer>
);
}
+136
View File
@@ -0,0 +1,136 @@
"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { X, ZoomIn } from "lucide-react";
import Image from "next/image";
const photos = [
{ id: 1, categoryKey: "beach", url: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?auto=format&fit=crop&q=80&w=1200" },
{ id: 2, categoryKey: "rooms", url: "https://images.unsplash.com/photo-1611892440504-42a792e24d32?auto=format&fit=crop&q=80&w=1200" },
{ id: 3, categoryKey: "restaurant", url: "https://images.unsplash.com/photo-1414235077428-338989a2e8c0?auto=format&fit=crop&q=80&w=1200" },
{ id: 4, categoryKey: "beach", url: "https://images.unsplash.com/photo-1519046904884-53103b34b206?auto=format&fit=crop&q=80&w=1200" },
{ id: 5, categoryKey: "events", url: "https://images.unsplash.com/photo-1511285560929-80b456fea0bc?auto=format&fit=crop&q=80&w=1200" },
{ id: 6, categoryKey: "restaurant", url: "https://images.unsplash.com/photo-1555396273-367ea4eb4db5?auto=format&fit=crop&q=80&w=1200" },
];
export default function Gallery({ dict }: { dict: any }) {
const categories = [
{ key: "all", label: dict.gallery.categories.all },
{ key: "beach", label: dict.gallery.categories.beach },
{ key: "restaurant", label: dict.gallery.categories.restaurant },
{ key: "rooms", label: dict.gallery.categories.rooms },
{ key: "events", label: dict.gallery.categories.events }
];
const [activeCategoryKey, setActiveCategoryKey] = useState("all");
const [selectedImage, setSelectedImage] = useState<string | null>(null);
const filteredPhotos =
activeCategoryKey === "all"
? photos
: photos.filter((p) => p.categoryKey === activeCategoryKey);
return (
<section id="gallery" className="py-24 bg-sand-light text-sea-dark">
<div className="container mx-auto px-6 max-w-7xl">
<div className="text-center mb-12">
<div className="flex items-center justify-center gap-3 mb-4">
<span className="w-8 h-px bg-coral" />
<h2 className="text-sm font-bold tracking-widest uppercase text-coral">{dict.gallery.title}</h2>
<span className="w-8 h-px bg-coral" />
</div>
<h3 className="text-4xl md:text-5xl font-serif mb-10">{dict.gallery.heading}</h3>
{/* Category filters */}
<div className="flex flex-wrap justify-center gap-3 mb-12">
{categories.map((cat) => (
<button
key={cat.key}
onClick={() => setActiveCategoryKey(cat.key)}
className={`px-5 py-2 rounded-full text-xs tracking-widest uppercase font-medium transition-all duration-300 ${
activeCategoryKey === cat.key
? "bg-sea-dark text-white shadow-md"
: "bg-white text-sea-dark border border-sand-dark/30 hover:border-sea-dark hover:bg-sea-dark/5"
}`}
>
{cat.label}
</button>
))}
</div>
</div>
<motion.div layout className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
<AnimatePresence mode="popLayout">
{filteredPhotos.map((photo) => (
<motion.div
key={photo.id}
layout
initial={{ opacity: 0, scale: 0.92 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.92 }}
transition={{ duration: 0.3 }}
className="relative h-72 cursor-pointer overflow-hidden rounded-2xl group shadow-sm hover:shadow-lg hover:shadow-sea-dark/10 transition-shadow duration-500"
onClick={() => setSelectedImage(photo.url)}
>
<Image
src={photo.url}
alt={dict.gallery.categories[photo.categoryKey]}
fill
className="object-cover transform group-hover:scale-108 transition-transform duration-700"
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
style={{ transform: "scale(1)", transition: "transform 700ms" }}
/>
{/* Hover overlay */}
<div className="absolute inset-0 bg-sea-dark/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10 flex items-center justify-center">
<div className="flex flex-col items-center gap-2 text-white">
<ZoomIn size={28} />
<span className="text-[10px] uppercase tracking-[0.25em]">{dict.gallery.categories[photo.categoryKey]}</span>
</div>
</div>
</motion.div>
))}
</AnimatePresence>
</motion.div>
</div>
{/* Lightbox */}
<AnimatePresence>
{selectedImage && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-[100] bg-black/92 flex items-center justify-center p-4"
onClick={() => setSelectedImage(null)}
>
<button
className="absolute top-6 right-6 text-white/70 hover:text-white transition-colors bg-white/10 hover:bg-white/20 p-2.5 rounded-full backdrop-blur-sm"
onClick={() => setSelectedImage(null)}
aria-label="Kapat"
>
<X size={20} />
</button>
<motion.div
initial={{ scale: 0.88, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.88, opacity: 0 }}
transition={{ duration: 0.25, ease: [0.22, 1, 0.36, 1] }}
className="relative max-w-4xl max-h-[88vh] w-full h-full"
onClick={(e) => e.stopPropagation()}
>
<Image
src={selectedImage}
alt="Büyütülmüş Görsel"
fill
className="object-contain rounded-lg"
sizes="100vw"
/>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</section>
);
}
+94
View File
@@ -0,0 +1,94 @@
"use client";
import { useState, useEffect } from "react";
import { Menu, X } from "lucide-react";
export default function Header({ dict, lang }: { dict: any, lang: string }) {
const [isScrolled, setIsScrolled] = useState(false);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
const navLinks = [
{ name: dict.nav.about, href: "#about" },
{ name: dict.nav.services, href: "#services" },
{ name: dict.nav.gallery, href: "#gallery" },
{ name: dict.nav.contact, href: "#contact" },
];
return (
<header
className={`fixed top-0 w-full z-50 transition-all duration-300 ${
isScrolled ? "bg-white/95 backdrop-blur-md shadow-sm py-4" : "bg-transparent py-6"
}`}
>
<div className="container mx-auto px-4 md:px-6 flex justify-between items-center">
<a href="#" className="flex items-center">
<img
src="/logo.png"
alt="Moy Beach Logo"
className={`h-12 w-auto transition-all duration-300 ${!isScrolled ? "brightness-0 invert opacity-90" : ""}`}
/>
</a>
{/* Desktop Nav */}
<nav className="hidden md:flex items-center space-x-8">
{navLinks.map((link) => (
<a
key={link.name}
href={link.href}
className={`text-sm tracking-wide hover:text-coral transition-colors ${
isScrolled ? "text-sea-dark" : "text-white"
}`}
>
{link.name}
</a>
))}
<div className={`flex items-center gap-2 text-sm font-medium ${isScrolled ? "text-sea-dark" : "text-white"}`}>
<a href="/tr" className={`cursor-pointer hover:text-coral ${lang === 'tr' ? 'opacity-100 font-bold' : 'opacity-70'}`}>TR</a>
<span className="opacity-50">/</span>
<a href="/en" className={`cursor-pointer hover:text-coral ${lang === 'en' ? 'opacity-100 font-bold' : 'opacity-70'}`}>EN</a>
</div>
</nav>
{/* Mobile Menu Toggle */}
<button
className="md:hidden"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
{mobileMenuOpen ? (
<X className={isScrolled ? "text-sea-dark" : "text-white"} />
) : (
<Menu className={isScrolled ? "text-sea-dark" : "text-white"} />
)}
</button>
</div>
{/* Mobile Nav */}
{mobileMenuOpen && (
<div className="md:hidden absolute top-full left-0 w-full bg-white shadow-xl flex flex-col py-4 px-6 space-y-4">
{navLinks.map((link) => (
<a
key={link.name}
href={link.href}
className="text-sea-dark text-lg py-2 border-b border-gray-100"
onClick={() => setMobileMenuOpen(false)}
>
{link.name}
</a>
))}
<div className="flex gap-4 pt-2">
<a href="/tr" className={`font-medium cursor-pointer ${lang === 'tr' ? 'text-sea-dark font-bold' : 'text-gray-400'}`}>TR</a>
<a href="/en" className={`font-medium cursor-pointer ${lang === 'en' ? 'text-sea-dark font-bold' : 'text-gray-400'}`}>EN</a>
</div>
</div>
)}
</header>
);
}
+141
View File
@@ -0,0 +1,141 @@
"use client";
import { motion } from "framer-motion";
import { ChevronDown } from "lucide-react";
import Image from "next/image";
export default function Hero({ dict }: { dict: any }) {
const words = ["MOY", "BEACH"];
return (
<section className="relative h-screen w-full flex items-center justify-center overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<Image
src="https://images.unsplash.com/photo-1590523277543-a94d2e4eb00b?auto=format&fit=crop&q=85&w=2400"
alt="Moy Beach Akyaka"
fill
className="object-cover object-center"
priority
sizes="100vw"
/>
</div>
{/* Multi-layer gradient for depth */}
<div className="absolute inset-0 bg-gradient-to-b from-sea-dark/55 via-black/15 to-sea-dark/70 z-10" />
<div className="absolute inset-0 bg-gradient-to-r from-sea-dark/20 via-transparent to-sea-dark/20 z-10" />
{/* Main Content */}
<div className="relative z-20 text-center px-4 max-w-5xl mx-auto">
{/* Location badge */}
<motion.p
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 1.4, delay: 0.1 }}
className="text-sand/60 text-[11px] md:text-xs uppercase tracking-[0.45em] mb-6 font-light"
>
Akyaka · Muğla · Türkiye
</motion.p>
{/* Decorative line */}
<motion.div
initial={{ scaleX: 0 }}
animate={{ scaleX: 1 }}
transition={{ duration: 0.7, delay: 0.25 }}
className="w-12 h-px bg-coral mx-auto mb-8 origin-center"
/>
{/* Main Title — word-by-word reveal */}
<h1 className="text-[4.5rem] md:text-[8rem] lg:text-[11rem] font-serif text-white leading-none tracking-tight mb-6">
{words.map((word, i) => (
<span key={word} className="inline-block overflow-hidden">
<motion.span
initial={{ y: 110, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{
duration: 0.9,
delay: 0.4 + i * 0.2,
ease: [0.22, 1, 0.36, 1],
}}
className="inline-block"
>
{word}
</motion.span>
{i === 0 && (
<span className="inline-block w-4 md:w-8 lg:w-12" />
)}
</span>
))}
</h1>
{/* Subtitle */}
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1, delay: 1.0 }}
className="text-lg md:text-2xl text-sand-light font-light tracking-wide mb-12 drop-shadow-md"
>
{dict.hero.subtitle}
</motion.p>
{/* CTA Buttons */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 1.35 }}
className="flex flex-wrap items-center justify-center gap-4"
>
<a
href="#about"
className="border border-white/50 hover:border-white text-white px-8 py-3.5 rounded-full text-sm tracking-widest uppercase font-medium transition-all hover:bg-white/10 backdrop-blur-sm"
>
{dict.hero.explore}
</a>
</motion.div>
</div>
{/* Scroll Indicator — direct child of section, correctly positioned */}
<motion.a
href="#about"
className="absolute bottom-20 left-1/2 -translate-x-1/2 z-20 text-white flex flex-col items-center gap-2 cursor-pointer"
initial={{ opacity: 0 }}
animate={{ opacity: 0.65 }}
transition={{ duration: 1, delay: 2.2 }}
whileHover={{ opacity: 1 }}
aria-label="Aşağı kaydır"
>
<span className="text-[9px] uppercase tracking-[0.35em] font-light">Kaydır</span>
<motion.div
animate={{ y: [0, 7, 0] }}
transition={{
duration: 1.6,
repeat: Infinity,
repeatType: "loop",
ease: "easeInOut",
delay: 2.6,
}}
>
<ChevronDown size={18} />
</motion.div>
</motion.a>
{/* Wave divider into About section */}
<div className="absolute bottom-0 left-0 right-0 z-20 leading-none pointer-events-none">
<svg
viewBox="0 0 1440 56"
fill="none"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="none"
className="w-full h-14 block"
>
<path
d="M0,28 C360,56 720,0 1080,28 C1260,42 1380,14 1440,28 L1440,56 L0,56 Z"
fill="#F4EFEB"
/>
</svg>
</div>
</section>
);
}
+88
View File
@@ -0,0 +1,88 @@
"use client";
const reels = [
{ id: 1, url: "https://www.instagram.com/reel/C97iqFqoSyl/embed" },
{ id: 2, url: "https://www.instagram.com/reel/C-slzOcIQB3/embed" },
{ id: 3, url: "https://www.instagram.com/reel/DLM8ng6MOKf/embed" },
{ id: 4, url: "https://www.instagram.com/reel/DX-BDErM5qd/embed" },
];
function InstagramIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} className="w-4 h-4">
<rect x="2" y="2" width="20" height="20" rx="5" ry="5" />
<circle cx="12" cy="12" r="4" />
<circle cx="17.5" cy="6.5" r="0.8" fill="currentColor" stroke="none" />
</svg>
);
}
export default function InstagramFeed({ dict }: { dict: any }) {
return (
<section className="py-24 bg-sand-light text-sea-dark overflow-hidden">
<div className="container mx-auto px-6 max-w-7xl">
{/* Header */}
<div className="text-center mb-14">
<div className="flex items-center justify-center gap-3 mb-4">
<span className="w-8 h-px bg-coral" />
<h2 className="text-sm font-bold tracking-widest uppercase text-coral flex items-center gap-2">
<InstagramIcon />
{dict.social.title}
</h2>
<span className="w-8 h-px bg-coral" />
</div>
<h3 className="text-4xl md:text-5xl font-serif mb-5">{dict.social.heading}</h3>
<a
href="https://www.instagram.com/moy_akyaka/"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-sm text-sea-dark/60 hover:text-coral transition-colors tracking-wide"
>
<InstagramIcon />
@moy_akyaka
</a>
</div>
{/* Reels grid */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 md:gap-6">
{reels.map((reel) => (
<div
key={reel.id}
className="group relative bg-white rounded-2xl overflow-hidden shadow-sm hover:shadow-xl hover:shadow-sea-dark/10 transition-all duration-500 hover:-translate-y-1"
>
{/* Thin coral top border accent */}
<div className="absolute top-0 left-0 right-0 h-[2px] bg-gradient-to-r from-coral/0 via-coral to-coral/0 opacity-0 group-hover:opacity-100 transition-opacity duration-500 z-10" />
<iframe
src={reel.url}
className="w-full h-[520px] md:h-[580px]"
style={{ border: "none", display: "block" }}
scrolling="no"
frameBorder="0"
allow="encrypted-media"
title={`Instagram Reel ${reel.id}`}
/>
</div>
))}
</div>
{/* CTA */}
<div className="text-center mt-12">
<a
href="https://www.instagram.com/moy_akyaka/"
target="_blank"
rel="noopener noreferrer"
className="btn-shimmer inline-flex items-center gap-2.5 bg-sea-dark hover:bg-sea-blue text-white px-8 py-3.5 rounded-full text-sm tracking-widest uppercase font-medium transition-colors shadow-md hover:shadow-lg"
>
<InstagramIcon />
{dict.social.button}
</a>
</div>
</div>
</section>
);
}
+108
View File
@@ -0,0 +1,108 @@
"use client";
import { motion } from "framer-motion";
import { Calendar, Users, Coffee } from "lucide-react";
export default function Reservation() {
return (
<section id="reservation" className="py-24 bg-white relative overflow-hidden">
{/* Decorative background blobs */}
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-sand-light rounded-full blur-3xl opacity-60 -translate-y-1/2 translate-x-1/3 pointer-events-none" />
<div className="absolute bottom-0 left-0 w-[380px] h-[380px] bg-coral-light/15 rounded-full blur-3xl opacity-50 translate-y-1/2 -translate-x-1/3 pointer-events-none" />
<div className="container mx-auto px-6 max-w-5xl relative z-10">
<div className="bg-sea-dark rounded-[2.5rem] p-8 md:p-14 shadow-2xl overflow-hidden relative">
{/* Inner glow */}
<div className="absolute top-0 right-0 w-72 h-72 bg-sea-light rounded-full blur-3xl opacity-25 -translate-y-1/2 translate-x-1/2 pointer-events-none" />
<div className="text-center mb-12 relative z-10 text-white">
<div className="flex items-center justify-center gap-3 mb-4">
<span className="w-8 h-px bg-coral/70" />
<h2 className="text-sm font-bold tracking-widest uppercase text-coral">Hemen Yerinizi Ayırtın</h2>
<span className="w-8 h-px bg-coral/70" />
</div>
<h3 className="text-4xl md:text-5xl font-serif mb-4">Rezervasyon Talebi</h3>
<p className="text-sand-light/80 max-w-2xl mx-auto text-sm leading-relaxed">
Unutulmaz bir Ege deneyimi için hemen formumuzu doldurun, ekibimiz en kısa sürede sizinle iletişime geçsin.
</p>
</div>
<motion.form
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
className="relative z-10 bg-white p-7 md:p-10 rounded-2xl shadow-xl max-w-4xl mx-auto"
onSubmit={(e) => e.preventDefault()}
>
<div className="grid md:grid-cols-3 gap-5 mb-6">
{/* Date */}
<div className="space-y-1.5">
<label className="text-xs font-semibold text-gray-600 uppercase tracking-wide flex items-center gap-1.5">
<Calendar size={13} className="text-coral" /> Tarih
</label>
<input
type="date"
className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-coral/40 focus:border-coral transition-colors text-sm"
/>
</div>
{/* Guests */}
<div className="space-y-1.5">
<label className="text-xs font-semibold text-gray-600 uppercase tracking-wide flex items-center gap-1.5">
<Users size={13} className="text-coral" /> Kişi Sayısı
</label>
<select className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-coral/40 focus:border-coral transition-colors bg-white text-sm">
<option>1 Kişi</option>
<option>2 Kişi</option>
<option>3 Kişi</option>
<option>4 Kişi</option>
<option>5+ Kişi</option>
</select>
</div>
{/* Service type */}
<div className="space-y-1.5">
<label className="text-xs font-semibold text-gray-600 uppercase tracking-wide flex items-center gap-1.5">
<Coffee size={13} className="text-coral" /> Hizmet Tipi
</label>
<select className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-coral/40 focus:border-coral transition-colors bg-white text-sm">
<option>Beach Club (Şezlong/Loca)</option>
<option>Restoran Akşam Yemeği</option>
<option>Konaklama</option>
<option>Özel Etkinlik / Organizasyon</option>
</select>
</div>
</div>
<div className="grid md:grid-cols-2 gap-5 mb-7">
<input
type="text"
placeholder="Adınız Soyadınız"
className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-coral/40 focus:border-coral transition-colors text-sm"
/>
<input
type="tel"
placeholder="Telefon Numaranız"
className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-coral/40 focus:border-coral transition-colors text-sm"
/>
</div>
{/* Shimmer submit button */}
<button
type="submit"
className="btn-shimmer w-full bg-coral hover:bg-coral-dark text-white font-medium py-4 rounded-xl transition-colors shadow-lg hover:shadow-xl text-sm tracking-wide uppercase"
>
Rezervasyon Talebi Gönder
</button>
<p className="text-[11px] text-center text-gray-400 mt-4">
Bu form ön rezervasyon talebidir. Kesin onay için ekibimiz sizinle iletişime geçecektir.
</p>
</motion.form>
</div>
</div>
</section>
);
}
+91
View File
@@ -0,0 +1,91 @@
"use client";
import { motion } from "framer-motion";
import { Waves, UtensilsCrossed, Hotel, CalendarHeart } from "lucide-react";
import Image from "next/image";
export default function Services({ dict }: { dict: any }) {
const services = [
{
title: dict.services.items.beach.title,
description: dict.services.items.beach.description,
icon: Waves,
image: "https://images.unsplash.com/photo-1519046904884-53103b34b206?auto=format&fit=crop&q=80&w=800",
},
{
title: dict.services.items.restaurant.title,
description: dict.services.items.restaurant.description,
icon: UtensilsCrossed,
image: "https://images.unsplash.com/photo-1544148103-0773bf10d330?auto=format&fit=crop&q=80&w=800",
},
{
title: dict.services.items.hotel.title,
description: dict.services.items.hotel.description,
icon: Hotel,
image: "https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?auto=format&fit=crop&q=80&w=800",
},
{
title: dict.services.items.events.title,
description: dict.services.items.events.description,
icon: CalendarHeart,
image: "https://images.unsplash.com/photo-1511285560929-80b456fea0bc?auto=format&fit=crop&q=80&w=800",
},
];
return (
<section id="services" className="py-24 bg-white text-sea-dark">
<div className="container mx-auto px-6 max-w-7xl">
<div className="text-center mb-16">
<div className="flex items-center justify-center gap-3 mb-4">
<span className="w-8 h-px bg-coral" />
<h2 className="text-sm font-bold tracking-widest uppercase text-coral">{dict.services.title}</h2>
<span className="w-8 h-px bg-coral" />
</div>
<h3 className="text-4xl md:text-5xl font-serif">{dict.services.heading}</h3>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
{services.map((service, index) => (
<motion.div
key={service.title}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-50px" }}
transition={{ duration: 0.6, delay: index * 0.1 }}
className="group cursor-pointer"
>
{/* Image card with gradient border on hover */}
<div className="relative mb-6">
{/* Border beam — visible on hover */}
<div className="absolute -inset-[1px] rounded-2xl bg-gradient-to-br from-coral/0 to-coral/0 group-hover:from-coral/50 group-hover:to-sea-light/40 transition-all duration-500 opacity-0 group-hover:opacity-100 z-0" />
<div className="relative h-80 overflow-hidden rounded-2xl shadow-md group-hover:shadow-lg group-hover:shadow-coral/15 transition-shadow duration-500 z-10">
<div className="absolute inset-0 bg-sea-dark/20 group-hover:bg-transparent transition-colors duration-500 z-10" />
<Image
src={service.image}
alt={service.title}
fill
className="object-cover transform group-hover:scale-110 transition-transform duration-700"
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 25vw"
/>
{/* Icon badge */}
<div className="absolute top-4 left-4 z-20 bg-white/90 backdrop-blur-sm p-3 rounded-full shadow-lg ring-2 ring-coral/10 group-hover:ring-coral/50 transition-all duration-300">
<service.icon className="w-5 h-5 text-coral" />
</div>
</div>
</div>
<h4 className="text-xl font-serif mb-2 group-hover:text-coral transition-colors duration-300">
{service.title}
</h4>
<p className="text-sm text-gray-500 leading-relaxed">{service.description}</p>
</motion.div>
))}
</div>
</div>
</section>
);
}
+122
View File
@@ -0,0 +1,122 @@
"use client";
import { motion } from "framer-motion";
import { Star, Quote, Play } from "lucide-react";
import Image from "next/image";
const testimonials = [
{
name: "Ayşe Y.",
platform: "Google Yorumu",
text: "Ege'de gördüğüm en kaliteli mekanlardan biri. Yemekler harika, denizi zaten muhteşem. Özellikle kokteyllerini denemelisiniz.",
rating: 5,
},
{
name: "David M.",
platform: "TripAdvisor",
text: "Mükemmel bir deneyimdi. Ailece geldik ve çocuklar da biz de çok eğlendik. Personel çok ilgili ve güler yüzlüydü.",
rating: 5,
},
{
name: "Caner K.",
platform: "Google Yorumu",
text: "Harika bir atmosfer. Akşam yemeği için tercih ettik, gün batımı manzarası eşliğinde unutulmaz bir anı oldu.",
rating: 4,
},
];
export default function VideoTestimonials() {
return (
<section className="bg-sea-dark text-white overflow-hidden relative">
<div className="grid lg:grid-cols-2">
{/* Video / Image Panel */}
<div className="relative h-[50vh] lg:h-auto min-h-[500px] overflow-hidden">
<Image
src="https://images.unsplash.com/photo-1507525428034-b723cf961d3e?auto=format&fit=crop&q=80&w=1200"
alt="Moy Beach Video"
fill
className="object-cover"
sizes="(max-width: 1024px) 100vw, 50vw"
/>
<div className="absolute inset-0 bg-sea-dark/50 z-10" />
{/* Play button overlay */}
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center gap-6 p-8 text-center">
<a
href="https://www.youtube.com/@moybeach"
target="_blank"
rel="noreferrer"
className="group w-20 h-20 bg-white/15 hover:bg-white/25 border-2 border-white/60 hover:border-white rounded-full flex items-center justify-center transition-all duration-300 hover:scale-110 backdrop-blur-sm"
aria-label="Videoyu izle"
>
<Play className="w-7 h-7 text-white ml-1 group-hover:scale-110 transition-transform" fill="white" />
</a>
<p className="text-sand/80 text-sm tracking-wide">Moy Beach&apos;i Keşfedin</p>
</div>
</div>
{/* Testimonials Panel */}
<div className="py-20 px-8 lg:px-14 flex flex-col justify-center">
<div className="flex items-center gap-3 mb-4">
<span className="w-8 h-px bg-coral" />
<h2 className="text-sm font-bold tracking-widest uppercase text-coral">Referanslar</h2>
</div>
<h3 className="text-4xl md:text-5xl font-serif mb-10">Misafirlerimiz<br />Ne Diyor?</h3>
<div className="space-y-6">
{testimonials.map((testimonial, index) => (
<motion.div
key={index}
initial={{ opacity: 0, x: 40 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, delay: index * 0.15 }}
className="bg-white/6 hover:bg-white/10 p-6 rounded-2xl relative border border-white/5 hover:border-white/10 transition-colors duration-300"
>
<Quote className="absolute top-5 right-6 text-coral/20 w-10 h-10" />
{/* Stars */}
<div className="flex text-coral mb-3">
{[...Array(5)].map((_, i) => (
<Star
key={i}
className={`w-3.5 h-3.5 ${i < testimonial.rating ? "fill-current" : "opacity-25"}`}
/>
))}
</div>
<p className="text-base italic text-sand-light/90 mb-5 leading-relaxed">
&quot;{testimonial.text}&quot;
</p>
<div className="flex items-center gap-3">
<div className="w-9 h-9 bg-coral rounded-full flex items-center justify-center font-bold text-sm shrink-0">
{testimonial.name.charAt(0)}
</div>
<div>
<p className="font-medium text-sm">{testimonial.name}</p>
<p className="text-xs text-gray-400">{testimonial.platform}</p>
</div>
</div>
</motion.div>
))}
</div>
{/* Aggregate rating */}
<div className="mt-8 flex items-center gap-4 pt-6 border-t border-white/10">
<div className="flex items-baseline gap-1">
<span className="text-3xl font-bold font-serif">4.8</span>
<span className="text-coral text-lg">/ 5</span>
</div>
<p className="text-sm text-gray-400 leading-snug">
Google &amp; TripAdvisor değerlendirmelerine göre
<br />
<span className="text-sand/60">(150+ Yorum)</span>
</p>
</div>
</div>
</div>
</section>
);
}