This commit is contained in:
2026-04-19 17:23:31 +03:00
parent 9cad199125
commit 4f2188363a
122 changed files with 3215 additions and 116 deletions

View File

@@ -0,0 +1,142 @@
'use client'
import { motion } from "framer-motion"
import Image from "next/image"
import { Check, Hotel, Star, Globe } from 'lucide-react'
export default function AboutClient({ lang, dict }: { lang: string, dict: any }) {
const whyUs = [
{ title: dict.about.why['1'].t, desc: dict.about.why['1'].d },
{ title: dict.about.why['2'].t, desc: dict.about.why['2'].d },
{ title: dict.about.why['3'].t, desc: dict.about.why['3'].d },
{ title: dict.about.why['4'].t, desc: dict.about.why['4'].d }
]
const stats = [
{ icon: <Hotel size={32} />, value: '8+', label: 'Premium Room' },
{ icon: <Star size={32} />, value: '4.8', label: 'Guest Rating' },
{ icon: <Globe size={32} />, value: '10+', label: 'Countries' }
]
return (
<main className="bg-[#FAF7F0] min-h-screen">
{/* HERO SECTION */}
<section className="pt-44 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center space-y-10">
<motion.h1
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 1 }}
className="text-7xl md:text-[120px] font-serif text-[#1A1A1A] leading-[0.9] tracking-tight uppercase"
>
{dict.about.title}
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.3 }}
className="text-[#1A1A1A]/70 text-lg md:text-xl max-w-2xl mx-auto font-medium leading-relaxed italic"
>
{dict.about.subtitle}
</motion.p>
</div>
</section>
{/* STORY & WHY US SECTION */}
<section className="py-24 px-6 md:px-12 max-w-[1400px] mx-auto">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16 lg:gap-24 items-start">
{/* Left: Story */}
<motion.div
initial={{ opacity: 0, x: -30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
className="lg:col-span-7 space-y-10"
>
<h2 className="text-4xl md:text-5xl font-serif text-[#1A1A1A]">{dict.about.story.title}</h2>
<div className="space-y-8 text-[#1A1A1A]/70 text-lg leading-relaxed italic border-l-2 border-[#C88C4B] pl-8">
<p>{dict.about.story.p1}</p>
<p>{dict.about.story.p2}</p>
</div>
</motion.div>
{/* Right: Why Us Card */}
<motion.div
initial={{ opacity: 0, x: 30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
className="lg:col-span-5 bg-white p-10 md:p-12 rounded-[2px] shadow-2xl border border-[#1A1A1A]/5"
>
<h3 className="text-3xl font-serif text-[#1A1A1A] mb-8">{dict.about.why.title}</h3>
<div className="space-y-8">
{whyUs.map((item, idx) => (
<div key={idx} className="flex items-start space-x-4">
<div className="mt-1 bg-[#C88C4B]/10 p-1 rounded-full text-[#C88C4B]">
<Check size={16} />
</div>
<div className="space-y-1">
<p className="font-bold text-[#1A1A1A] text-sm uppercase tracking-wider">{item.title}</p>
<p className="text-[#1A1A1A]/60 text-sm italic">{item.desc}</p>
</div>
</div>
))}
</div>
</motion.div>
</div>
</section>
{/* STATS SECTION */}
<section className="py-24 px-6 md:px-12 max-w-[1400px] mx-auto overflow-hidden">
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{stats.map((stat, idx) => (
<motion.div
key={idx}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: idx * 0.1 }}
className="bg-white p-12 text-center space-y-6 rounded-[2px] shadow-sm hover:shadow-xl transition-shadow duration-500 border border-[#1A1A1A]/5 group"
>
<div className="flex justify-center text-[#C88C4B] group-hover:scale-110 transition-transform duration-500">
{stat.icon}
</div>
<div className="space-y-1">
<p className="text-5xl font-serif text-[#1A1A1A]">{stat.value}</p>
<p className="text-[11px] font-bold tracking-[0.3em] uppercase text-[#1A1A1A]/40">{stat.label}</p>
</div>
</motion.div>
))}
</div>
</section>
{/* VISION SECTION */}
<section className="py-32 px-6">
<div className="max-w-4xl mx-auto bg-white p-16 md:p-24 text-center space-y-10 rounded-[2px] shadow-2xl border border-[#1A1A1A]/5">
<motion.h2
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="text-[12px] font-bold tracking-[0.5em] uppercase text-[#1A1A1A]/30"
>
{dict.about.vision.title}
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ delay: 0.2 }}
className="text-2xl md:text-4xl font-serif leading-tight text-[#1A1A1A] italic"
>
{dict.about.vision.text}
</motion.p>
</div>
</section>
</main>
)
}

18
app/[lang]/about/page.tsx Normal file
View File

