first commit
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Waves, Leaf, Music } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
|
||||
const features = [
|
||||
{ icon: Waves, titleKey: 'card1_title', descKey: 'card1_desc', color: 'text-aqua', bg: 'bg-aqua/10' },
|
||||
{ icon: Leaf, titleKey: 'card2_title', descKey: 'card2_desc', color: 'text-amber', bg: 'bg-amber/10' },
|
||||
{ icon: Music, titleKey: 'card3_title', descKey: 'card3_desc', color: 'text-coral', bg: 'bg-coral/10' },
|
||||
];
|
||||
|
||||
export default function About() {
|
||||
const t = useTranslations('About');
|
||||
|
||||
return (
|
||||
<section id="about" className="py-28 bg-sand text-midnight relative">
|
||||
<div className="container mx-auto px-6 lg:px-12">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-20 items-center">
|
||||
|
||||
{/* Left content */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className="space-y-8"
|
||||
>
|
||||
<div>
|
||||
<span className="text-xs tracking-[0.4em] uppercase font-black text-coral mb-4 block">
|
||||
— Beach & More
|
||||
</span>
|
||||
<h2 className="font-heading text-5xl md:text-6xl font-black leading-tight text-midnight mb-6">
|
||||
{t('title')}
|
||||
</h2>
|
||||
<p className="text-lg leading-relaxed text-midnight/60">{t('description')}</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
{features.map(({ icon: Icon, titleKey, descKey, color, bg }, i) => (
|
||||
<motion.div
|
||||
key={titleKey}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: i * 0.1 + 0.2 }}
|
||||
className="flex items-start gap-4 p-4 rounded-2xl hover:bg-sandy/50 transition-colors"
|
||||
>
|
||||
<div className={`p-3 rounded-xl ${bg} ${color} flex-shrink-0`}>
|
||||
<Icon size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-heading text-lg font-bold mb-0.5">{t(titleKey)}</h3>
|
||||
<p className="text-midnight/55 text-sm leading-relaxed">{t(descKey)}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Right image */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.95 }}
|
||||
whileInView={{ opacity: 1, scale: 1 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className="relative"
|
||||
>
|
||||
{/* Glow ring */}
|
||||
<div
|
||||
className="absolute inset-0 rounded-3xl opacity-30 blur-2xl scale-105"
|
||||
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827, #00BFA5)' }}
|
||||
/>
|
||||
<div className="relative h-[560px] w-full rounded-3xl overflow-hidden shadow-2xl">
|
||||
<Image
|
||||
src="https://picsum.photos/800/1100?random=2"
|
||||
alt="Kozmos atmosferi"
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 50vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0"
|
||||
style={{ background: 'linear-gradient(to top, rgba(8,13,24,0.35) 0%, transparent 55%)' }}
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion } from 'framer-motion';
|
||||
import Image from 'next/image';
|
||||
import { Users, Check, Sparkles } from 'lucide-react';
|
||||
|
||||
export default function Accommodation() {
|
||||
const t = useTranslations('Accommodation');
|
||||
|
||||
const openWhatsApp = () => {
|
||||
const phone = process.env.NEXT_PUBLIC_WHATSAPP_NUMBER || '905000000000';
|
||||
window.open(`https://wa.me/${phone}`, '_blank');
|
||||
};
|
||||
|
||||
const rooms = [
|
||||
{
|
||||
id: 'standard',
|
||||
image: 'https://picsum.photos/600/400?random=3',
|
||||
capacity: 2,
|
||||
features: t.raw('rooms.standard.features') as string[],
|
||||
featured: false,
|
||||
gradient: 'linear-gradient(135deg, #00BFA5, #00E5FF)',
|
||||
},
|
||||
{
|
||||
id: 'sea_view',
|
||||
image: 'https://picsum.photos/600/400?random=4',
|
||||
capacity: 2,
|
||||
features: t.raw('rooms.sea_view.features') as string[],
|
||||
featured: true,
|
||||
gradient: 'linear-gradient(135deg, #FF5A36, #FFA827)',
|
||||
},
|
||||
{
|
||||
id: 'garden_suite',
|
||||
image: 'https://picsum.photos/600/400?random=5',
|
||||
capacity: 4,
|
||||
features: t.raw('rooms.garden_suite.features') as string[],
|
||||
featured: false,
|
||||
gradient: 'linear-gradient(135deg, #00BFA5, #00E5FF)',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="accommodation" className="py-28 bg-sandy/25 text-midnight">
|
||||
<div className="container mx-auto px-6 lg:px-12">
|
||||
|
||||
<div className="text-center max-w-3xl mx-auto mb-16">
|
||||
<motion.span
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="text-xs tracking-[0.4em] uppercase font-black text-coral mb-4 block"
|
||||
>
|
||||
— Konaklama
|
||||
</motion.span>
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="font-heading text-5xl md:text-6xl font-black mb-6 text-midnight"
|
||||
>
|
||||
{t('title')}
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="text-lg text-midnight/60"
|
||||
>
|
||||
{t('description')}
|
||||
</motion.p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{rooms.map((room, index) => (
|
||||
<motion.div
|
||||
key={room.id}
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: index * 0.1, duration: 0.6 }}
|
||||
className={`relative rounded-3xl overflow-hidden bg-white shadow-lg hover:shadow-2xl transition-all duration-500 hover:-translate-y-1 ${
|
||||
room.featured ? 'outline outline-2 outline-offset-2 outline-coral' : ''
|
||||
}`}
|
||||
>
|
||||
{/* Featured badge */}
|
||||
{room.featured && (
|
||||
<div
|
||||
className="absolute top-4 right-4 z-10 flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[11px] font-black text-white tracking-wider"
|
||||
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827)' }}
|
||||
>
|
||||
<Sparkles size={10} />
|
||||
FEATURED
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Image */}
|
||||
<div className="relative h-52 w-full overflow-hidden">
|
||||
<Image
|
||||
src={room.image}
|
||||
alt={t(`rooms.${room.id}.name`)}
|
||||
fill
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
|
||||
className="object-cover transition-transform duration-700 hover:scale-110"
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0"
|
||||
style={{ background: 'linear-gradient(to top, rgba(8,13,24,0.5), transparent)' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="p-7">
|
||||
<h3 className="font-heading text-xl font-black mb-2 text-midnight">
|
||||
{t(`rooms.${room.id}.name`)}
|
||||
</h3>
|
||||
|
||||
<div className="flex items-center gap-2 text-midnight/45 mb-5 text-sm">
|
||||
<Users size={14} />
|
||||
<span>
|
||||
{t('capacity')} {room.capacity} {t('person')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ul className="space-y-2 mb-7">
|
||||
{room.features.map((feature, i) => (
|
||||
<li key={i} className="flex items-center gap-2.5 text-sm text-midnight/65">
|
||||
<Check size={13} className="text-aqua flex-shrink-0" />
|
||||
<span>{feature}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<button
|
||||
onClick={openWhatsApp}
|
||||
className="w-full py-3.5 rounded-2xl font-black text-sm text-white transition-all duration-300 hover:opacity-90 hover:scale-[1.02]"
|
||||
style={{ background: room.gradient }}
|
||||
>
|
||||
{t('book_whatsapp')}
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion } from 'framer-motion';
|
||||
import Image from 'next/image';
|
||||
import { Sun } from 'lucide-react';
|
||||
|
||||
export default function Beach() {
|
||||
const t = useTranslations('Beach');
|
||||
|
||||
const openWhatsApp = () => {
|
||||
const phone = process.env.NEXT_PUBLIC_WHATSAPP_NUMBER || '905000000000';
|
||||
window.open(
|
||||
`https://wa.me/${phone}?text=Merhaba,%20şezlong%20rezervasyonu%20yaptırmak%20istiyorum.`,
|
||||
'_blank',
|
||||
);
|
||||
};
|
||||
|
||||
const stats = [
|
||||
{ value: '∞', label: 'Şezlong' },
|
||||
{ value: '7/7', label: 'Açık' },
|
||||
{ value: 'VIP', label: 'Cabana' },
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="beach" className="pt-28 pb-36 bg-sand text-midnight relative overflow-hidden">
|
||||
<div className="container mx-auto px-6 lg:px-12">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center">
|
||||
|
||||
{/* Left masonry photos */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="space-y-3"
|
||||
>
|
||||
<div className="relative h-64 rounded-2xl overflow-hidden shadow-md">
|
||||
<Image
|
||||
src="https://picsum.photos/400/600?random=10"
|
||||
alt="Plaj"
|
||||
fill
|
||||
sizes="(max-width: 1024px) 50vw, 25vw"
|
||||
className="object-cover hover:scale-105 transition-transform duration-700"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative h-48 rounded-2xl overflow-hidden shadow-md">
|
||||
<Image
|
||||
src="https://picsum.photos/400/400?random=11"
|
||||
alt="Şezlong"
|
||||
fill
|
||||
sizes="(max-width: 1024px) 50vw, 25vw"
|
||||
className="object-cover hover:scale-105 transition-transform duration-700"
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.15 }}
|
||||
className="space-y-3 pt-8"
|
||||
>
|
||||
<div className="relative h-48 rounded-2xl overflow-hidden shadow-md">
|
||||
<Image
|
||||
src="https://picsum.photos/400/400?random=12"
|
||||
alt="Deniz"
|
||||
fill
|
||||
sizes="(max-width: 1024px) 50vw, 25vw"
|
||||
className="object-cover hover:scale-105 transition-transform duration-700"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative h-64 rounded-2xl overflow-hidden shadow-md">
|
||||
<Image
|
||||
src="https://picsum.photos/400/600?random=13"
|
||||
alt="Koy"
|
||||
fill
|
||||
sizes="(max-width: 1024px) 50vw, 25vw"
|
||||
className="object-cover hover:scale-105 transition-transform duration-700"
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Right content */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7 }}
|
||||
className="space-y-7"
|
||||
>
|
||||
<div className="inline-flex items-center gap-2 font-black text-amber tracking-wider uppercase text-sm">
|
||||
<Sun size={18} />
|
||||
Beach Club
|
||||
</div>
|
||||
|
||||
<h2 className="font-heading text-5xl md:text-6xl font-black text-midnight leading-tight">
|
||||
{t('title')}
|
||||
</h2>
|
||||
|
||||
<p className="text-lg text-midnight/60 leading-relaxed">{t('description')}</p>
|
||||
|
||||
{/* Stats */}
|
||||
<div className="grid grid-cols-3 gap-4 py-6 border-y border-sandy">
|
||||
{stats.map(({ value, label }) => (
|
||||
<div key={label} className="text-center">
|
||||
<div className="font-heading text-2xl font-black gradient-text-warm">{value}</div>
|
||||
<div className="text-[11px] text-midnight/45 mt-1 uppercase tracking-wider">{label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Info & CTA */}
|
||||
<div className="p-6 rounded-2xl bg-sandy/50 border border-sandy">
|
||||
<p className="text-midnight/70 text-sm font-medium mb-5">{t('reservation_info')}</p>
|
||||
<button
|
||||
onClick={openWhatsApp}
|
||||
className="px-8 py-3.5 rounded-full font-black text-sm text-midnight transition-all duration-300 hover:scale-105 hover:shadow-lg"
|
||||
style={{ background: 'linear-gradient(135deg, #FFA827, #FFD166)' }}
|
||||
>
|
||||
{t('book_lounger')}
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Wave → midnight */}
|
||||
<div className="absolute bottom-0 left-0 w-full leading-none pointer-events-none">
|
||||
<svg viewBox="0 0 1440 64" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" className="w-full h-16">
|
||||
<path d="M0,32 C240,64 480,0 720,32 C960,64 1200,0 1440,32 L1440,64 L0,64 Z" fill="#080D18" />
|
||||
</svg>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion } from 'framer-motion';
|
||||
import { MapPin, Phone, Send } from 'lucide-react';
|
||||
import { Instagram } from '@/components/InstagramIcon';
|
||||
import { useState } from 'react';
|
||||
|
||||
export default function Contact() {
|
||||
const t = useTranslations('Contact');
|
||||
const [formData, setFormData] = useState({ name: '', date: '', guests: '', message: '' });
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
const phone = process.env.NEXT_PUBLIC_WHATSAPP_NUMBER || '905000000000';
|
||||
const text = `*Yeni Rezervasyon Talebi*%0A%0A*Ad Soyad:* ${formData.name}%0A*Tarih:* ${formData.date}%0A*Kişi Sayısı:* ${formData.guests}%0A*Mesaj:* ${formData.message}`;
|
||||
window.open(`https://wa.me/${phone}?text=${text}`, '_blank');
|
||||
};
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||
};
|
||||
|
||||
const contactItems = [
|
||||
{
|
||||
Icon: MapPin,
|
||||
label: 'Adres',
|
||||
value: t('address'),
|
||||
color: 'text-coral',
|
||||
bg: 'bg-coral/10',
|
||||
},
|
||||
{
|
||||
Icon: Phone,
|
||||
label: 'Telefon / WhatsApp',
|
||||
value: `+${process.env.NEXT_PUBLIC_WHATSAPP_NUMBER || '90 500 000 00 00'}`,
|
||||
color: 'text-aqua',
|
||||
bg: 'bg-aqua/10',
|
||||
},
|
||||
{
|
||||
Icon: Instagram,
|
||||
label: 'Instagram',
|
||||
value: '@kozmosbeach',
|
||||
href: 'https://www.instagram.com/kozmosbeach/',
|
||||
color: 'text-amber',
|
||||
bg: 'bg-amber/10',
|
||||
},
|
||||
];
|
||||
|
||||
const inputClass =
|
||||
'w-full bg-sand border border-sandy rounded-xl px-4 py-3 text-sm focus:outline-none focus:border-coral focus:ring-1 focus:ring-coral transition-all placeholder:text-midnight/30';
|
||||
|
||||
return (
|
||||
<section id="contact" className="py-28 bg-sandy/25 text-midnight">
|
||||
<div className="container mx-auto px-6 lg:px-12">
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="text-center mb-16"
|
||||
>
|
||||
<span className="text-xs tracking-[0.4em] uppercase font-black text-coral mb-4 block">
|
||||
— Bize Ulaşın
|
||||
</span>
|
||||
<h2 className="font-heading text-5xl md:text-6xl font-black text-midnight">
|
||||
{t('title')}
|
||||
</h2>
|
||||
</motion.div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-16">
|
||||
|
||||
{/* Left: info + form */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="space-y-8"
|
||||
>
|
||||
{/* Contact info */}
|
||||
<div className="space-y-5">
|
||||
{contactItems.map(({ Icon, label, value, href, color, bg }) => (
|
||||
<div key={label} className="flex items-start gap-4">
|
||||
<div className={`p-3 rounded-xl ${bg} ${color} flex-shrink-0`}>
|
||||
<Icon size={19} />
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-bold text-sm text-midnight/50 mb-0.5">{label}</p>
|
||||
{href ? (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={`${color} font-medium hover:underline`}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
) : (
|
||||
<p className="text-midnight font-medium">{value}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="bg-white p-8 rounded-3xl shadow-sm border border-sandy space-y-5"
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] font-black uppercase tracking-wider text-midnight/45">
|
||||
{t('form.name')}
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
className={inputClass}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] font-black uppercase tracking-wider text-midnight/45">
|
||||
{t('form.date')}
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
type="date"
|
||||
name="date"
|
||||
value={formData.date}
|
||||
onChange={handleChange}
|
||||
className={inputClass}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] font-black uppercase tracking-wider text-midnight/45">
|
||||
{t('form.guests')}
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
type="number"
|
||||
min="1"
|
||||
name="guests"
|
||||
value={formData.guests}
|
||||
onChange={handleChange}
|
||||
className={inputClass}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<label className="text-[11px] font-black uppercase tracking-wider text-midnight/45">
|
||||
{t('form.message')}
|
||||
</label>
|
||||
<textarea
|
||||
rows={3}
|
||||
name="message"
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
className={inputClass + ' resize-none'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-4 rounded-2xl font-black text-sm text-white flex items-center justify-center gap-2 hover:opacity-90 hover:scale-[1.01] transition-all shadow-md"
|
||||
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827)' }}
|
||||
>
|
||||
<Send size={15} />
|
||||
{t('form.submit')}
|
||||
</button>
|
||||
</form>
|
||||
</motion.div>
|
||||
|
||||
{/* Right: map */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 30 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="min-h-[420px] lg:min-h-[600px] w-full rounded-3xl overflow-hidden shadow-2xl"
|
||||
>
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d12754.717654763133!2d28.3144!3d36.9507!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x14bf76ccf312ba37%3A0xcdaaa97b102b4bb7!2sAkyaka%2C%20Ula%2FMu%C4%9Fla!5e0!3m2!1str!2str!4v1700000000000!5m2!1str!2str"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style={{ border: 0 }}
|
||||
allowFullScreen
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Utensils, Wine, Coffee, ArrowRight } from 'lucide-react';
|
||||
|
||||
const CARDS = [
|
||||
{ id: 'seafood', icon: Utensils, accent: '#FF5A36' },
|
||||
{ id: 'cocktails', icon: Wine, accent: '#00BFA5' },
|
||||
{ id: 'breakfast', icon: Coffee, accent: '#FFA827' },
|
||||
];
|
||||
|
||||
export default function Dining() {
|
||||
const t = useTranslations('Dining');
|
||||
const menuUrl = process.env.NEXT_PUBLIC_MENU_URL || '#';
|
||||
|
||||
return (
|
||||
<section
|
||||
id="dining"
|
||||
className="pt-20 pb-28 text-white relative overflow-hidden"
|
||||
style={{ background: '#080D18' }}
|
||||
>
|
||||
{/* Background blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
<div
|
||||
className="absolute bottom-0 left-1/4 w-[500px] h-[500px] rounded-full opacity-20"
|
||||
style={{ background: 'radial-gradient(circle, #FF5A36 0%, transparent 70%)' }}
|
||||
/>
|
||||
<div
|
||||
className="absolute top-0 right-1/4 w-[400px] h-[400px] rounded-full opacity-15"
|
||||
style={{ background: 'radial-gradient(circle, #00BFA5 0%, transparent 70%)' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-6 lg:px-12 relative z-10">
|
||||
<div className="text-center max-w-3xl mx-auto mb-16">
|
||||
<motion.span
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="text-xs tracking-[0.4em] uppercase font-black text-amber mb-4 block"
|
||||
>
|
||||
— Yeme & İçme
|
||||
</motion.span>
|
||||
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="font-heading text-5xl md:text-6xl font-black mb-6"
|
||||
>
|
||||
<span className="gradient-text">{t('title')}</span>
|
||||
</motion.h2>
|
||||
|
||||
<motion.p
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="text-lg text-white/50 mb-8"
|
||||
>
|
||||
{t('description')}
|
||||
</motion.p>
|
||||
|
||||
<motion.a
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.2 }}
|
||||
href={menuUrl}
|
||||
target={menuUrl !== '#' ? '_blank' : '_self'}
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 px-8 py-3.5 rounded-full font-black text-sm text-midnight transition-all hover:scale-105"
|
||||
style={{ background: 'linear-gradient(135deg, #FFA827, #FFD166)' }}
|
||||
>
|
||||
{t('view_menu')}
|
||||
<ArrowRight size={15} />
|
||||
</motion.a>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{CARDS.map(({ id, icon: Icon, accent }, index) => (
|
||||
<motion.div
|
||||
key={id}
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: index * 0.1 + 0.2 }}
|
||||
className="group relative p-8 rounded-3xl border border-white/10 hover:border-white/25 transition-all duration-300"
|
||||
style={{ background: 'rgba(255,255,255,0.04)' }}
|
||||
>
|
||||
{/* Icon */}
|
||||
<div
|
||||
className="w-14 h-14 rounded-2xl mb-6 flex items-center justify-center"
|
||||
style={{ background: `${accent}18`, color: accent }}
|
||||
>
|
||||
<Icon size={26} />
|
||||
</div>
|
||||
|
||||
<h3 className="font-heading text-2xl font-black mb-3 text-white">
|
||||
{t(`cards.${id}.title`)}
|
||||
</h3>
|
||||
<p className="text-white/45 text-sm leading-relaxed">{t(`cards.${id}.desc`)}</p>
|
||||
|
||||
{/* Bottom accent line on hover */}
|
||||
<div
|
||||
className="absolute bottom-0 left-8 right-8 h-[1px] opacity-0 group-hover:opacity-100 transition-opacity duration-300 rounded-full"
|
||||
style={{ background: `linear-gradient(90deg, transparent, ${accent}, transparent)` }}
|
||||
/>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Calendar, Music, Disc3, CalendarDays, Zap } from 'lucide-react';
|
||||
|
||||
/* ── static data ───────────────────────────────── */
|
||||
|
||||
const WEEK_DAYS = ['Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt', 'Paz'];
|
||||
const ACTIVE_DAYS: Record<number, string> = {
|
||||
3: '#FF5A36',
|
||||
4: '#00E5FF',
|
||||
5: '#00E5FF',
|
||||
};
|
||||
|
||||
/* ── sub-components ────────────────────────────── */
|
||||
|
||||
function VinylDisc() {
|
||||
return (
|
||||
<motion.div
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{ duration: 4, repeat: Infinity, ease: 'linear' }}
|
||||
className="w-36 h-36 md:w-44 md:h-44 rounded-full relative flex-shrink-0"
|
||||
style={{
|
||||
background:
|
||||
'repeating-conic-gradient(#0a0f1e 0deg 18deg, #141e30 18deg 36deg)',
|
||||
boxShadow: '0 0 48px rgba(0,229,255,0.35), 0 0 80px rgba(0,229,255,0.12)',
|
||||
}}
|
||||
>
|
||||
{/* Grooves */}
|
||||
{[55, 45, 35].map((size) => (
|
||||
<div
|
||||
key={size}
|
||||
className="absolute rounded-full border border-white/[0.04]"
|
||||
style={{ inset: `${(100 - size) / 2}%` }}
|
||||
/>
|
||||
))}
|
||||
{/* Label */}
|
||||
<div
|
||||
className="absolute inset-[35%] rounded-full flex items-center justify-center"
|
||||
style={{ background: 'radial-gradient(circle, #00E5FF, #0084A8)' }}
|
||||
>
|
||||
<div className="w-2 h-2 rounded-full bg-white/80" />
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
function EqBars({ color }: { color: string }) {
|
||||
const heights = [0.4, 0.8, 0.5, 1, 0.65, 0.9, 0.45, 0.75, 0.55, 0.85];
|
||||
return (
|
||||
<div className="flex items-end gap-[3px] h-8">
|
||||
{heights.map((h, i) => (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="w-1.5 rounded-full origin-bottom"
|
||||
style={{ background: color, height: `${h * 100}%` }}
|
||||
animate={{ scaleY: [h, h > 0.6 ? 0.2 : 1, h] }}
|
||||
transition={{
|
||||
duration: 0.5 + Math.random() * 0.4,
|
||||
repeat: Infinity,
|
||||
repeatType: 'mirror',
|
||||
delay: i * 0.07,
|
||||
ease: 'easeInOut',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function WineGlassIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="22"
|
||||
height="22"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M8 22h8" />
|
||||
<path d="M12 15v7" />
|
||||
<path d="M12 15a5 5 0 0 0 5-5c0-2-.5-4-2-8H9c-1.5 4-2 6-2 8a5 5 0 0 0 5 5Z" />
|
||||
<path d="M7 10h10" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
/* ── main component ────────────────────────────── */
|
||||
|
||||
export default function Events() {
|
||||
const t = useTranslations('Events');
|
||||
|
||||
return (
|
||||
<section
|
||||
id="events"
|
||||
className="pt-28 pb-36 text-white relative overflow-hidden"
|
||||
style={{ background: '#080D18' }}
|
||||
>
|
||||
{/* Aurora background blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
<div
|
||||
className="absolute top-[-20%] left-[-10%] w-[600px] h-[600px] rounded-full opacity-[0.12]"
|
||||
style={{ background: 'radial-gradient(circle, #00E5FF 0%, transparent 70%)' }}
|
||||
/>
|
||||
<div
|
||||
className="absolute bottom-[-10%] right-[-5%] w-[500px] h-[500px] rounded-full opacity-[0.1]"
|
||||
style={{ background: 'radial-gradient(circle, #FF5A36 0%, transparent 70%)' }}
|
||||
/>
|
||||
<div
|
||||
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[700px] rounded-full opacity-[0.05]"
|
||||
style={{ background: 'radial-gradient(circle, #FFA827 0%, transparent 70%)' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Fine dot grid */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.035] pointer-events-none"
|
||||
style={{
|
||||
backgroundImage: 'radial-gradient(circle, rgba(255,255,255,0.9) 1px, transparent 1px)',
|
||||
backgroundSize: '36px 36px',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="container mx-auto px-6 lg:px-12 relative z-10 space-y-10">
|
||||
|
||||
{/* ── Header ───────────────────────────────── */}
|
||||
<div className="flex flex-col lg:flex-row lg:items-end justify-between gap-6">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<Zap size={13} className="text-coral" />
|
||||
<span className="text-xs tracking-[0.4em] uppercase font-black text-coral">
|
||||
Live Events
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="font-heading text-5xl md:text-6xl font-black leading-tight">
|
||||
{t('title')}
|
||||
</h2>
|
||||
<p className="text-white/45 mt-3 text-base max-w-md leading-relaxed">
|
||||
{t('description')}
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<motion.button
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="self-start lg:self-auto flex items-center gap-2 px-7 py-3.5 rounded-full font-black text-sm text-white flex-shrink-0 transition-all hover:scale-105"
|
||||
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827)' }}
|
||||
>
|
||||
<CalendarDays size={15} />
|
||||
{t('view_calendar')}
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
{/* ── Weekly schedule bar ───────────────────── */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
className="flex items-center gap-2 md:gap-4 bg-white/[0.04] rounded-2xl px-6 py-4 border border-white/[0.07]"
|
||||
>
|
||||
{WEEK_DAYS.map((day, i) => {
|
||||
const accent = ACTIVE_DAYS[i];
|
||||
const isActive = !!accent;
|
||||
return (
|
||||
<div key={day} className="flex-1 flex flex-col items-center gap-2">
|
||||
<span
|
||||
className={`text-[10px] font-black uppercase tracking-wider ${
|
||||
isActive ? 'text-white' : 'text-white/25'
|
||||
}`}
|
||||
>
|
||||
{day}
|
||||
</span>
|
||||
<div
|
||||
className={`w-1.5 h-1.5 rounded-full transition-all ${isActive ? 'scale-125' : ''}`}
|
||||
style={{
|
||||
background: isActive ? accent : 'rgba(255,255,255,0.12)',
|
||||
boxShadow: isActive ? `0 0 8px ${accent}` : 'none',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
|
||||
{/* ── Featured Event: DJ Nights ────────────── */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 24 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.7 }}
|
||||
className="border-spin-cyan rounded-3xl p-px overflow-hidden"
|
||||
>
|
||||
<div
|
||||
className="rounded-3xl p-8 md:p-10 flex flex-col md:flex-row items-center gap-8 overflow-hidden relative"
|
||||
style={{ background: '#0C1828' }}
|
||||
>
|
||||
{/* Glow center */}
|
||||
<div
|
||||
className="absolute inset-0 pointer-events-none"
|
||||
style={{
|
||||
background:
|
||||
'radial-gradient(ellipse at 80% 50%, rgba(0,229,255,0.08) 0%, transparent 60%)',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Left: text */}
|
||||
<div className="flex-1 relative z-10">
|
||||
<div className="flex items-center gap-3 mb-5">
|
||||
<span
|
||||
className="text-[10px] font-black uppercase tracking-[0.35em] px-3 py-1.5 rounded-full"
|
||||
style={{ background: '#00E5FF1A', color: '#00E5FF' }}
|
||||
>
|
||||
EN POPÜLER
|
||||
</span>
|
||||
<div className="flex items-center gap-1.5 text-white/40 text-xs">
|
||||
<Calendar size={11} />
|
||||
<span>{t('cards.dj.time')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 className="font-heading text-4xl md:text-5xl font-black mb-3 text-white leading-tight">
|
||||
{t('cards.dj.title')}
|
||||
</h3>
|
||||
|
||||
<div className="flex items-center gap-3 mb-7">
|
||||
<Disc3 size={18} style={{ color: '#00E5FF' }} />
|
||||
<span className="text-white/50 text-sm">Open-air · Beach Stage</span>
|
||||
</div>
|
||||
|
||||
<EqBars color="#00E5FF" />
|
||||
</div>
|
||||
|
||||
{/* Right: vinyl */}
|
||||
<div className="relative z-10 flex-shrink-0">
|
||||
<VinylDisc />
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* ── Secondary events: 2-col grid ─────────── */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
|
||||
|
||||
{/* Rakı Geceleri */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="border-spin-coral rounded-3xl p-px group cursor-pointer"
|
||||
>
|
||||
<div
|
||||
className="rounded-3xl p-7 h-full flex flex-col gap-5 relative overflow-hidden transition-colors duration-300 group-hover:bg-[#110a0a]"
|
||||
style={{ background: '#0C0808' }}
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-400 pointer-events-none"
|
||||
style={{
|
||||
background:
|
||||
'radial-gradient(ellipse at 20% 50%, rgba(255,90,54,0.1) 0%, transparent 65%)',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex items-start justify-between">
|
||||
<div
|
||||
className="w-12 h-12 rounded-2xl flex items-center justify-center"
|
||||
style={{ background: '#FF5A361A', color: '#FF5A36' }}
|
||||
>
|
||||
<WineGlassIcon />
|
||||
</div>
|
||||
<span
|
||||
className="text-[10px] font-black uppercase tracking-wider px-2.5 py-1 rounded-full"
|
||||
style={{ background: '#FF5A361A', color: '#FF5A36' }}
|
||||
>
|
||||
PER
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-heading text-2xl font-black text-white mb-2">
|
||||
{t('cards.raki.title')}
|
||||
</h3>
|
||||
<div className="flex items-center gap-1.5 text-sm text-white/40">
|
||||
<Calendar size={12} />
|
||||
<span>{t('cards.raki.time')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-auto opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<EqBars color="#FF5A36" />
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Canlı Müzik */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: 0.2 }}
|
||||
className="border-spin-amber rounded-3xl p-px group cursor-pointer"
|
||||
>
|
||||
<div
|
||||
className="rounded-3xl p-7 h-full flex flex-col gap-5 relative overflow-hidden transition-colors duration-300 group-hover:bg-[#110d04]"
|
||||
style={{ background: '#0C0A04' }}
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-400 pointer-events-none"
|
||||
style={{
|
||||
background:
|
||||
'radial-gradient(ellipse at 80% 50%, rgba(255,168,39,0.1) 0%, transparent 65%)',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex items-start justify-between">
|
||||
<div
|
||||
className="w-12 h-12 rounded-2xl flex items-center justify-center"
|
||||
style={{ background: '#FFA8271A', color: '#FFA827' }}
|
||||
>
|
||||
<Music size={22} />
|
||||
</div>
|
||||
<span
|
||||
className="text-[10px] font-black uppercase tracking-wider px-2.5 py-1 rounded-full"
|
||||
style={{ background: '#FFA8271A', color: '#FFA827' }}
|
||||
>
|
||||
★ ÖZEL
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-heading text-2xl font-black text-white mb-2">
|
||||
{t('cards.live_music.title')}
|
||||
</h3>
|
||||
<div className="flex items-center gap-1.5 text-sm text-white/40">
|
||||
<Calendar size={12} />
|
||||
<span>{t('cards.live_music.time')}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-auto opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<EqBars color="#FFA827" />
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Wave → sand */}
|
||||
<div className="absolute bottom-0 left-0 w-full leading-none pointer-events-none">
|
||||
<svg viewBox="0 0 1440 64" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" className="w-full h-16">
|
||||
<path d="M0,20 C360,64 720,0 1080,40 C1260,56 1380,10 1440,20 L1440,64 L0,64 Z" fill="#FFF8EE" />
|
||||
</svg>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Instagram } from '@/components/InstagramIcon';
|
||||
import { Link, usePathname } from '@/i18n/routing';
|
||||
|
||||
export default function Footer() {
|
||||
const t = useTranslations('Footer');
|
||||
const tNav = useTranslations('Navbar');
|
||||
|
||||
const pathname = usePathname();
|
||||
|
||||
const navLinks = [
|
||||
{ href: pathname === '/' ? '#about' : '/#about', label: tNav('about') },
|
||||
{ href: '/accommodation', label: tNav('accommodation') },
|
||||
{ href: pathname === '/' ? '#beach' : '/#beach', label: tNav('beach') },
|
||||
{ href: pathname === '/' ? '#dining' : '/#dining', label: tNav('dining') },
|
||||
{ href: pathname === '/' ? '#events' : '/#events', label: tNav('events') },
|
||||
{ href: pathname === '/' ? '#gallery' : '/#gallery', label: tNav('gallery') },
|
||||
{ href: pathname === '/' ? '#contact' : '/#contact', label: tNav('contact') },
|
||||
];
|
||||
|
||||
return (
|
||||
<footer
|
||||
className="text-white py-16 relative overflow-hidden"
|
||||
style={{ background: '#080D18' }}
|
||||
>
|
||||
{/* Rainbow top border */}
|
||||
<div
|
||||
className="absolute top-0 left-0 right-0 h-[1px]"
|
||||
style={{
|
||||
background:
|
||||
'linear-gradient(90deg, transparent 0%, #FF5A36 25%, #FFA827 50%, #00BFA5 75%, transparent 100%)',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="container mx-auto px-6 lg:px-12">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start gap-12 mb-12">
|
||||
|
||||
{/* Brand */}
|
||||
<div>
|
||||
<Link href="/" className="inline-flex flex-col mb-3">
|
||||
<span className="font-heading text-5xl font-black uppercase tracking-tighter gradient-text-warm">
|
||||
Kozmos
|
||||
</span>
|
||||
<span className="text-[10px] tracking-[0.5em] font-body uppercase text-white/30 mt-0.5">
|
||||
Beach & More
|
||||
</span>
|
||||
</Link>
|
||||
<p className="text-white/35 text-sm mt-1">{t('tagline')}</p>
|
||||
</div>
|
||||
|
||||
{/* Nav links */}
|
||||
<div className="flex flex-wrap gap-x-7 gap-y-3">
|
||||
{navLinks.map((link) => (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-sm text-white/40 hover:text-white transition-colors"
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Social */}
|
||||
<a
|
||||
href="https://www.instagram.com/kozmosbeach/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="w-12 h-12 rounded-2xl border border-white/10 flex items-center justify-center text-white/40 hover:border-coral hover:text-coral transition-all"
|
||||
>
|
||||
<Instagram size={19} />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="pt-8 border-t border-white/10 flex flex-col md:flex-row justify-between items-center gap-4 text-xs text-white/25">
|
||||
<div>{t('rights')}</div>
|
||||
<div>
|
||||
Created by{' '}
|
||||
<a
|
||||
href="https://ayris.tech"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-white/40 hover:text-coral transition-colors"
|
||||
>
|
||||
ayris.tech
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { Instagram } from '@/components/InstagramIcon';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { X, ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
|
||||
export default function Gallery() {
|
||||
const t = useTranslations('Gallery');
|
||||
|
||||
const images = Array.from({ length: 12 }).map((_, i) => ({
|
||||
id: i,
|
||||
src: `https://picsum.photos/600/${400 + (i % 5) * 50}?random=${30 + i}`,
|
||||
alt: `Gallery ${i + 1}`,
|
||||
}));
|
||||
|
||||
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
||||
|
||||
// Close lightbox on escape key
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') setSelectedIndex(null);
|
||||
if (e.key === 'ArrowRight' && selectedIndex !== null) {
|
||||
setSelectedIndex((prev) => (prev !== null ? (prev + 1) % images.length : null));
|
||||
}
|
||||
if (e.key === 'ArrowLeft' && selectedIndex !== null) {
|
||||
setSelectedIndex((prev) => (prev !== null ? (prev - 1 + images.length) % images.length : null));
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, [selectedIndex, images.length]);
|
||||
|
||||
return (
|
||||
<section id="gallery" className="py-24 bg-white text-midnight">
|
||||
<div className="container mx-auto px-6 lg:px-12">
|
||||
|
||||
{/* Header */}
|
||||
<div className="flex flex-col md:flex-row justify-between items-end mb-10">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
>
|
||||
<span className="text-xs tracking-[0.4em] uppercase font-black text-coral mb-3 block">
|
||||
— Fotoğraflar
|
||||
</span>
|
||||
<h2 className="font-heading text-5xl md:text-6xl font-black text-midnight">
|
||||
{t('title')}
|
||||
</h2>
|
||||
</motion.div>
|
||||
|
||||
<motion.a
|
||||
initial={{ opacity: 0, x: 20 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
href="https://www.instagram.com/kozmosbeach/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2 px-5 py-2.5 rounded-full border border-coral/30 text-coral font-bold text-sm hover:bg-coral hover:text-white transition-all"
|
||||
>
|
||||
<Instagram size={15} />
|
||||
{t('follow_instagram')}
|
||||
</motion.a>
|
||||
</div>
|
||||
|
||||
{/* Masonry grid */}
|
||||
<div className="columns-1 sm:columns-2 md:columns-3 lg:columns-4 gap-3 space-y-3">
|
||||
{images.map((img, index) => (
|
||||
<motion.div
|
||||
key={img.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ delay: (index % 4) * 0.07 }}
|
||||
onClick={() => setSelectedIndex(index)}
|
||||
className="relative rounded-2xl overflow-hidden group break-inside-avoid cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src={img.src}
|
||||
alt={img.alt}
|
||||
className="w-full h-auto object-cover transition-transform duration-700 group-hover:scale-105"
|
||||
loading="lazy"
|
||||
/>
|
||||
{/* Coral gradient overlay */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300"
|
||||
style={{
|
||||
background:
|
||||
'linear-gradient(135deg, rgba(255,90,54,0.55), rgba(0,191,165,0.4))',
|
||||
}}
|
||||
/>
|
||||
{/* Plus icon */}
|
||||
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<span className="text-white text-4xl font-thin select-none">+</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Lightbox Overlay */}
|
||||
<AnimatePresence>
|
||||
{selectedIndex !== null && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="fixed inset-0 z-[100] flex items-center justify-center bg-midnight/95 backdrop-blur-md"
|
||||
>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
onClick={() => setSelectedIndex(null)}
|
||||
className="absolute top-6 right-6 z-[110] text-white/70 hover:text-white transition-colors"
|
||||
>
|
||||
<X size={36} />
|
||||
</button>
|
||||
|
||||
{/* Left/Right Navigation */}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedIndex((selectedIndex - 1 + images.length) % images.length);
|
||||
}}
|
||||
className="absolute left-4 md:left-10 z-[110] p-3 rounded-full bg-white/10 text-white hover:bg-white/20 transition-all"
|
||||
>
|
||||
<ChevronLeft size={30} />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedIndex((selectedIndex + 1) % images.length);
|
||||
}}
|
||||
className="absolute right-4 md:right-10 z-[110] p-3 rounded-full bg-white/10 text-white hover:bg-white/20 transition-all"
|
||||
>
|
||||
<ChevronRight size={30} />
|
||||
</button>
|
||||
|
||||
{/* Image */}
|
||||
<motion.div
|
||||
key={selectedIndex}
|
||||
initial={{ opacity: 0, scale: 0.9 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.9 }}
|
||||
transition={{ type: "spring", damping: 25, stiffness: 300 }}
|
||||
className="relative max-w-5xl w-full h-[80vh] px-4 md:px-24"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<img
|
||||
src={images[selectedIndex].src}
|
||||
alt={images[selectedIndex].alt}
|
||||
className="w-full h-full object-contain drop-shadow-2xl"
|
||||
/>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { motion } from 'framer-motion';
|
||||
import { ChevronDown, MapPin } from 'lucide-react';
|
||||
|
||||
export default function Hero() {
|
||||
const t = useTranslations('Hero');
|
||||
|
||||
const openWhatsApp = () => {
|
||||
const phone = process.env.NEXT_PUBLIC_WHATSAPP_NUMBER || '905000000000';
|
||||
window.open(`https://wa.me/${phone}`, '_blank');
|
||||
};
|
||||
|
||||
return (
|
||||
<section
|
||||
id="hero"
|
||||
className="relative w-full h-screen flex items-center justify-center overflow-hidden"
|
||||
style={{ background: '#080D18' }}
|
||||
>
|
||||
{/* ── Ambient gradient blobs ───────────────────── */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<motion.div
|
||||
animate={{ x: [0, 60, -20, 0], y: [0, -50, 30, 0], scale: [1, 1.15, 0.95, 1] }}
|
||||
transition={{ duration: 28, repeat: Infinity, ease: 'easeInOut' }}
|
||||
className="absolute -top-56 -left-56 w-[700px] h-[700px] rounded-full"
|
||||
style={{ background: 'radial-gradient(circle, rgba(255,90,54,0.28) 0%, transparent 65%)' }}
|
||||
/>
|
||||
<motion.div
|
||||
animate={{ x: [0, -80, 50, 0], y: [0, 70, -30, 0], scale: [1, 0.85, 1.2, 1] }}
|
||||
transition={{ duration: 32, repeat: Infinity, ease: 'easeInOut', delay: 6 }}
|
||||
className="absolute -bottom-40 -right-40 w-[600px] h-[600px] rounded-full"
|
||||
style={{ background: 'radial-gradient(circle, rgba(0,191,165,0.22) 0%, transparent 65%)' }}
|
||||
/>
|
||||
<motion.div
|
||||
animate={{ x: [0, 100, -60, 0], y: [0, -80, 50, 0], scale: [1, 1.3, 0.85, 1] }}
|
||||
transition={{ duration: 22, repeat: Infinity, ease: 'easeInOut', delay: 12 }}
|
||||
className="absolute top-1/2 right-1/3 w-[400px] h-[400px] rounded-full"
|
||||
style={{ background: 'radial-gradient(circle, rgba(255,168,39,0.18) 0%, transparent 65%)' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Grain overlay */}
|
||||
<div
|
||||
className="absolute inset-0 z-[1] opacity-[0.035] pointer-events-none"
|
||||
style={{
|
||||
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")`,
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* ── Content ──────────────────────────────────── */}
|
||||
<div className="relative z-10 container mx-auto px-6 flex flex-col items-center text-center">
|
||||
|
||||
{/* Location */}
|
||||
<motion.p
|
||||
initial={{ opacity: 0, y: 16 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.7 }}
|
||||
className="text-[11px] tracking-[0.45em] uppercase text-coral font-bold mb-10"
|
||||
>
|
||||
Akyaka · Gökova Körfezi
|
||||
</motion.p>
|
||||
|
||||
{/* Brand name — static gradient, no shimmer */}
|
||||
<motion.h1
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.9, delay: 0.15 }}
|
||||
className="font-heading font-black uppercase tracking-tight leading-none gradient-text-warm mb-4"
|
||||
style={{ fontSize: 'clamp(3rem, 8vw, 6.5rem)' }}
|
||||
>
|
||||
KOZMOS
|
||||
</motion.h1>
|
||||
|
||||
{/* Thin divider */}
|
||||
<motion.div
|
||||
initial={{ scaleX: 0 }}
|
||||
animate={{ scaleX: 1 }}
|
||||
transition={{ duration: 0.8, delay: 0.35 }}
|
||||
className="w-16 h-px mb-5"
|
||||
style={{ background: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent)' }}
|
||||
/>
|
||||
|
||||
{/* Subtitle */}
|
||||
<motion.p
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.45 }}
|
||||
className="text-sm md:text-base tracking-[0.55em] uppercase text-white/40 font-medium mb-6"
|
||||
>
|
||||
Beach & More
|
||||
</motion.p>
|
||||
|
||||
{/* Tagline */}
|
||||
<motion.p
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.6, delay: 0.6 }}
|
||||
className="text-white/55 text-sm md:text-base max-w-xs leading-relaxed mb-12"
|
||||
>
|
||||
{t('tagline')}
|
||||
</motion.p>
|
||||
|
||||
{/* CTAs */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 16 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.75 }}
|
||||
className="flex flex-col sm:flex-row gap-3"
|
||||
>
|
||||
<button
|
||||
onClick={openWhatsApp}
|
||||
className="px-8 py-3.5 rounded-full font-bold text-sm tracking-wider text-white transition-all duration-300 hover:scale-105 hover:shadow-[0_0_32px_rgba(255,90,54,0.45)]"
|
||||
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827)' }}
|
||||
>
|
||||
{t('cta_reservation')}
|
||||
</button>
|
||||
|
||||
<a
|
||||
href="#contact"
|
||||
className="flex items-center justify-center gap-2 px-7 py-3.5 rounded-full text-sm tracking-wider font-medium text-white/70 border border-white/15 hover:border-white/35 hover:text-white transition-all duration-300"
|
||||
>
|
||||
<MapPin size={14} />
|
||||
{t('cta_location')}
|
||||
</a>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* ── Wave divider ─────────────────────────────── */}
|
||||
<div className="absolute bottom-0 left-0 w-full z-10 leading-none">
|
||||
<svg
|
||||
viewBox="0 0 1440 72"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
preserveAspectRatio="none"
|
||||
className="w-full h-[72px]"
|
||||
>
|
||||
<path
|
||||
d="M0,36 C240,72 480,0 720,36 C960,72 1200,0 1440,36 L1440,72 L0,72 Z"
|
||||
fill="#FFF8EE"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Scroll cue */}
|
||||
<motion.div
|
||||
className="absolute bottom-10 left-1/2 -translate-x-1/2 z-20 text-white/35"
|
||||
animate={{ y: [0, 7, 0] }}
|
||||
transition={{ repeat: Infinity, duration: 1.8 }}
|
||||
>
|
||||
<a href="#about" aria-label="Scroll down">
|
||||
<ChevronDown size={24} />
|
||||
</a>
|
||||
</motion.div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
|
||||
export function Instagram({ size = 24, className = "" }: { size?: number, className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className={className}
|
||||
>
|
||||
<rect width="20" height="20" x="2" y="2" rx="5" ry="5" />
|
||||
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
|
||||
<line x1="17.5" x2="17.51" y1="6.5" y2="6.5" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
"use client";
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Link, usePathname, useRouter } from '@/i18n/routing';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Menu, X } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
export default function Navbar({ locale }: { locale: string }) {
|
||||
const t = useTranslations('Navbar');
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => setIsScrolled(window.scrollY > 50);
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
const switchLocale = (newLocale: string) => {
|
||||
router.replace(pathname, { locale: newLocale });
|
||||
};
|
||||
|
||||
const navLinks = [
|
||||
{ href: pathname === '/' ? '#about' : '/#about', label: t('about') },
|
||||
{ href: '/accommodation', label: t('accommodation') },
|
||||
{ href: pathname === '/' ? '#beach' : '/#beach', label: t('beach') },
|
||||
{ href: pathname === '/' ? '#dining' : '/#dining', label: t('dining') },
|
||||
{ href: pathname === '/' ? '#events' : '/#events', label: t('events') },
|
||||
{ href: pathname === '/' ? '#gallery' : '/#gallery', label: t('gallery') },
|
||||
{ href: pathname === '/' ? '#contact' : '/#contact', label: t('contact') },
|
||||
];
|
||||
|
||||
return (
|
||||
<nav
|
||||
className={`fixed top-0 left-0 w-full z-50 transition-all duration-300 ${
|
||||
isScrolled
|
||||
? 'bg-white/90 backdrop-blur-lg shadow-sm py-4 border-b border-sandy/40'
|
||||
: 'bg-transparent py-6'
|
||||
}`}
|
||||
>
|
||||
<div className="container mx-auto px-6 lg:px-12 flex justify-between items-center">
|
||||
|
||||
{/* Logo */}
|
||||
<Link href="/" className="flex flex-col items-start">
|
||||
<span
|
||||
className={`font-heading text-2xl font-black uppercase tracking-tighter ${
|
||||
isScrolled ? 'text-midnight' : 'gradient-text-warm'
|
||||
}`}
|
||||
>
|
||||
Kozmos
|
||||
</span>
|
||||
<span
|
||||
className={`text-[10px] tracking-[0.4em] font-body uppercase ${
|
||||
isScrolled ? 'text-coral' : 'text-white/40'
|
||||
}`}
|
||||
>
|
||||
Beach & More
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
{/* Desktop Nav */}
|
||||
<div className="hidden lg:flex items-center gap-8">
|
||||
<div className="flex gap-6">
|
||||
{navLinks.map((link) => (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className={`text-sm font-medium tracking-wide transition-colors hover:text-coral ${
|
||||
isScrolled ? 'text-midnight/70' : 'text-white/80'
|
||||
}`}
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`flex items-center gap-3 border-l pl-5 ${
|
||||
isScrolled ? 'border-sandy' : 'border-white/20'
|
||||
}`}
|
||||
>
|
||||
{(['tr', 'en'] as const).map((l) => (
|
||||
<button
|
||||
key={l}
|
||||
onClick={() => switchLocale(l)}
|
||||
className={`text-[11px] font-black uppercase tracking-wider transition-colors ${
|
||||
locale === l
|
||||
? 'text-coral'
|
||||
: isScrolled
|
||||
? 'text-midnight/40'
|
||||
: 'text-white/40'
|
||||
}`}
|
||||
>
|
||||
{l}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="#contact"
|
||||
className="px-5 py-2.5 rounded-full text-xs font-black text-white tracking-wider transition-all hover:scale-105 hover:shadow-[0_0_24px_rgba(255,90,54,0.45)]"
|
||||
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827)' }}
|
||||
>
|
||||
{t('reservation')}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Mobile toggle */}
|
||||
<button
|
||||
className="lg:hidden"
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
{isMobileMenuOpen ? (
|
||||
<X className={isScrolled ? 'text-midnight' : 'text-white'} size={26} />
|
||||
) : (
|
||||
<Menu className={isScrolled ? 'text-midnight' : 'text-white'} size={26} />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu */}
|
||||
<AnimatePresence>
|
||||
{isMobileMenuOpen && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -10 }}
|
||||
className="lg:hidden absolute top-full left-0 w-full bg-white/96 backdrop-blur-lg shadow-xl border-t border-sandy/30"
|
||||
>
|
||||
<div className="flex flex-col py-6 px-8 gap-3">
|
||||
{navLinks.map((link) => (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-midnight text-base font-heading font-semibold py-2 border-b border-sandy/20 hover:text-coral transition-colors"
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
))}
|
||||
|
||||
<div className="flex gap-4 pt-3">
|
||||
{(['tr', 'en'] as const).map((l) => (
|
||||
<button
|
||||
key={l}
|
||||
onClick={() => switchLocale(l)}
|
||||
className={`text-sm font-black uppercase ${locale === l ? 'text-coral' : 'text-midnight/40'}`}
|
||||
>
|
||||
{l}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="#contact"
|
||||
className="mt-2 text-center py-3.5 rounded-full text-sm font-black text-white"
|
||||
style={{ background: 'linear-gradient(135deg, #FF5A36, #FFA827)' }}
|
||||
onClick={() => setIsMobileMenuOpen(false)}
|
||||
>
|
||||
{t('reservation')}
|
||||
</a>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import { MessageCircle } from 'lucide-react';
|
||||
|
||||
export default function WhatsAppButton() {
|
||||
const openWhatsApp = () => {
|
||||
const phone = process.env.NEXT_PUBLIC_WHATSAPP_NUMBER || '905000000000';
|
||||
window.open(`https://wa.me/${phone}`, '_blank');
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={openWhatsApp}
|
||||
className="fixed bottom-6 right-6 z-50 bg-[#25D366] text-white p-4 rounded-full shadow-[0_4px_14px_0_rgba(37,211,102,0.39)] hover:shadow-[0_6px_20px_rgba(37,211,102,0.23)] hover:scale-105 transition-all duration-300 flex items-center justify-center group"
|
||||
aria-label="WhatsApp ile iletişime geçin"
|
||||
>
|
||||
<div className="absolute inset-0 rounded-full bg-[#25D366] animate-ping opacity-20"></div>
|
||||
<MessageCircle size={28} className="relative z-10" />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user