@@ -0,0 +1,18 @@
import { getDictionary } from "@/dictionaries/get-dictionary"
import AboutClient from "./AboutClient"
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return {
title: `${dict.about.title} - Ayris Apart`,
description: dict.about.subtitle,
}
}
export default async function AboutPage({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return <AboutClient lang={lang} dict={dict} />
}

View File

@@ -0,0 +1,184 @@
'use client'
import { motion } from "framer-motion"
import { Mail, Phone, MapPin, Clock, ArrowUpRight, MessageCircle } from 'lucide-react'
import Link from "next/link"
const InstagramIcon = ({ size = 20 }: { size?: number }) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect>
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path>
<line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line>
</svg>
)
export default function ContactClient({ lang, dict }: { lang: string, dict: any }) {
return (
<main className="bg-[#FAF7F0] min-h-screen text-[#1A1A1A]">
{/* HERO SECTION */}
<section className="pt-64 pb-32 px-6">
<div className="max-w-[1400px] mx-auto">
<motion.h1
initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1, ease: [0.33, 1, 0.68, 1] }}
className="text-[12vw] md:text-[150px] font-serif leading-[0.8] tracking-tight uppercase"
>
{dict.contact.title.split(' ')[0]} <br /> <span className="italic ml-[5vw]">{dict.contact.title.split(' ').slice(1).join(' ')}</span>
</motion.h1>
</div>
</section>
{/* MINIMALIST INFO GRID */}
<section className="py-24 px-6 md:px-12 max-w-[1400px] mx-auto">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-0.5 bg-[#1A1A1A]/10 border border-[#1A1A1A]/10">
{/* Address */}
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="bg-[#FAF7F0] p-16 space-y-12 flex flex-col justify-between aspect-square"
>
<MapPin size={32} strokeWidth={1} className="text-[#C88C4B]" />
<div className="space-y-6">
<h3 className="text-3xl font-serif">{dict.contact.visit.t}</h3>
<p className="text-xl text-[#1A1A1A]/60 italic leading-relaxed">
{dict.contact.visit.d}
</p>
<Link href="https://www.google.com/maps/search/?api=1&query=Ayris+Apart+Milas+Ören" target="_blank" className="inline-flex items-center space-x-2 text-xs font-bold uppercase tracking-[0.3em] border-b border-[#1A1A1A] pb-1">
<span>{dict.contact.btn.map}</span>
<ArrowUpRight size={14} />
</Link>
</div>
</motion.div>
{/* Direct Connect */}
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.1 }}
className="bg-[#FAF7F0] p-16 space-y-12 flex flex-col justify-between aspect-square"
>
<Phone size={32} strokeWidth={1} className="text-[#C88C4B]" />
<div className="space-y-6">
<h3 className="text-3xl font-serif">{dict.contact.call.t}</h3>
<div className="space-y-2">
<p className="text-2xl font-medium">+90 543 231 87 13</p>
<p className="text-lg text-[#1A1A1A]/50 italic">{dict.contact.call.d}</p>
</div>
<Link href="tel:+905432318713" className="inline-flex items-center space-x-2 text-xs font-bold uppercase tracking-[0.3em] border-b border-[#1A1A1A] pb-1">
<span>{dict.contact.btn.call}</span>
<ArrowUpRight size={14} />
</Link>
</div>
</motion.div>
{/* Email */}
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.2 }}
className="bg-[#FAF7F0] p-16 space-y-12 flex flex-col justify-between aspect-square"
>
<Mail size={32} strokeWidth={1} className="text-[#C88C4B]" />
<div className="space-y-6">
<h3 className="text-3xl font-serif">{dict.contact.write.t}</h3>
<div className="space-y-2">
<p className="text-2xl font-medium">hello@ayrisapart.com</p>
<p className="text-lg text-[#1A1A1A]/50 italic">{dict.contact.write.d}</p>
</div>
<Link href="mailto:hello@ayrisapart.com" className="inline-flex items-center space-x-2 text-xs font-bold uppercase tracking-[0.3em] border-b border-[#1A1A1A] pb-1">
<span>{dict.contact.btn.mail}</span>
<ArrowUpRight size={14} />
</Link>
</div>
</motion.div>
{/* WhatsApp */}
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="bg-[#FAF7F0] p-16 space-y-12 flex flex-col justify-between aspect-square"
>
<MessageCircle size={32} strokeWidth={1} className="text-[#C88C4B]" />
<div className="space-y-6">
<h3 className="text-3xl font-serif">{dict.contact.wa.t}</h3>
<p className="text-xl text-[#1A1A1A]/60 italic leading-relaxed">
{dict.contact.wa.d}
</p>
<Link href="https://wa.me/905432318713" target="_blank" className="inline-flex items-center space-x-2 text-xs font-bold uppercase tracking-[0.3em] border-b border-[#1A1A1A] pb-1">
<span>{dict.contact.btn.wa}</span>
<ArrowUpRight size={14} />
</Link>
</div>
</motion.div>
{/* Instagram */}
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.1 }}
className="bg-[#FAF7F0] p-16 space-y-12 flex flex-col justify-between aspect-square"
>
<InstagramIcon size={32} />
<div className="space-y-6">
<h3 className="text-3xl font-serif">{dict.contact.ig.t}</h3>
<p className="text-xl text-[#1A1A1A]/60 italic leading-relaxed">
{dict.contact.ig.d}
</p>
<Link href="#" className="inline-flex items-center space-x-2 text-xs font-bold uppercase tracking-[0.3em] border-b border-[#1A1A1A] pb-1">
<span>{dict.contact.btn.ig}</span>
<ArrowUpRight size={14} />
</Link>
</div>
</motion.div>
{/* Working Hours */}
<motion.div
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
transition={{ delay: 0.2 }}
className="bg-[#FAF7F0] p-16 space-y-12 flex flex-col justify-between aspect-square"
>
<Clock size={32} strokeWidth={1} className="text-[#C88C4B]" />
<div className="space-y-6">
<h3 className="text-3xl font-serif">{dict.contact.hours.t}</h3>
<div className="space-y-2">
<p className="text-xl font-medium">{dict.contact.hours.d}</p>
<p className="text-lg text-[#1A1A1A]/50 italic">{dict.contact.hours.sub}</p>
</div>
<div className="text-[10px] font-bold uppercase tracking-[0.4em] text-[#1A1A1A]/30">Open 24/7 for you</div>
</div>
</motion.div>
</div>
</section>
{/* FULL WIDTH MAP SECTION */}
<section className="py-24">
<div className="h-[600px] w-full relative grayscale hover:grayscale-0 transition-all duration-1000">
<iframe
src="https://maps.google.com/maps?q=Ayris+Apart+Milas+Ören&t=&z=15&ie=UTF8&iwloc=&output=embed"
width="100%"
height="100%"
style={{ border: 0 }}
allowFullScreen
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
></iframe>
</div>
</section>
</main>
)
}

View File

@@ -0,0 +1,18 @@
import { getDictionary } from "@/dictionaries/get-dictionary"
import ContactClient from "./ContactClient"
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return {
title: `${dict.contact.title} - Ayris Apart`,
description: dict.contact.subtitle,
}
}
export default async function ContactPage({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return <ContactClient lang={lang} dict={dict} />
}

49
app/[lang]/layout.tsx Normal file
View File

@@ -0,0 +1,49 @@
import type { Metadata } from "next";
import { Oranienbaum, Inter } from "next/font/google";
import "../globals.css";
import Navbar from "@/components/Navbar";
import { getDictionary } from "@/dictionaries/get-dictionary";
import Footer from "@/components/Footer";
const oranienbaum = Oranienbaum({
subsets: ["latin", "latin-ext"],
weight: ["400"],
variable: "--font-oranienbaum",
display: "swap",
});
const inter = Inter({
subsets: ["latin", "latin-ext"],
variable: "--font-inter",
display: "swap",
});
export const metadata: Metadata = {
title: "Ayris - Luxury Accommodation",
description: "Experience the ultimate comfort and luxury at Ayris.",
};
export async function generateStaticParams() {
return [{ lang: 'en' }, { lang: 'tr' }]
}
export default async function RootLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ lang: string }>;
}) {
const { lang } = await params;
const dict = await getDictionary(lang as 'en' | 'tr');
return (
<html lang={lang} className={`${oranienbaum.variable} ${inter.variable} h-full antialiased`}>
<body className="font-sans min-h-full flex flex-col bg-[#FAF7F0] text-[#1A1A1A]">
<Navbar lang={lang} dict={dict} />
{children}
<Footer lang={lang} dict={dict} />
</body>
</html>
);
}

View File

@@ -0,0 +1,120 @@
'use client'
import { motion } from "framer-motion"
import Image from "next/image"
import Link from "next/link"
import { Calendar, ArrowRight } from 'lucide-react'
export default function NewsClient({ lang, dict }: { lang: string, dict: any }) {
const newsItems = [
{
id: 'hidden-gems-oren',
title: dict.news_page.list.n1.title,
excerpt: dict.news_page.list.n1.excerpt,
image: 'https://images.unsplash.com/photo-1544124499-58912cbddaad?q=80&w=2127&auto=format&fit=crop',
date: 'April 15, 2026',
author: dict.news_page.list.n1.author
},
{
id: 'summer-cocktails-retreat',
title: dict.news_page.list.n2.title,
excerpt: dict.news_page.list.n2.excerpt,
image: 'https://images.unsplash.com/photo-1519046904884-53103b34b206?q=80&w=2073&auto=format&fit=crop',
date: 'April 10, 2026',
author: dict.news_page.list.n2.author
},
{
id: 'luxury-interior-trends',
title: dict.news_page.list.n3.title,
excerpt: dict.news_page.list.n3.excerpt,
image: 'https://images.unsplash.com/photo-1618773928121-c32242e63f39?q=80&w=1964&auto=format&fit=crop',
date: 'April 05, 2026',
author: dict.news_page.list.n3.author
}
]
return (
<main className="bg-[#FAF7F0] min-h-screen">
{/* HEADER SECTION */}
<section className="pt-44 pb-24 px-6">
<div className="max-w-5xl mx-auto text-center space-y-10">
<motion.h1
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 1 }}
className="text-7xl md:text-[120px] font-serif text-[#1A1A1A] leading-[0.9] tracking-tight uppercase"
>
{dict.news_page.title}
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.3 }}
className="text-[#1A1A1A]/70 text-lg md:text-xl max-w-3xl mx-auto font-medium leading-relaxed italic"
>
{dict.news_page.subtitle}
</motion.p>
</div>
</section>
{/* ARTICLES GRID SECTION */}
<section className="pb-44 px-6 md:px-12 max-w-[1400px] mx-auto">
<div className="grid grid-cols-1 md:grid-cols-3 gap-12">
{newsItems.map((article, idx) => (
<motion.div
key={article.id}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8, delay: idx * 0.15 }}
className="group cursor-pointer"
>
<Link href={`/${lang}/news/${article.id}`}>
<div className="space-y-8">
{/* Image Card */}
<div className="aspect-[4/5] relative overflow-hidden rounded-[2px] shadow-sm">
<Image
src={article.image}
alt={article.title}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-black/5 group-hover:bg-transparent transition-colors duration-500" />
</div>
{/* Metadata and Title */}
<div className="space-y-4">
<div className="flex items-center space-x-6 text-[11px] font-bold tracking-[0.3em] uppercase text-[#1A1A1A]/40 mb-2">
<span className="flex items-center space-x-2">
<Calendar size={14} className="opacity-50" />
<span>{article.date}</span>
</span>
</div>
<h2 className="text-3xl md:text-4xl font-serif text-[#1A1A1A] leading-tight group-hover:text-[#C88C4B] transition-colors duration-300">
{article.title}
</h2>
<p className="text-[#1A1A1A]/60 text-lg leading-relaxed italic line-clamp-2">
{article.excerpt}
</p>
<div className="inline-flex items-center space-x-2 text-[12px] font-bold tracking-widest uppercase text-[#1A1A1A] pt-2 border-b-2 border-transparent group-hover:border-[#C88C4B] transition-all pb-1">
<span>{dict.news_page.read}</span>
<ArrowRight size={16} className="transform group-hover:translate-x-1 transition-transform" />
</div>
</div>
</div>
</Link>
</motion.div>
))}
</div>
</section>
</main>
)
}

View File

@@ -0,0 +1,157 @@
'use client'
import { motion } from "framer-motion"
import Image from "next/image"
import Link from "next/link"
import { Calendar, User, Share2, ArrowLeft } from 'lucide-react'
export default function NewsDetailClient({ lang, slug, dict }: { lang: string, slug: string, dict: any }) {
// Use dictionary instead of hardcoded data where possible
// For demo, we still use a local map but referring to Ören
const newsData: Record<string, any> = {
'hidden-gems-oren': {
title: dict.news_page.list.n1.title,
date: 'April 15, 2026',
author: dict.news_page.list.n1.author,
category: 'Travel Guide',
image: 'https://images.unsplash.com/photo-1544124499-58912cbddaad?q=80&w=2127&auto=format&fit=crop',
content: [
{ type: 'paragraph', text: dict.news_page.list.n1.excerpt + ' ' + (lang === 'tr' ? 'Örenin saklı koyları, zamanın ötesinde bir huzur sunuyor. Turkuaz suların üzerinden sabah sisi kalkarken, standart haritaların ötesine bakmaya istekli olanlar için gizli sığınaklar kendilerini göstermeye başlıyor. Bugünkü yolculuğumuz bizi Egenin saklı kalbinde bir keşfe çıkarıyor.' : 'Beyond the crowded beaches, the secret coves of Oren offer a peace beyond time. As the morning mist lifts from the turquoise waters, hidden havens begin to reveal themselves to those willing to look beyond standard maps. Our journey today takes us on an exploration in the hidden heart of the Aegean.') },
{ type: 'quote', text: lang === 'tr' ? 'Gerçek keşif yolculuğu yeni manzaralar aramak değil, yeni gözlere sahip olmaktan geçer.' : 'The real voyage of discovery consists not in seeking new landscapes, but in having new eyes.' },
{ type: 'paragraph', text: lang === 'tr' ? 'Gemile koyunun sessiz kıyılarında, zeytinlikler arasında sessizce oturan antik kalıntılar bunlardan sadece biri. Bu sessiz taşların arasında yürürken, Bizanslı tüccarların yankılarını neredeyse duyabilirsiniz. Burası, tarihin, doğanın ve sessiz lüksün harmanlandığı, Ayris Apart\'ın gerçek özünü bulduğumuz yerdir.' : 'The ancient ruins sitting quietly amidst olive groves on the silent shores of Gemile Bay are just one of them. Walking among these silent stones, you can almost hear the echoes of Byzantine merchants. This is where we find the true essence of Ayris Apart, where history, nature, and silent luxury blend.' },
{ type: 'image', url: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=2073&auto=format&fit=crop' }
]
},
'summer-cocktails-retreat': {
title: dict.news_page.list.n2.title,
date: 'April 10, 2026',
author: dict.news_page.list.n2.author,
category: 'Lifestyle',
image: 'https://images.unsplash.com/photo-1519046904884-53103b34b206?q=80&w=2073&auto=format&fit=crop',
content: [
{ type: 'paragraph', text: dict.news_page.list.n2.excerpt }
]
},
'luxury-interior-trends': {
title: dict.news_page.list.n3.title,
date: 'April 05, 2026',
author: dict.news_page.list.n3.author,
category: 'Design',
image: 'https://images.unsplash.com/photo-1618773928121-c32242e63f39?q=80&w=1964&auto=format&fit=crop',
content: [
{ type: 'paragraph', text: dict.news_page.list.n3.excerpt }
]
}
}
const post = newsData[slug] || newsData['hidden-gems-oren']
return (
<main className="bg-[#FAF7F0] min-h-screen">
{/* HEADER SECTION */}
<section className="pt-44 pb-20 px-6">
<div className="max-w-4xl mx-auto text-center space-y-8">
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
className="flex items-center justify-center space-x-6 text-[11px] font-bold tracking-[0.4em] uppercase text-[#1A1A1A]/40"
>
<span>{post.category}</span>
<span className="w-1 h-1 bg-[#C88C4B] rounded-full" />
<span>{post.date}</span>
</motion.div>
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="text-5xl md:text-7xl lg:text-[88px] font-serif text-[#1A1A1A] leading-[1.1] tracking-tight uppercase"
>
{post.title}
</motion.h1>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.4 }}
className="flex items-center justify-center space-x-4 pt-4"
>
<div className="w-12 h-12 rounded-full bg-[#1A1A1A]/5 flex items-center justify-center text-[#1A1A1A]/40 overflow-hidden">
<User size={24} />
</div>
<div className="text-left leading-tight">
<p className="text-[11px] font-bold tracking-widest uppercase text-[#1A1A1A]/30 mb-1">Written By</p>
<p className="text-sm font-medium text-[#1A1A1A]">{post.author}</p>
</div>
</motion.div>
</div>
</section>
{/* FEATURE IMAGE */}
<section className="px-6 md:px-12 max-w-[1400px] mx-auto overflow-hidden">
<motion.div
initial={{ opacity: 0, scale: 1.05 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 1.5 }}
className="aspect-[21/9] relative rounded-[2px]"
>
<Image src={post.image} alt={post.title} fill className="object-cover" />
</motion.div>
</section>
{/* CONTENT SECTION */}
<section className="py-24 px-6">
<div className="max-w-2xl mx-auto space-y-12">
{post.content.map((block: any, idx: number) => {
if (block.type === 'paragraph') {
return (
<p key={idx} className={`text-[#1A1A1A]/80 text-xl leading-relaxed italic ${idx === 0 ? 'first-letter:text-7xl first-letter:font-serif first-letter:mr-3 first-letter:float-left first-letter:leading-[0.8] first-letter:mt-1' : ''}`}>
{block.text}
</p>
)
}
if (block.type === 'quote') {
return (
<blockquote key={idx} className="border-l-4 border-[#C88C4B] pl-8 py-4 my-16">
<p className="text-3xl font-serif text-[#1A1A1A] leading-snug">
&ldquo;{block.text}&rdquo;
</p>
</blockquote>
)
}
if (block.type === 'image') {
return (
<div key={idx} className="my-16 -mx-6 md:-mx-24 aspect-video relative overflow-hidden rounded-[2px] shadow-2xl">
<Image src={block.url} alt="Article imagery" fill className="object-cover" />
</div>
)
}
return null
})}
{/* SHARE & BACK */}
<div className="pt-16 border-t border-[#1A1A1A]/10 flex items-center justify-between">
<Link
href={`/${lang}/news`}
className="inline-flex items-center space-x-2 text-[12px] font-bold tracking-widest uppercase text-[#1A1A1A]/40 hover:text-[#1A1A1A] transition-colors"
>
<ArrowLeft size={16} />
<span>{lang === 'tr' ? 'Haberlere Dön' : 'Back to News'}</span>
</Link>
<div className="flex items-center space-x-4">
<span className="text-[11px] font-bold tracking-widest uppercase text-[#1A1A1A]/40">Share</span>
<button className="w-10 h-10 rounded-full border border-[#1A1A1A]/10 flex items-center justify-center hover:bg-[#1A1A1A] hover:text-white transition-all">
<Share2 size={16} />
</button>
</div>
</div>
</div>
</section>
</main>
)
}

View File

@@ -0,0 +1,20 @@
import { getDictionary } from "@/dictionaries/get-dictionary"
import NewsDetailClient from "./NewsDetailClient"
export async function generateMetadata({ params }: { params: Promise<{ lang: string, slug: string }> }) {
const { lang, slug } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
// Dynamic title based on slug if possible, or just section title
return {
title: `News - Ayris Apart`,
description: dict.news_page.subtitle,
}
}
export default async function NewsDetailPage({ params }: { params: Promise<{ lang: string, slug: string }> }) {
const { lang, slug } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return <NewsDetailClient lang={lang} slug={slug} dict={dict} />
}

18
app/[lang]/news/page.tsx Normal file
View File

@@ -0,0 +1,18 @@
import { getDictionary } from "@/dictionaries/get-dictionary"
import NewsClient from "./NewsClient"
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return {
title: `${dict.news_page.title} - Ayris Apart`,
description: dict.news_page.subtitle,
}
}
export default async function NewsPage({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return <NewsClient lang={lang} dict={dict} />
}

40
app/[lang]/page.tsx Normal file
View File

@@ -0,0 +1,40 @@
import Hero from "@/components/Hero";
import Welcome from "@/components/Welcome";
import ShowcaseImage from "@/components/ShowcaseImage";
import QuoteSection from "@/components/QuoteSection";
import SuitesHighlights from "@/components/SuitesHighlights";
import Experiences from "@/components/Experiences";
import ScrollReveal from "@/components/ScrollReveal";
import CallToAction from "@/components/CallToAction";
import Amenities from "@/components/Amenities";
import { getDictionary } from "@/dictionaries/get-dictionary";
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params;
const dict = await getDictionary(lang as 'en' | 'tr');
return {
title: `${dict.hero.title} - ${dict.hero.desc.split('.')[0]}`,
description: dict.hero.desc,
};
}
export default async function Home({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params;
const dict = await getDictionary(lang as 'en' | 'tr');
return (
<main className="relative w-full bg-[#FAF7F0]">
<Hero lang={lang} dict={dict} />
<Welcome lang={lang} dict={dict} />
<ShowcaseImage />
<QuoteSection />
<SuitesHighlights lang={lang} dict={dict} />
<Experiences />
<ScrollReveal />
<CallToAction lang={lang} dict={dict} />
</main>
);
}

View File

@@ -0,0 +1,117 @@
'use client'
import { motion } from "framer-motion"
import Image from "next/image"
import Link from "next/link"
import { Users, BedDouble } from 'lucide-react'
import Amenities from "@/components/Amenities"
export default function SuitesClient({ lang, dict }: { lang: string, dict: any }) {
const suites = [
{ id: 'iris', number: '01', name: dict.suites_page.list.s1.name, desc: dict.suites_page.list.s1.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606641/ayrisapart/Daire%201/photo_1_2024-04-05_12-32-09.jpg', bed: dict.suites_page.list.s1.bed, guests: dict.suites_page.list.s1.guests },
{ id: 'electra', number: '02', name: dict.suites_page.list.s2.name, desc: dict.suites_page.list.s2.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606648/ayrisapart/Daire%202/photo_1_2024-04-05_16-04-34.jpg', bed: dict.suites_page.list.s2.bed, guests: dict.suites_page.list.s2.guests },
{ id: 'arke', number: '03', name: dict.suites_page.list.s3.name, desc: dict.suites_page.list.s3.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606654/ayrisapart/Daire%203/photo_1_2024-04-05_16-06-09.jpg', bed: dict.suites_page.list.s3.bed, guests: dict.suites_page.list.s3.guests },
{ id: 'harpy', number: '04', name: dict.suites_page.list.s4.name, desc: dict.suites_page.list.s4.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606661/ayrisapart/Daire%204/photo_1_2024-04-05_16-07-01.jpg', bed: dict.suites_page.list.s4.bed, guests: dict.suites_page.list.s4.guests },
{ id: 'hydaspes', number: '05', name: dict.suites_page.list.s5.name, desc: dict.suites_page.list.s5.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606671/ayrisapart/Daire%205/photo_1_2024-05-04_15-32-44.jpg', bed: dict.suites_page.list.s5.bed, guests: dict.suites_page.list.s5.guests },
{ id: 'zephyrus', number: '06', name: dict.suites_page.list.s6.name, desc: dict.suites_page.list.s6.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606681/ayrisapart/Daire%206/photo_1_2024-05-04_15-32-44.jpg', bed: dict.suites_page.list.s6.bed, guests: dict.suites_page.list.s6.guests },
{ id: 'pothos', number: '07', name: dict.suites_page.list.s7.name, desc: dict.suites_page.list.s7.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606689/ayrisapart/Daire%207/photo_1_2024-05-04_15-33-34.jpg', bed: dict.suites_page.list.s7.bed, guests: dict.suites_page.list.s7.guests },
{ id: 'thaumas', number: '08', name: dict.suites_page.list.s8.name, desc: dict.suites_page.list.s8.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606696/ayrisapart/Daire%208/photo_1_2024-05-04_15-33-34.jpg', bed: dict.suites_page.list.s8.bed, guests: dict.suites_page.list.s8.guests },
]
return (
<main className="bg-[#FAF7F0] min-h-screen z-60 ">
{/* HEADER SECTION */}
<section className="pt-44 pb-20 px-6 ">
<div className="max-w-4xl mx-auto text-center space-y-10">
<motion.h1
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
className="text-7xl md:text-[120px] font-serif text-[#1A1A1A] leading-[0.9] tracking-tight uppercase"
>
{dict.suites_page.title}
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
className="text-[#1A1A1A]/60 text-lg md:text-xl max-w-2xl mx-auto font-medium leading-relaxed italic"
>
{dict.suites_page.subtitle}
</motion.p>
</div>
</section>
{/* SUITES LIST SECTION */}
<section className="pb-32 px-6 md:px-12 max-w-[1400px] mx-auto">
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-24">
{suites.map((suite, idx) => (
<motion.div
key={suite.id}
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.8, delay: (idx % 2) * 0.1 }}
className="group cursor-pointer"
>
{/* Image Card */}
<div className="aspect-[4/3] relative overflow-hidden rounded-[2px] bg-white p-0 shadow-sm">
<Image
src={suite.image}
alt={suite.name}
fill
className="object-cover transition-transform duration-1000 group-hover:scale-105"
/>
</div>
{/* Info */}
<div className="mt-10 space-y-6">
<h2 className="text-4xl font-serif text-[#1A1A1A] uppercase tracking-tight">
<span className="mr-4 font-sans text-xl opacity-20">{suite.number}.</span>
{suite.name}
</h2>
{/* Icons row */}
<div className="flex items-center space-x-8 text-[#1A1A1A]/60 text-[15px] font-medium">
<div className="flex items-center space-x-2">
<Users size={16} strokeWidth={1.5} className="text-[#C88C4B]" />
<span>{suite.guests}</span>
</div>
<div className="flex items-center space-x-2">
<BedDouble size={16} strokeWidth={1.5} className="text-[#C88C4B]" />
<span>{suite.bed}</span>
</div>
</div>
<p className="text-[#1A1A1A]/70 text-[17px] leading-relaxed italic max-w-lg">
{suite.desc}
</p>
{/* Link */}
<Link
href={`/${lang}/suites/${suite.id}`}
className="inline-flex items-center space-x-3 text-[13px] font-bold tracking-[0.3em] uppercase border-b-2 border-[#1A1A1A] pb-2 group/btn"
>
<span className="bg-[#1A1A1A] text-white p-1 rounded-full group-hover/btn:bg-[#C88C4B] transition-colors">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" className="rotate-45">
<line x1="12" y1="19" x2="12" y2="5" />
<polyline points="5 12 12 5 19 12" />
</svg>
</span>
<span>{dict.suites_page.details}</span>
</Link>
</div>
</motion.div>
))}
</div>
</section>
{/* GENERAL AMENITIES SECTION */}
<section className="py-32 px-6 md:px-12 max-w-[1400px] mx-auto bg-white/30 rounded-[4px] mb-32 border border-[#1A1A1A]/5 shadow-sm">
<Amenities dict={dict} />
</section>
</main>
)
}

View File

@@ -0,0 +1,221 @@
'use client'
import { motion } from "framer-motion"
import Image from "next/image"
import Link from "next/link"
import { Users, BedDouble, ArrowLeft } from 'lucide-react'
import Amenities from "@/components/Amenities"
export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id: string, dict: any }) {
// Mapping the 8 mythological suites with their Cloudinary assets
const suitesData: Record<string, any> = {
'iris': {
number: '01',
name: dict.suites_page.list.s1.name,
description: dict.suites_page.list.s1.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606641/ayrisapart/Daire%201/photo_1_2024-04-05_12-32-09.jpg',
guests: dict.suites_page.list.s1.guests,
bed: dict.suites_page.list.s1.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606642/ayrisapart/Daire%201/photo_2_2024-04-05_12-32-09.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606643/ayrisapart/Daire%201/photo_3_2024-04-05_12-32-09.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606644/ayrisapart/Daire%201/photo_4_2024-04-05_12-32-09.jpg'
]
},
'electra': {
number: '02',
name: dict.suites_page.list.s2.name,
description: dict.suites_page.list.s2.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606648/ayrisapart/Daire%202/photo_1_2024-04-05_16-04-34.jpg',
guests: dict.suites_page.list.s2.guests,
bed: dict.suites_page.list.s2.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606649/ayrisapart/Daire%202/photo_2_2024-04-05_16-04-34.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606650/ayrisapart/Daire%202/photo_3_2024-04-05_16-04-34.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606651/ayrisapart/Daire%202/photo_5_2024-04-05_16-04-34.jpg'
]
},
'arke': {
number: '03',
name: dict.suites_page.list.s3.name,
description: dict.suites_page.list.s3.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606654/ayrisapart/Daire%203/photo_1_2024-04-05_16-06-09.jpg',
guests: dict.suites_page.list.s3.guests,
bed: dict.suites_page.list.s3.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606655/ayrisapart/Daire%203/photo_2_2024-04-05_16-06-09.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606655/ayrisapart/Daire%203/photo_3_2024-04-05_16-06-09.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606656/ayrisapart/Daire%203/photo_4_2024-04-05_16-06-09.jpg'
]
},
'harpy': {
number: '04',
name: dict.suites_page.list.s4.name,
description: dict.suites_page.list.s4.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606661/ayrisapart/Daire%204/photo_1_2024-04-05_16-07-01.jpg',
guests: dict.suites_page.list.s4.guests,
bed: dict.suites_page.list.s4.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606662/ayrisapart/Daire%204/photo_2_2024-04-05_16-07-01.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606663/ayrisapart/Daire%204/photo_3_2024-04-05_16-07-01.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606664/ayrisapart/Daire%204/photo_5_2024-04-05_16-07-01.jpg'
]
},
'hydaspes': {
number: '05',
name: dict.suites_page.list.s5.name,
description: dict.suites_page.list.s5.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606671/ayrisapart/Daire%205/photo_1_2024-05-04_15-32-44.jpg',
guests: dict.suites_page.list.s5.guests,
bed: dict.suites_page.list.s5.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606672/ayrisapart/Daire%205/photo_2_2024-05-04_15-33-08.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606673/ayrisapart/Daire%205/photo_3_2024-05-04_15-33-08.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606674/ayrisapart/Daire%205/photo_4_2024-05-04_15-33-08.jpg'
]
},
'zephyrus': {
number: '06',
name: dict.suites_page.list.s6.name,
description: dict.suites_page.list.s6.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606681/ayrisapart/Daire%206/photo_1_2024-05-04_15-32-44.jpg',
guests: dict.suites_page.list.s6.guests,
bed: dict.suites_page.list.s6.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606682/ayrisapart/Daire%206/photo_2_2024-05-04_15-33-08.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606683/ayrisapart/Daire%206/photo_3_2024-05-04_15-33-08.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606684/ayrisapart/Daire%206/photo_5_2024-05-04_15-33-08.jpg'
]
},
'pothos': {
number: '07',
name: dict.suites_page.list.s7.name,
description: dict.suites_page.list.s7.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606689/ayrisapart/Daire%207/photo_1_2024-05-04_15-33-34.jpg',
guests: dict.suites_page.list.s7.guests,
bed: dict.suites_page.list.s7.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606690/ayrisapart/Daire%207/photo_2_2024-05-04_15-33-34.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606691/ayrisapart/Daire%207/photo_3_2024-05-04_15-33-34.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606692/ayrisapart/Daire%207/photo_5_2024-05-04_15-33-34.jpg'
]
},
'thaumas': {
number: '08',
name: dict.suites_page.list.s8.name,
description: dict.suites_page.list.s8.desc,
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606696/ayrisapart/Daire%208/photo_1_2024-05-04_15-33-34.jpg',
guests: dict.suites_page.list.s8.guests,
bed: dict.suites_page.list.s8.bed,
gallery: [
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606697/ayrisapart/Daire%208/photo_2_2024-05-04_15-33-34.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606698/ayrisapart/Daire%208/photo_4_2024-05-04_15-33-34.jpg',
'https://res.cloudinary.com/du7xohbct/image/upload/v1776606699/ayrisapart/Daire%208/photo_5_2024-05-04_15-33-34.jpg'
]
}
}
const suite = suitesData[id] || suitesData['iris']
return (
<main className="bg-[#FAF7F0] min-h-screen">
{/* SECTION 1: HEADER & MAIN IMAGE */}
<section className="pt-44 pb-20 px-6 md:px-16 max-w-[1400px] mx-auto">
<div className="space-y-12">
{/* Back Button */}
<Link href={`/${lang}/suites`} className="inline-flex items-center space-x-2 text-[11px] font-bold tracking-[0.4em] uppercase text-[#1A1A1A]/40 hover:text-[#1A1A1A] transition-colors">
<ArrowLeft size={16} />
<span>{lang === 'tr' ? 'Tüm Odalar' : 'All Suites'}</span>
</Link>
{/* Title and Brief Header */}
<div className="space-y-8">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-6xl md:text-[88px] font-serif text-[#1A1A1A] tracking-tight leading-none uppercase"
>
<span className="opacity-50 mr-4 font-sans text-4xl">{suite.number}.</span>
{suite.name}
</motion.h1>
<div className="flex flex-wrap items-center gap-x-12 gap-y-4 text-[#1A1A1A]/70 text-[15px] font-medium">
<div className="flex items-center space-x-2 uppercase tracking-widest">
<Users size={18} className="text-[#C88C4B]" />
<span>{suite.guests}</span>
</div>
<div className="flex items-center space-x-2 uppercase tracking-widest">
<BedDouble size={18} className="text-[#C88C4B]" />
<span>{suite.bed}</span>
</div>
</div>
</div>
{/* Main Visual */}
<motion.div
initial={{ opacity: 0, scale: 0.98 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 1 }}
className="aspect-[21/9] relative overflow-hidden rounded-[2px] shadow-2xl"
>
<Image
src={suite.mainImage}
alt={suite.name}
fill
className="object-cover"
priority
/>
</motion.div>
</div>
</section>
{/* SECTION 2: ABOUT & AMENITIES */}
<section className="py-24 px-6 md:px-16 max-w-[1400px] mx-auto">
<div className="grid grid-cols-1 md:grid-cols-12 gap-16 border-b border-[#1A1A1A]/10 pb-20">
<div className="md:col-span-4">
<h2 className="text-4xl font-serif text-[#1A1A1A] uppercase tracking-tight">{lang === 'tr' ? 'Suit Hakkında' : 'About Suite'}</h2>
</div>
<div className="md:col-span-8 space-y-12">
<p className="text-[#1A1A1A]/70 text-2xl leading-relaxed italic max-w-2xl">
{suite.description}
</p>
<Link
href={`/${lang}/reservation`}
className="inline-flex items-center space-x-3 text-[14px] font-bold tracking-[0.4em] uppercase border-b-2 border-[#1A1A1A] pb-2 group"
>
<span className="transform group-hover:translate-x-1 transition-transform">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" className="rotate-45">
<line x1="12" y1="19" x2="12" y2="5" />
<polyline points="5 12 12 5 19 12" />
</svg>
</span>
<span>{dict.footer.book}</span>
</Link>
</div>
</div>
{/* INTEGRATED AMENITIES COMPONENT */}
<div className="mt-20">
<Amenities dict={dict} />
</div>
</section>
{/* SECTION 3: GALLERY GRID */}
<section className="py-24 px-6 md:px-16 max-w-[1400px] mx-auto pb-44">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="aspect-square relative overflow-hidden rounded-[2px] shadow-lg">
<Image src={suite.gallery[0]} alt="Gallery" fill className="object-cover hover:scale-105 transition-transform duration-1000" />
</div>
<div className="aspect-square relative overflow-hidden rounded-[2px] shadow-lg">
<Image src={suite.gallery[1]} alt="Gallery" fill className="object-cover hover:scale-105 transition-transform duration-1000" />
</div>
<div className="md:col-span-2 aspect-[21/9] relative overflow-hidden rounded-[2px] shadow-lg">
<Image src={suite.gallery[2]} alt="Gallery" fill className="object-cover hover:scale-105 transition-transform duration-1000" />
</div>
</div>
</section>
</main>
)
}

View File

@@ -0,0 +1,19 @@
import { getDictionary } from "@/dictionaries/get-dictionary"
import SuiteDetailClient from "./SuiteDetailClient"
export async function generateMetadata({ params }: { params: Promise<{ lang: string, id: string }> }) {
const { lang, id } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return {
title: `Suites - Ayris Apart`,
description: dict.suites_page.subtitle,
}
}
export default async function SuiteDetailPage({ params }: { params: Promise<{ lang: string, id: string }> }) {
const { lang, id } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return <SuiteDetailClient lang={lang} id={id} dict={dict} />
}

View File

@@ -0,0 +1,18 @@
import { getDictionary } from "@/dictionaries/get-dictionary"
import SuitesClient from "./SuitesClient"
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return {
title: `${dict.suites_page.title} - Ayris Apart`,
description: dict.suites_page.subtitle,
}
}
export default async function SuitesPage({ params }: { params: Promise<{ lang: string }> }) {
const { lang } = await params
const dict = await getDictionary(lang as 'en' | 'tr')
return <SuitesClient lang={lang} dict={dict} />
}