feat: i18n fixes, blog rename, footer cleanup, and contact info update
- Rename /news route to /blog across all pages, links, and sitemap - Fix hardcoded English text in Experiences, QuoteSection, and Footer by wiring all content through the TR/EN dictionaries - Clean up Footer: remove non-existent page links, add contact column - Update contact info: new phone numbers, bilgi@ email, No:71 address, Instagram @ayrisapart link - Add suppressHydrationWarning to <body> to silence browser-extension attribute mismatch errors - Add sizes prop to all fill-mode Next.js Image components Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,3 +39,5 @@ yarn-error.log*
|
|||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
|
/lib/generated/prisma
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { motion } from "framer-motion"
|
||||||
|
import Image from "next/image"
|
||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
|
export default function NewsClient({ lang, dict, posts }: { lang: string, dict: any, posts: any[] }) {
|
||||||
|
return (
|
||||||
|
<main className="bg-[#FAF7F0] min-h-screen">
|
||||||
|
{/* HEADER */}
|
||||||
|
<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 }}
|
||||||
|
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 }}
|
||||||
|
className="text-[#1A1A1A]/60 text-lg md:text-xl max-w-2xl mx-auto font-medium leading-relaxed italic"
|
||||||
|
>
|
||||||
|
{dict.news_page.excerpt}
|
||||||
|
</motion.p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* POSTS GRID */}
|
||||||
|
<section className="pb-44 px-6 md:px-12 max-w-[1400px] mx-auto">
|
||||||
|
{posts.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-20">
|
||||||
|
{posts.map((post, idx) => (
|
||||||
|
<motion.div
|
||||||
|
key={post.id}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: idx * 0.1 }}
|
||||||
|
className="group"
|
||||||
|
>
|
||||||
|
<Link href={`/${lang}/blog/${post.slug}`}>
|
||||||
|
<div className="aspect-[16/10] relative overflow-hidden rounded-[2px] shadow-sm bg-white">
|
||||||
|
{post.image && (
|
||||||
|
<Image
|
||||||
|
src={post.image}
|
||||||
|
alt={post.title}
|
||||||
|
fill
|
||||||
|
sizes="(max-width: 768px) 100vw, 33vw"
|
||||||
|
className="object-cover transition-transform duration-700 group-hover:scale-105"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 space-y-4">
|
||||||
|
<div className="flex items-center space-x-4 text-[11px] font-bold tracking-[0.2em] uppercase text-[#1A1A1A]/40">
|
||||||
|
<span>{post.author}</span>
|
||||||
|
<span>•</span>
|
||||||
|
<span>{new Date(post.createdAt).toLocaleDateString(lang === 'tr' ? 'tr-TR' : 'en-US')}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-serif text-[#1A1A1A] group-hover:text-[#C88C4B] transition-colors leading-tight">
|
||||||
|
{post.title}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className="text-[#1A1A1A]/60 text-base leading-relaxed line-clamp-2 italic">
|
||||||
|
{post.excerpt}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="inline-flex items-center space-x-3 text-[12px] font-bold tracking-[0.3em] uppercase border-b border-[#1A1A1A] pb-1">
|
||||||
|
<span>{dict.news_page.read}</span>
|
||||||
|
<span className="text-lg">→</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-center py-20">
|
||||||
|
<p className="text-[#1A1A1A]/40 italic">{lang === 'tr' ? 'Henüz yazı bulunmuyor.' : 'No stories found yet.'}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { motion } from "framer-motion"
|
||||||
|
import Image from "next/image"
|
||||||
|
import Link from "next/link"
|
||||||
|
import { ArrowLeft, Clock, User } from 'lucide-react'
|
||||||
|
|
||||||
|
export default function NewsDetailClient({ lang, dict, post }: { lang: string, dict: any, post: any }) {
|
||||||
|
return (
|
||||||
|
<main className="bg-[#FAF7F0] min-h-screen">
|
||||||
|
{/* HEADER & IMAGE */}
|
||||||
|
<section className="pt-44 pb-20 px-6 max-w-[1000px] mx-auto">
|
||||||
|
<div className="space-y-12">
|
||||||
|
{/* Back Button */}
|
||||||
|
<Link href={`/${lang}/blog`} 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' ? 'Haberlere Dön' : 'Back to News'}</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<div className="space-y-8 text-center md:text-left">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 10 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
className="flex flex-wrap justify-center md:justify-start items-center gap-6 text-[12px] font-bold tracking-[0.2em] uppercase text-[#1A1A1A]/30"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<User size={14} className="text-[#C88C4B]" />
|
||||||
|
<span>{post.author}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Clock size={14} className="text-[#C88C4B]" />
|
||||||
|
<span>{new Date(post.createdAt).toLocaleDateString(lang === 'tr' ? 'tr-TR' : 'en-US')}</span>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.h1
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: 0.1 }}
|
||||||
|
className="text-5xl md:text-[80px] font-serif text-[#1A1A1A] leading-[1.1] tracking-tight"
|
||||||
|
>
|
||||||
|
{post.title}
|
||||||
|
</motion.h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{post.image && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, scale: 0.98 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
transition={{ duration: 1, delay: 0.2 }}
|
||||||
|
className="aspect-[21/10] relative overflow-hidden rounded-[2px] shadow-2xl"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={post.image}
|
||||||
|
alt={post.title}
|
||||||
|
fill
|
||||||
|
sizes="100vw"
|
||||||
|
className="object-cover"
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* CONTENT */}
|
||||||
|
<section className="pb-44 px-6 max-w-[800px] mx-auto">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ delay: 0.4 }}
|
||||||
|
className="prose prose-neutral prose-xl max-w-none"
|
||||||
|
>
|
||||||
|
<p className="text-2xl md:text-3xl font-serif text-[#1A1A1A] italic leading-relaxed mb-12 opacity-80 border-l-4 border-[#C88C4B] pl-8">
|
||||||
|
{post.excerpt}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="text-[#1A1A1A]/80 leading-loose text-lg md:text-xl space-y-8 whitespace-pre-wrap">
|
||||||
|
{post.content}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<div className="mt-32 pt-12 border-t border-[#1A1A1A]/10 text-center">
|
||||||
|
<Link
|
||||||
|
href={`/${lang}/contact`}
|
||||||
|
className="inline-flex items-center space-x-4 text-[13px] font-bold tracking-[0.4em] uppercase border-b-2 border-[#1A1A1A] pb-2 group"
|
||||||
|
>
|
||||||
|
<span>{dict.footer.book}</span>
|
||||||
|
<span className="transform group-hover:translate-x-1 transition-transform">→</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
import { getDictionary } from "@/dictionaries/get-dictionary"
|
import { getDictionary } from "@/dictionaries/get-dictionary"
|
||||||
import NewsDetailClient from "./NewsDetailClient"
|
import NewsDetailClient from "./NewsDetailClient"
|
||||||
|
import { prisma } from "@/lib/prisma"
|
||||||
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string, slug: string }> }) {
|
export async function generateMetadata({ params }: { params: Promise<{ lang: string, slug: string }> }) {
|
||||||
const { lang, slug } = await params
|
const { lang, slug } = await params
|
||||||
const dict = await getDictionary(lang as 'en' | 'tr')
|
|
||||||
|
|
||||||
// Dynamic title based on slug if possible, or just section title
|
const post = await prisma.post.findUnique({
|
||||||
|
where: { slug }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!post) return { title: 'Post Not Found' }
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: `News - Ayris Apart`,
|
title: `${post.title} - Ayris Apart`,
|
||||||
description: dict.news_page.excerpt,
|
description: post.excerpt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,5 +22,11 @@ export default async function NewsDetailPage({ params }: { params: Promise<{ lan
|
|||||||
const { lang, slug } = await params
|
const { lang, slug } = await params
|
||||||
const dict = await getDictionary(lang as 'en' | 'tr')
|
const dict = await getDictionary(lang as 'en' | 'tr')
|
||||||
|
|
||||||
return <NewsDetailClient lang={lang} slug={slug} dict={dict} />
|
const post = await prisma.post.findUnique({
|
||||||
|
where: { slug }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!post) notFound()
|
||||||
|
|
||||||
|
return <NewsDetailClient lang={lang} dict={dict} post={post} />
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { getDictionary } from "@/dictionaries/get-dictionary"
|
import { getDictionary } from "@/dictionaries/get-dictionary"
|
||||||
import NewsClient from "./NewsClient"
|
import NewsClient from "./NewsClient"
|
||||||
|
import { prisma } from "@/lib/prisma"
|
||||||
|
|
||||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||||
const { lang } = await params
|
const { lang } = await params
|
||||||
@@ -14,5 +15,16 @@ export default async function NewsPage({ params }: { params: Promise<{ lang: str
|
|||||||
const { lang } = await params
|
const { lang } = await params
|
||||||
const dict = await getDictionary(lang as 'en' | 'tr')
|
const dict = await getDictionary(lang as 'en' | 'tr')
|
||||||
|
|
||||||
return <NewsClient lang={lang} dict={dict} />
|
// Fetch posts from database based on the selected language
|
||||||
|
const posts = await prisma.post.findMany({
|
||||||
|
where: {
|
||||||
|
lang: lang,
|
||||||
|
published: true
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
createdAt: 'desc'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return <NewsClient lang={lang} dict={dict} posts={posts} />
|
||||||
}
|
}
|
||||||
@@ -70,9 +70,10 @@ export default function ContactClient({ lang, dict }: { lang: string, dict: any
|
|||||||
<h3 className="text-3xl font-serif">{dict.contact.call.t}</h3>
|
<h3 className="text-3xl font-serif">{dict.contact.call.t}</h3>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<p className="text-2xl font-medium">+90 543 231 87 13</p>
|
<p className="text-2xl font-medium">+90 543 231 87 13</p>
|
||||||
|
<p className="text-2xl font-medium">+90 554 376 51 03</p>
|
||||||
<p className="text-lg text-[#1A1A1A]/50 italic">{dict.contact.call.d}</p>
|
<p className="text-lg text-[#1A1A1A]/50 italic">{dict.contact.call.d}</p>
|
||||||
</div>
|
</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">
|
<Link href="tel:+905543765103" 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>
|
<span>{dict.contact.btn.call}</span>
|
||||||
<ArrowUpRight size={14} />
|
<ArrowUpRight size={14} />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -91,10 +92,10 @@ export default function ContactClient({ lang, dict }: { lang: string, dict: any
|
|||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<h3 className="text-3xl font-serif">{dict.contact.write.t}</h3>
|
<h3 className="text-3xl font-serif">{dict.contact.write.t}</h3>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<p className="text-2xl font-medium">hello@ayrisapart.com</p>
|
<p className="text-2xl font-medium">bilgi@ayrisapart.com</p>
|
||||||
<p className="text-lg text-[#1A1A1A]/50 italic">{dict.contact.write.d}</p>
|
<p className="text-lg text-[#1A1A1A]/50 italic">{dict.contact.write.d}</p>
|
||||||
</div>
|
</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">
|
<Link href="mailto:bilgi@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>
|
<span>{dict.contact.btn.mail}</span>
|
||||||
<ArrowUpRight size={14} />
|
<ArrowUpRight size={14} />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -114,7 +115,7 @@ export default function ContactClient({ lang, dict }: { lang: string, dict: any
|
|||||||
<p className="text-xl text-[#1A1A1A]/60 italic leading-relaxed">
|
<p className="text-xl text-[#1A1A1A]/60 italic leading-relaxed">
|
||||||
{dict.contact.wa.d}
|
{dict.contact.wa.d}
|
||||||
</p>
|
</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">
|
<Link href="https://wa.me/905543765103" 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>
|
<span>{dict.contact.btn.wa}</span>
|
||||||
<ArrowUpRight size={14} />
|
<ArrowUpRight size={14} />
|
||||||
</Link>
|
</Link>
|
||||||
@@ -135,7 +136,7 @@ export default function ContactClient({ lang, dict }: { lang: string, dict: any
|
|||||||
<p className="text-xl text-[#1A1A1A]/60 italic leading-relaxed">
|
<p className="text-xl text-[#1A1A1A]/60 italic leading-relaxed">
|
||||||
{dict.contact.ig.d}
|
{dict.contact.ig.d}
|
||||||
</p>
|
</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">
|
<Link href="https://instagram.com/ayrisapart" 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.ig}</span>
|
<span>{dict.contact.btn.ig}</span>
|
||||||
<ArrowUpRight size={14} />
|
<ArrowUpRight size={14} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
+38
-1
@@ -37,9 +37,46 @@ export default async function RootLayout({
|
|||||||
const { lang } = await params;
|
const { lang } = await params;
|
||||||
const dict = await getDictionary(lang as 'en' | 'tr');
|
const dict = await getDictionary(lang as 'en' | 'tr');
|
||||||
|
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Hotel",
|
||||||
|
"name": "Ayris Apart",
|
||||||
|
"description": dict.hero.desc,
|
||||||
|
"address": {
|
||||||
|
"@type": "PostalAddress",
|
||||||
|
"streetAddress": "Orta İskele Caddesi No:71",
|
||||||
|
"addressLocality": "Milas",
|
||||||
|
"addressRegion": "Muğla",
|
||||||
|
"postalCode": "48220",
|
||||||
|
"addressCountry": "TR"
|
||||||
|
},
|
||||||
|
"geo": {
|
||||||
|
"@type": "GeoCoordinates",
|
||||||
|
"latitude": 37.037,
|
||||||
|
"longitude": 27.962
|
||||||
|
},
|
||||||
|
"url": "https://ayrisapart.com",
|
||||||
|
"telephone": "+90",
|
||||||
|
"image": "https://ayrisapart.com/logo.png",
|
||||||
|
"amenityFeature": [
|
||||||
|
{ "@type": "LocationFeatureSpecification", "name": "Free Wi-Fi", "value": true },
|
||||||
|
{ "@type": "LocationFeatureSpecification", "name": "Kitchen", "value": true },
|
||||||
|
{ "@type": "LocationFeatureSpecification", "name": "Air Conditioning", "value": true },
|
||||||
|
{ "@type": "LocationFeatureSpecification", "name": "Free Parking", "value": true }
|
||||||
|
],
|
||||||
|
"checkinTime": "14:00",
|
||||||
|
"checkoutTime": "11:00"
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang={lang} className={`${oranienbaum.variable} ${inter.variable} h-full antialiased`}>
|
<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]">
|
<head>
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body className="font-sans min-h-full flex flex-col bg-[#FAF7F0] text-[#1A1A1A]" suppressHydrationWarning>
|
||||||
<Navbar lang={lang} dict={dict} />
|
<Navbar lang={lang} dict={dict} />
|
||||||
{children}
|
{children}
|
||||||
<Footer lang={lang} dict={dict} />
|
<Footer lang={lang} dict={dict} />
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
'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>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
'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' ? 'Ören’in 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 Ege’nin 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">
|
|
||||||
“{block.text}”
|
|
||||||
</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>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
+2
-2
@@ -28,9 +28,9 @@ export default async function Home({ params }: { params: Promise<{ lang: string
|
|||||||
<Hero lang={lang} dict={dict} />
|
<Hero lang={lang} dict={dict} />
|
||||||
<Welcome lang={lang} dict={dict} />
|
<Welcome lang={lang} dict={dict} />
|
||||||
<ShowcaseImage />
|
<ShowcaseImage />
|
||||||
<QuoteSection />
|
<QuoteSection dict={dict} />
|
||||||
<SuitesHighlights lang={lang} dict={dict} />
|
<SuitesHighlights lang={lang} dict={dict} />
|
||||||
<Experiences />
|
<Experiences dict={dict} />
|
||||||
<ScrollReveal />
|
<ScrollReveal />
|
||||||
<CallToAction lang={lang} dict={dict} />
|
<CallToAction lang={lang} dict={dict} />
|
||||||
|
|
||||||
|
|||||||
@@ -8,21 +8,21 @@ import Amenities from "@/components/Amenities"
|
|||||||
|
|
||||||
export default function SuitesClient({ lang, dict }: { lang: string, dict: any }) {
|
export default function SuitesClient({ lang, dict }: { lang: string, dict: any }) {
|
||||||
const suites = [
|
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: '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, price: dict.suites_page.list.s1.price },
|
||||||
{ 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: '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_4_2024-04-05_16-04-34.jpg', bed: dict.suites_page.list.s2.bed, guests: dict.suites_page.list.s2.guests, price: dict.suites_page.list.s2.price },
|
||||||
{ 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: '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_8_2024-04-05_16-06-09.jpg', bed: dict.suites_page.list.s3.bed, guests: dict.suites_page.list.s3.guests, price: dict.suites_page.list.s3.price },
|
||||||
{ 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: '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_8_2024-04-05_16-07-01.jpg', bed: dict.suites_page.list.s4.bed, guests: dict.suites_page.list.s4.guests, price: dict.suites_page.list.s4.price },
|
||||||
{ 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: '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, price: dict.suites_page.list.s5.price },
|
||||||
{ 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: '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-33-08.jpg', bed: dict.suites_page.list.s6.bed, guests: dict.suites_page.list.s6.guests, price: dict.suites_page.list.s6.price },
|
||||||
{ 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: '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_5_2024-05-04_15-33-34.jpg', bed: dict.suites_page.list.s7.bed, guests: dict.suites_page.list.s7.guests, price: dict.suites_page.list.s7.price },
|
||||||
{ 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 },
|
{ 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_9_2024-05-04_15-33-34.jpg', bed: dict.suites_page.list.s8.bed, guests: dict.suites_page.list.s8.guests, price: dict.suites_page.list.s8.price },
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="bg-[#FAF7F0] min-h-screen z-60 ">
|
<main className="bg-[#FAF7F0] min-h-screen">
|
||||||
|
|
||||||
{/* HEADER SECTION */}
|
{/* HEADER SECTION */}
|
||||||
<section className="pt-44 pb-20 px-6 ">
|
<section className="pt-44 pb-20 px-6">
|
||||||
<div className="max-w-4xl mx-auto text-center space-y-10">
|
<div className="max-w-4xl mx-auto text-center space-y-10">
|
||||||
<motion.h1
|
<motion.h1
|
||||||
initial={{ opacity: 0, y: 30 }}
|
initial={{ opacity: 0, y: 30 }}
|
||||||
@@ -45,7 +45,7 @@ export default function SuitesClient({ lang, dict }: { lang: string, dict: any }
|
|||||||
|
|
||||||
{/* SUITES LIST SECTION */}
|
{/* SUITES LIST SECTION */}
|
||||||
<section className="pb-32 px-6 md:px-12 max-w-[1400px] mx-auto">
|
<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">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-32">
|
||||||
{suites.map((suite, idx) => (
|
{suites.map((suite, idx) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={suite.id}
|
key={suite.id}
|
||||||
@@ -61,8 +61,14 @@ export default function SuitesClient({ lang, dict }: { lang: string, dict: any }
|
|||||||
src={suite.image}
|
src={suite.image}
|
||||||
alt={suite.name}
|
alt={suite.name}
|
||||||
fill
|
fill
|
||||||
|
sizes="(max-width: 768px) 100vw, 50vw"
|
||||||
className="object-cover transition-transform duration-1000 group-hover:scale-105"
|
className="object-cover transition-transform duration-1000 group-hover:scale-105"
|
||||||
/>
|
/>
|
||||||
|
{/* Price Badge */}
|
||||||
|
<div className="absolute top-6 right-6 bg-white/90 backdrop-blur-md px-6 py-3 rounded-full shadow-xl">
|
||||||
|
<span className="text-[#1A1A1A] font-serif text-xl">{suite.price}</span>
|
||||||
|
<span className="text-[#1A1A1A]/40 text-xs ml-1 uppercase tracking-widest">/ {lang === 'tr' ? 'Gece' : 'Night'}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Info */}
|
{/* Info */}
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import { Users, BedDouble, ArrowLeft } from 'lucide-react'
|
|||||||
import Amenities from "@/components/Amenities"
|
import Amenities from "@/components/Amenities"
|
||||||
|
|
||||||
export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id: string, dict: any }) {
|
export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id: string, dict: any }) {
|
||||||
// Mapping the 8 mythological suites with their Cloudinary assets
|
// Mapping the 8 mythological suites with their Cloudinary assets and dictionary prices
|
||||||
const suitesData: Record<string, any> = {
|
const suitesData: Record<string, any> = {
|
||||||
'iris': {
|
'iris': {
|
||||||
number: '01',
|
number: '01',
|
||||||
name: dict.suites_page.list.s1.name,
|
name: dict.suites_page.list.s1.name,
|
||||||
description: dict.suites_page.list.s1.desc,
|
description: dict.suites_page.list.s1.desc,
|
||||||
|
price: dict.suites_page.list.s1.price,
|
||||||
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606641/ayrisapart/Daire%201/photo_1_2024-04-05_12-32-09.jpg',
|
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,
|
guests: dict.suites_page.list.s1.guests,
|
||||||
bed: dict.suites_page.list.s1.bed,
|
bed: dict.suites_page.list.s1.bed,
|
||||||
@@ -26,7 +27,8 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
number: '02',
|
number: '02',
|
||||||
name: dict.suites_page.list.s2.name,
|
name: dict.suites_page.list.s2.name,
|
||||||
description: dict.suites_page.list.s2.desc,
|
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',
|
price: dict.suites_page.list.s2.price,
|
||||||
|
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606648/ayrisapart/Daire%202/photo_4_2024-04-05_16-04-34.jpg',
|
||||||
guests: dict.suites_page.list.s2.guests,
|
guests: dict.suites_page.list.s2.guests,
|
||||||
bed: dict.suites_page.list.s2.bed,
|
bed: dict.suites_page.list.s2.bed,
|
||||||
gallery: [
|
gallery: [
|
||||||
@@ -39,6 +41,7 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
number: '03',
|
number: '03',
|
||||||
name: dict.suites_page.list.s3.name,
|
name: dict.suites_page.list.s3.name,
|
||||||
description: dict.suites_page.list.s3.desc,
|
description: dict.suites_page.list.s3.desc,
|
||||||
|
price: dict.suites_page.list.s3.price,
|
||||||
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606654/ayrisapart/Daire%203/photo_1_2024-04-05_16-06-09.jpg',
|
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,
|
guests: dict.suites_page.list.s3.guests,
|
||||||
bed: dict.suites_page.list.s3.bed,
|
bed: dict.suites_page.list.s3.bed,
|
||||||
@@ -52,6 +55,7 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
number: '04',
|
number: '04',
|
||||||
name: dict.suites_page.list.s4.name,
|
name: dict.suites_page.list.s4.name,
|
||||||
description: dict.suites_page.list.s4.desc,
|
description: dict.suites_page.list.s4.desc,
|
||||||
|
price: dict.suites_page.list.s4.price,
|
||||||
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606661/ayrisapart/Daire%204/photo_1_2024-04-05_16-07-01.jpg',
|
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,
|
guests: dict.suites_page.list.s4.guests,
|
||||||
bed: dict.suites_page.list.s4.bed,
|
bed: dict.suites_page.list.s4.bed,
|
||||||
@@ -65,6 +69,7 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
number: '05',
|
number: '05',
|
||||||
name: dict.suites_page.list.s5.name,
|
name: dict.suites_page.list.s5.name,
|
||||||
description: dict.suites_page.list.s5.desc,
|
description: dict.suites_page.list.s5.desc,
|
||||||
|
price: dict.suites_page.list.s5.price,
|
||||||
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606671/ayrisapart/Daire%205/photo_1_2024-05-04_15-32-44.jpg',
|
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,
|
guests: dict.suites_page.list.s5.guests,
|
||||||
bed: dict.suites_page.list.s5.bed,
|
bed: dict.suites_page.list.s5.bed,
|
||||||
@@ -78,6 +83,7 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
number: '06',
|
number: '06',
|
||||||
name: dict.suites_page.list.s6.name,
|
name: dict.suites_page.list.s6.name,
|
||||||
description: dict.suites_page.list.s6.desc,
|
description: dict.suites_page.list.s6.desc,
|
||||||
|
price: dict.suites_page.list.s6.price,
|
||||||
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606681/ayrisapart/Daire%206/photo_1_2024-05-04_15-32-44.jpg',
|
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,
|
guests: dict.suites_page.list.s6.guests,
|
||||||
bed: dict.suites_page.list.s6.bed,
|
bed: dict.suites_page.list.s6.bed,
|
||||||
@@ -91,6 +97,7 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
number: '07',
|
number: '07',
|
||||||
name: dict.suites_page.list.s7.name,
|
name: dict.suites_page.list.s7.name,
|
||||||
description: dict.suites_page.list.s7.desc,
|
description: dict.suites_page.list.s7.desc,
|
||||||
|
price: dict.suites_page.list.s7.price,
|
||||||
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606689/ayrisapart/Daire%207/photo_1_2024-05-04_15-33-34.jpg',
|
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,
|
guests: dict.suites_page.list.s7.guests,
|
||||||
bed: dict.suites_page.list.s7.bed,
|
bed: dict.suites_page.list.s7.bed,
|
||||||
@@ -104,6 +111,7 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
number: '08',
|
number: '08',
|
||||||
name: dict.suites_page.list.s8.name,
|
name: dict.suites_page.list.s8.name,
|
||||||
description: dict.suites_page.list.s8.desc,
|
description: dict.suites_page.list.s8.desc,
|
||||||
|
price: dict.suites_page.list.s8.price,
|
||||||
mainImage: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606696/ayrisapart/Daire%208/photo_1_2024-05-04_15-33-34.jpg',
|
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,
|
guests: dict.suites_page.list.s8.guests,
|
||||||
bed: dict.suites_page.list.s8.bed,
|
bed: dict.suites_page.list.s8.bed,
|
||||||
@@ -131,7 +139,7 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
|
|
||||||
{/* Title and Brief Header */}
|
{/* Title and Brief Header */}
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<motion.h1
|
<motion.h1
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
className="text-6xl md:text-[88px] font-serif text-[#1A1A1A] tracking-tight leading-none uppercase"
|
className="text-6xl md:text-[88px] font-serif text-[#1A1A1A] tracking-tight leading-none uppercase"
|
||||||
@@ -153,19 +161,20 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Main Visual */}
|
{/* Main Visual */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.98 }}
|
initial={{ opacity: 0, scale: 0.98 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
transition={{ duration: 1 }}
|
transition={{ duration: 1 }}
|
||||||
className="aspect-[21/9] relative overflow-hidden rounded-[2px] shadow-2xl"
|
className="aspect-[21/9] relative overflow-hidden rounded-[2px] shadow-2xl"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={suite.mainImage}
|
src={suite.mainImage}
|
||||||
alt={suite.name}
|
alt={suite.name}
|
||||||
fill
|
fill
|
||||||
className="object-cover"
|
sizes="100vw"
|
||||||
priority
|
className="object-cover"
|
||||||
/>
|
priority
|
||||||
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -174,45 +183,53 @@ export default function SuiteDetailClient({ lang, id, dict }: { lang: string, id
|
|||||||
<section className="py-24 px-6 md:px-16 max-w-[1400px] mx-auto">
|
<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="grid grid-cols-1 md:grid-cols-12 gap-16 border-b border-[#1A1A1A]/10 pb-20">
|
||||||
<div className="md:col-span-4">
|
<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>
|
<h2 className="text-4xl font-serif text-[#1A1A1A] uppercase tracking-tight">{lang === 'tr' ? 'Suit Hakkında' : 'About Suite'}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-8 space-y-12">
|
<div className="md:col-span-8 space-y-12">
|
||||||
<p className="text-[#1A1A1A]/70 text-2xl leading-relaxed italic max-w-2xl">
|
<div className="flex justify-between items-baseline">
|
||||||
{suite.description}
|
<span className="text-[13px] font-bold tracking-[0.3em] uppercase text-[#1A1A1A]/40">{lang === 'tr' ? 'Başlayan fiyatlar' : 'Starting at'}</span>
|
||||||
</p>
|
<div className="text-right">
|
||||||
<Link
|
<span className="text-6xl md:text-8xl font-serif text-[#1A1A1A]">{suite.price}</span>
|
||||||
href={`/${lang}/reservation`}
|
<span className="text-[#1A1A1A]/40 text-lg font-medium ml-2 uppercase tracking-widest">/ {lang === 'tr' ? 'Gece' : 'Night'}</span>
|
||||||
className="inline-flex items-center space-x-3 text-[14px] font-bold tracking-[0.4em] uppercase border-b-2 border-[#1A1A1A] pb-2 group"
|
</div>
|
||||||
>
|
</div>
|
||||||
<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">
|
<p className="text-[#1A1A1A]/70 text-2xl leading-relaxed italic max-w-2xl">
|
||||||
<line x1="12" y1="19" x2="12" y2="5" />
|
{suite.description}
|
||||||
<polyline points="5 12 12 5 19 12" />
|
</p>
|
||||||
</svg>
|
<Link
|
||||||
</span>
|
href={`/${lang}/reservation`}
|
||||||
<span>{dict.footer.book}</span>
|
className="inline-flex items-center space-x-3 text-[14px] font-bold tracking-[0.4em] uppercase border-b-2 border-[#1A1A1A] pb-2 group"
|
||||||
</Link>
|
>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* INTEGRATED AMENITIES COMPONENT */}
|
{/* INTEGRATED AMENITIES COMPONENT */}
|
||||||
<div className="mt-20">
|
<div className="mt-20">
|
||||||
<Amenities dict={dict} />
|
<Amenities dict={dict} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* SECTION 3: GALLERY GRID */}
|
{/* SECTION 3: GALLERY GRID */}
|
||||||
<section className="py-24 px-6 md:px-16 max-w-[1400px] mx-auto pb-44">
|
<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="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
<div className="aspect-square relative overflow-hidden rounded-[2px] shadow-lg">
|
<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" />
|
<Image src={suite.gallery[0]} alt="Gallery" fill sizes="(max-width: 768px) 100vw, 50vw" className="object-cover hover:scale-105 transition-transform duration-1000" />
|
||||||
</div>
|
</div>
|
||||||
<div className="aspect-square relative overflow-hidden rounded-[2px] shadow-lg">
|
<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" />
|
<Image src={suite.gallery[1]} alt="Gallery" fill sizes="(max-width: 768px) 100vw, 50vw" className="object-cover hover:scale-105 transition-transform duration-1000" />
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2 aspect-[21/9] relative overflow-hidden rounded-[2px] shadow-lg">
|
<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" />
|
<Image src={suite.gallery[2]} alt="Gallery" fill sizes="100vw" className="object-cover hover:scale-105 transition-transform duration-1000" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { MetadataRoute } from 'next'
|
||||||
|
import { prisma } from '@/lib/prisma'
|
||||||
|
|
||||||
|
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||||
|
const baseUrl = 'https://ayrisapart.com'
|
||||||
|
const languages = ['tr', 'en']
|
||||||
|
|
||||||
|
// 1. Static Routes
|
||||||
|
const staticRoutes = [
|
||||||
|
'',
|
||||||
|
'/about',
|
||||||
|
'/suites',
|
||||||
|
'/blog',
|
||||||
|
'/contact',
|
||||||
|
]
|
||||||
|
|
||||||
|
const staticEntries: MetadataRoute.Sitemap = []
|
||||||
|
|
||||||
|
languages.forEach((lang) => {
|
||||||
|
staticRoutes.forEach((route) => {
|
||||||
|
staticEntries.push({
|
||||||
|
url: `${baseUrl}/${lang}${route}`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: route === '' ? 1 : 0.8,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2. Dynamic Suite Routes (8 mythological rooms)
|
||||||
|
const suites = ['iris', 'electra', 'arke', 'harpy', 'hydaspes', 'zephyrus', 'pothos', 'thaumas']
|
||||||
|
const suiteEntries: MetadataRoute.Sitemap = []
|
||||||
|
|
||||||
|
languages.forEach((lang) => {
|
||||||
|
suites.forEach((id) => {
|
||||||
|
suiteEntries.push({
|
||||||
|
url: `${baseUrl}/${lang}/suites/${id}`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.7,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 3. Dynamic News Routes (from Database)
|
||||||
|
const posts = await prisma.post.findMany({
|
||||||
|
where: { published: true },
|
||||||
|
select: { slug: true, lang: true, updatedAt: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
const newsEntries: MetadataRoute.Sitemap = posts.map((post) => ({
|
||||||
|
url: `${baseUrl}/${post.lang}/blog/${post.slug}`,
|
||||||
|
lastModified: post.updatedAt,
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.6,
|
||||||
|
}))
|
||||||
|
|
||||||
|
return [...staticEntries, ...suiteEntries, ...newsEntries]
|
||||||
|
}
|
||||||
@@ -7,25 +7,25 @@ import Image from 'next/image'
|
|||||||
|
|
||||||
const images = [
|
const images = [
|
||||||
{
|
{
|
||||||
src: "https://images.unsplash.com/photo-1541410950669-e771b058097d?q=80&w=2070&auto=format&fit=crop",
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/1_cxfvrw.jpg",
|
||||||
w: 305, h: 225,
|
w: 305, h: 425,
|
||||||
tx: -550, ty: -350,
|
tx: -550, ty: -350,
|
||||||
rotate: -2
|
rotate: -2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "https://images.unsplash.com/photo-1590490360182-c33d57733427?q=80&w=2100&auto=format&fit=crop",
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/7_yuouc0.jpg",
|
||||||
w: 325, h: 425,
|
w: 325, h: 425,
|
||||||
tx: 550, ty: -350,
|
tx: 550, ty: -350,
|
||||||
rotate: 1
|
rotate: 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "https://images.unsplash.com/photo-1566665797739-1674de7a421a?q=80&w=2070&auto=format&fit=crop",
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/2_dfrmwi.jpg",
|
||||||
w: 385, h: 485,
|
w: 385, h: 485,
|
||||||
tx: -550, ty: 350,
|
tx: -550, ty: 350,
|
||||||
rotate: -1
|
rotate: -1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "https://images.unsplash.com/photo-1571896349842-33c89424de2d?q=80&w=2073&auto=format&fit=crop",
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/8_kjih1z.jpg",
|
||||||
w: 425, h: 365,
|
w: 425, h: 365,
|
||||||
tx: 550, ty: 350,
|
tx: 550, ty: 350,
|
||||||
rotate: 2
|
rotate: 2
|
||||||
@@ -81,7 +81,7 @@ export default function CallToAction({ lang, dict }: { lang: string, dict: any }
|
|||||||
>
|
>
|
||||||
<div className={`relative shadow-2xl p-4 bg-white`} style={{ width: img.w, height: img.h }}>
|
<div className={`relative shadow-2xl p-4 bg-white`} style={{ width: img.w, height: img.h }}>
|
||||||
<div className="relative w-full h-full">
|
<div className="relative w-full h-full">
|
||||||
<Image src={img.src} alt="Ayris" fill className="object-cover" />
|
<Image src={img.src} alt="Ayris" fill sizes="(max-width: 768px) 100vw, 50vw" className="object-cover" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
+16
-24
@@ -4,34 +4,25 @@ import { motion, AnimatePresence } from 'framer-motion'
|
|||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
const experiences = [
|
const experienceImages = [
|
||||||
{
|
"https://res.cloudinary.com/du7xohbct/image/upload/v1776642503/ayrisapart/experiences/akbuk_cjfyan.jpg",
|
||||||
title: "Infinity Pool",
|
"https://res.cloudinary.com/du7xohbct/image/upload/v1776642502/ayrisapart/experiences/oren_d2pxcy.jpg",
|
||||||
description: "Swim towards the horizon in our stunning heated infinity pool, overlooking the turquoise expanse of the Aegean Sea.",
|
"https://res.cloudinary.com/du7xohbct/image/upload/v1776642501/ayrisapart/experiences/alatepe_oawu3z.jpg",
|
||||||
image: "https://images.unsplash.com/photo-1576013551627-0cfde316be70?q=80&w=1974&auto=format&fit=crop"
|
"https://res.cloudinary.com/du7xohbct/image/upload/v1776642492/ayrisapart/experiences/cokertme_d5qfiw.jpg",
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Snorkeling",
|
|
||||||
description: "Discover vibrant marine life, swim through crystal-clear waters, and experience the wonder of ocean.",
|
|
||||||
image: "https://images.unsplash.com/photo-1544551763-46a013bb70d5?q=80&w=2070&auto=format&fit=crop"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Paddle boarding",
|
|
||||||
description: "Balance your soul and body while gliding over calm morning waves on our premium paddle boards.",
|
|
||||||
image: "https://images.unsplash.com/photo-1517176641128-052478950337?q=80&w=1974&auto=format&fit=crop"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Fishing trips",
|
|
||||||
description: "Join our local experts for an authentic Mediterranean fishing experience at sunrise.",
|
|
||||||
image: "https://images.unsplash.com/photo-1524704652723-21444983944d?q=80&w=1974&auto=format&fit=crop"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function Experiences() {
|
export default function Experiences({ dict }: { dict: any }) {
|
||||||
const [hoveredIdx, setHoveredIdx] = useState<number | null>(null)
|
const [hoveredIdx, setHoveredIdx] = useState<number | null>(null)
|
||||||
|
|
||||||
|
const experiences = [
|
||||||
|
{ title: dict.experiences.e1.title, description: dict.experiences.e1.desc, image: experienceImages[0] },
|
||||||
|
{ title: dict.experiences.e2.title, description: dict.experiences.e2.desc, image: experienceImages[1] },
|
||||||
|
{ title: dict.experiences.e3.title, description: dict.experiences.e3.desc, image: experienceImages[2] },
|
||||||
|
{ title: dict.experiences.e4.title, description: dict.experiences.e4.desc, image: experienceImages[3] },
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="relative z-60 bg-[#FAF7F0] py-32 px-6 md:px-12">
|
<section className="relative z-60 bg-[#FAF7F0] ">
|
||||||
<div className="max-w-[1400px] mx-auto space-y-20">
|
<div className="max-w-[1400px] mx-auto space-y-20">
|
||||||
<div className="text-center space-y-4">
|
<div className="text-center space-y-4">
|
||||||
<motion.h2
|
<motion.h2
|
||||||
@@ -41,7 +32,7 @@ export default function Experiences() {
|
|||||||
transition={{ duration: 1.2, ease: [0.33, 1, 0.68, 1] }}
|
transition={{ duration: 1.2, ease: [0.33, 1, 0.68, 1] }}
|
||||||
className="text-4xl md:text-[64px] font-medium text-[#1A1A1A] leading-tight"
|
className="text-4xl md:text-[64px] font-medium text-[#1A1A1A] leading-tight"
|
||||||
>
|
>
|
||||||
Discover experiences <br /> beyond the shore
|
{dict.experiences.title}
|
||||||
</motion.h2>
|
</motion.h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -67,6 +58,7 @@ export default function Experiences() {
|
|||||||
src={exp.image}
|
src={exp.image}
|
||||||
alt={exp.title}
|
alt={exp.title}
|
||||||
fill
|
fill
|
||||||
|
sizes="(max-width: 768px) 100vw, 33vw"
|
||||||
className="object-cover transition-transform duration-1000 group-hover:scale-110"
|
className="object-cover transition-transform duration-1000 group-hover:scale-110"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
+19
-28
@@ -16,10 +16,10 @@ export default function Footer({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
</h2>
|
</h2>
|
||||||
<div className="space-y-4 pt-10 md:pt-0">
|
<div className="space-y-4 pt-10 md:pt-0">
|
||||||
<div className="flex items-center justify-end space-x-3 text-sm font-medium tracking-widest opacity-80">
|
<div className="flex items-center justify-end space-x-3 text-sm font-medium tracking-widest opacity-80">
|
||||||
<Phone size={15} className="opacity-60" /> <span>+90 543 231 87 13</span>
|
<Phone size={15} className="opacity-60" /> <span>+90 543 231 87 13 — +90 554 376 51 03</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-end space-x-3 text-sm font-medium tracking-widest opacity-80">
|
<div className="flex items-center justify-end space-x-3 text-sm font-medium tracking-widest opacity-80">
|
||||||
<Mail size={15} className="opacity-60" /> <span>hello@ayrisapart.com</span>
|
<Mail size={15} className="opacity-60" /> <span>bilgi@ayrisapart.com</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,12 +33,10 @@ export default function Footer({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
{/* LEFT CONTENT (CTA) */}
|
{/* LEFT CONTENT (CTA) */}
|
||||||
<div className="lg:col-span-5 space-y-10 max-w-sm">
|
<div className="lg:col-span-5 space-y-10 max-w-sm">
|
||||||
<p className="text-white/70 text-[17px] leading-relaxed">
|
<p className="text-white/70 text-[17px] leading-relaxed">
|
||||||
{lang === 'tr'
|
{dict.footer.desc}
|
||||||
? "Konaklamanızı bugün ayırtın ve Ören kıyılarında deniz kenarı lüksünü, nefes kesen manzaraları ve unutulmaz anları keşfedin."
|
|
||||||
: "Book your stay today and discover seaside luxury, breathtaking views, and unforgettable moments on the shores of Oren."}
|
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link
|
||||||
href={`/${lang}/reservation`}
|
href={`/${lang}/contact`}
|
||||||
className="inline-flex items-center space-x-2 border-b border-white/40 pb-1 group hover:border-white transition-all"
|
className="inline-flex items-center space-x-2 border-b border-white/40 pb-1 group hover:border-white transition-all"
|
||||||
>
|
>
|
||||||
<span className="text-[#C88C4B] text-xl transform group-hover:translate-x-1 transition-transform">↳</span>
|
<span className="text-[#C88C4B] text-xl transform group-hover:translate-x-1 transition-transform">↳</span>
|
||||||
@@ -48,45 +46,37 @@ export default function Footer({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
|
|
||||||
{/* RIGHT LINKS */}
|
{/* RIGHT LINKS */}
|
||||||
<div className="lg:col-span-7">
|
<div className="lg:col-span-7">
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-12">
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-12">
|
||||||
{/* EXPLORE */}
|
{/* EXPLORE */}
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<h4 className="text-[10px] font-bold tracking-[0.4em] opacity-40 uppercase">EXPLORE</h4>
|
<h4 className="text-[10px] font-bold tracking-[0.4em] opacity-40 uppercase">{dict.footer.explore}</h4>
|
||||||
<ul className="space-y-4 text-sm font-medium opacity-60 uppercase tracking-widest">
|
<ul className="space-y-4 text-sm font-medium opacity-60 uppercase tracking-widest">
|
||||||
<li><Link href={`/${lang}`} className="hover:opacity-100 transition-opacity">{dict.nav.home}</Link></li>
|
<li><Link href={`/${lang}`} className="hover:opacity-100 transition-opacity">{dict.nav.home}</Link></li>
|
||||||
<li><Link href={`/${lang}/about`} className="hover:opacity-100 transition-opacity">{dict.nav.about}</Link></li>
|
<li><Link href={`/${lang}/about`} className="hover:opacity-100 transition-opacity">{dict.nav.about}</Link></li>
|
||||||
<li><Link href={`/${lang}/news`} className="hover:opacity-100 transition-opacity">{dict.nav.news}</Link></li>
|
|
||||||
<li><Link href={`/${lang}/suites`} className="hover:opacity-100 transition-opacity">{dict.nav.suites}</Link></li>
|
<li><Link href={`/${lang}/suites`} className="hover:opacity-100 transition-opacity">{dict.nav.suites}</Link></li>
|
||||||
</ul>
|
<li><Link href={`/${lang}/blog`} className="hover:opacity-100 transition-opacity">{dict.nav.news}</Link></li>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* OTHERS */}
|
|
||||||
<div className="space-y-8">
|
|
||||||
<h4 className="text-[10px] font-bold tracking-[0.4em] opacity-40 uppercase">OTHERS</h4>
|
|
||||||
<ul className="space-y-4 text-sm font-medium opacity-60 uppercase tracking-widest">
|
|
||||||
<li><Link href={`/${lang}/services`} className="hover:opacity-100 transition-opacity">Services</Link></li>
|
|
||||||
<li><Link href={`/${lang}/activities`} className="hover:opacity-100 transition-opacity">Activities</Link></li>
|
|
||||||
<li><Link href={`/${lang}/gallery`} className="hover:opacity-100 transition-opacity">Gallery</Link></li>
|
|
||||||
<li><Link href={`/${lang}/contact`} className="hover:opacity-100 transition-opacity">{dict.nav.contact}</Link></li>
|
<li><Link href={`/${lang}/contact`} className="hover:opacity-100 transition-opacity">{dict.nav.contact}</Link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* UTILITY */}
|
{/* CONTACT */}
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<h4 className="text-[10px] font-bold tracking-[0.4em] opacity-40 uppercase">UTILITY</h4>
|
<h4 className="text-[10px] font-bold tracking-[0.4em] opacity-40 uppercase">{dict.contact.title}</h4>
|
||||||
<ul className="space-y-4 text-sm font-medium opacity-60 uppercase tracking-widest">
|
<ul className="space-y-4 text-sm font-medium opacity-60 tracking-widest">
|
||||||
<li><Link href={`/${lang}/license`} className="hover:opacity-100 transition-opacity">License</Link></li>
|
<li>+90 543 231 87 13</li>
|
||||||
<li><Link href={`/${lang}/404`} className="hover:opacity-100 transition-opacity">404</Link></li>
|
<li>+90 554 376 51 03</li>
|
||||||
|
<li>bilgi@ayrisapart.com</li>
|
||||||
|
<li className="leading-relaxed">{dict.contact.visit.d}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* SOCIALS */}
|
{/* SOCIALS */}
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<h4 className="text-[10px] font-bold tracking-[0.4em] opacity-40 uppercase">SOCIALS</h4>
|
<h4 className="text-[10px] font-bold tracking-[0.4em] opacity-40 uppercase">{dict.footer.socials}</h4>
|
||||||
<ul className="space-y-4 text-sm font-medium opacity-60 uppercase tracking-widest">
|
<ul className="space-y-4 text-sm font-medium opacity-60 uppercase tracking-widest">
|
||||||
<li><a href="#" className="hover:opacity-100 transition-opacity">Instagram</a></li>
|
<li><a href="https://instagram.com/ayrisapart" target="_blank" className="hover:opacity-100 transition-opacity">Instagram</a></li>
|
||||||
<li><a href="#" className="hover:opacity-100 transition-opacity">Facebook</a></li>
|
<li><a href="#" className="hover:opacity-100 transition-opacity">Facebook</a></li>
|
||||||
<li><a href="#" className="hover:opacity-100 transition-opacity">Twitter</a></li>
|
<li><a href="#" className="hover:opacity-100 transition-opacity">WhatsApp</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -109,7 +99,8 @@ export default function Footer({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
<Image
|
<Image
|
||||||
src="/logo.png"
|
src="/logo.png"
|
||||||
alt="Ayris Apart Logo"
|
alt="Ayris Apart Logo"
|
||||||
fill
|
fill
|
||||||
|
sizes="200px"
|
||||||
className="object-contain filter brightness-0 invert"
|
className="object-contain filter brightness-0 invert"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+22
-22
@@ -8,48 +8,48 @@ import Image from 'next/image'
|
|||||||
const heroSlots = [
|
const heroSlots = [
|
||||||
{
|
{
|
||||||
srcs: [
|
srcs: [
|
||||||
'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?q=80&w=2070&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/1_cxfvrw.jpg',
|
||||||
'https://images.unsplash.com/photo-1566665797739-1674de7a421a?q=80&w=2070&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/9_vym2pc.jpg',
|
||||||
'https://images.unsplash.com/photo-1590490360182-c33d57733427?q=80&w=2070&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/8_kjih1z.jpg',
|
||||||
],
|
],
|
||||||
rotate: -12,
|
rotate: 15,
|
||||||
top: '15%',
|
top: '5%',
|
||||||
left: '22%',
|
left: '22%',
|
||||||
size: 'w-48 h-64 md:w-64 md:h-80',
|
size: 'w-48 h-64 md:w-64 md:h-80',
|
||||||
delay: 0.2
|
delay: 0.2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
srcs: [
|
srcs: [
|
||||||
'https://images.unsplash.com/photo-1544124499-58912cbddaad?q=80&w=2127&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/7_yuouc0.jpg',
|
||||||
'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?q=80&w=2127&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/4_eeyoge.jpg',
|
||||||
'https://images.unsplash.com/photo-1571896349842-33c89424de2d?q=80&w=2127&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/3_tolqzo.jpg',
|
||||||
],
|
],
|
||||||
rotate: 10,
|
rotate: -15,
|
||||||
top: '10%',
|
top: '8%',
|
||||||
left: '58%',
|
left: '58%',
|
||||||
size: 'w-52 h-64 md:w-72 md:h-80',
|
size: 'w-52 h-64 md:w-72 md:h-80',
|
||||||
delay: 0.4
|
delay: 0.4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
srcs: [
|
srcs: [
|
||||||
'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?q=80&w=2073&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/2_dfrmwi.jpg',
|
||||||
'https://images.unsplash.com/photo-1519046904884-53103b34b206?q=80&w=2073&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/5_mmcnjw.jpg',
|
||||||
'https://images.unsplash.com/photo-1506929199020-feee17651703?q=80&w=2073&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/6_x44c4w.jpg',
|
||||||
],
|
],
|
||||||
rotate: -8,
|
rotate: -8,
|
||||||
top: '65%',
|
top: '60%',
|
||||||
left: '18%',
|
left: '18%',
|
||||||
size: 'w-48 h-60 md:w-64 md:h-72',
|
size: 'w-48 h-60 md:w-64 md:h-72',
|
||||||
delay: 0.6
|
delay: 0.6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
srcs: [
|
srcs: [
|
||||||
'https://images.unsplash.com/photo-1536935338218-422119932906?q=80&w=1964&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/4_eeyoge.jpg',
|
||||||
'https://images.unsplash.com/photo-1618773928121-c32242e63f39?q=80&w=1964&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/5_mmcnjw.jpg',
|
||||||
'https://images.unsplash.com/photo-1560185007-cde436f6a4d0?q=80&w=1964&auto=format&fit=crop',
|
'https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/9_vym2pc.jpg',
|
||||||
],
|
],
|
||||||
rotate: 15,
|
rotate: -8,
|
||||||
top: '72%',
|
top: '62%',
|
||||||
left: '62%',
|
left: '62%',
|
||||||
size: 'w-52 h-64 md:w-72 md:h-88',
|
size: 'w-52 h-64 md:w-72 md:h-88',
|
||||||
delay: 0.8
|
delay: 0.8
|
||||||
@@ -112,7 +112,7 @@ function FloatingSlot({ slot, idx }: { slot: typeof heroSlots[0], idx: number })
|
|||||||
|
|
||||||
export default function Hero({ lang, dict }: { lang: string, dict: any }) {
|
export default function Hero({ lang, dict }: { lang: string, dict: any }) {
|
||||||
return (
|
return (
|
||||||
<section className="sticky top-0 z-[20] h-screen w-full bg-[#FAF7F0] flex items-center justify-center overflow-hidden">
|
<section className="sticky top-30 z-[20] h-screen w-full bg-[#FAF7F0] flex items-center justify-center overflow-hidden">
|
||||||
{/* BACKGROUND TEXT */}
|
{/* BACKGROUND TEXT */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.95 }}
|
initial={{ opacity: 0, scale: 0.95 }}
|
||||||
@@ -120,7 +120,7 @@ export default function Hero({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
transition={{ duration: 1.5, ease: [0.33, 1, 0.68, 1] }}
|
transition={{ duration: 1.5, ease: [0.33, 1, 0.68, 1] }}
|
||||||
className="relative z-10 w-full text-center px-4"
|
className="relative z-10 w-full text-center px-4"
|
||||||
>
|
>
|
||||||
<h1 className="text-[14vw] leading-[0.8] font-serif tracking-[-0.04em] text-[#1A1A1A] uppercase select-none drop-shadow-sm">
|
<h1 className="text-[18vw] leading-[0.8] font-serif tracking-[-0.04em] text-[#1F1C19] uppercase select-none drop-shadow-sm">
|
||||||
{dict.hero.title}
|
{dict.hero.title}
|
||||||
</h1>
|
</h1>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -131,7 +131,7 @@ export default function Hero({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{/* BOTTOM CONTENT */}
|
{/* BOTTOM CONTENT */}
|
||||||
<div className="absolute bottom-12 right-12 z-30 max-w-sm text-right flex flex-col items-end space-y-6">
|
<div className="absolute bottom-36 right-12 z-30 max-w-sm text-right flex flex-col items-end space-y-6">
|
||||||
<motion.p
|
<motion.p
|
||||||
initial={{ opacity: 0, x: 20 }}
|
initial={{ opacity: 0, x: 20 }}
|
||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function Navbar({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
const navLinks = [
|
const navLinks = [
|
||||||
{ name: dict.nav.about, href: `/${lang}/about` },
|
{ name: dict.nav.about, href: `/${lang}/about` },
|
||||||
{ name: dict.nav.suites, href: `/${lang}/suites`, hasDropdown: true },
|
{ name: dict.nav.suites, href: `/${lang}/suites`, hasDropdown: true },
|
||||||
{ name: dict.nav.news, href: `/${lang}/news` },
|
{ name: dict.nav.news, href: `/${lang}/blog` },
|
||||||
]
|
]
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -55,13 +55,13 @@ export default function Navbar({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
initial={{ y: -100 }}
|
initial={{ y: -100 }}
|
||||||
animate={{ y: isVisible ? 0 : -100 }}
|
animate={{ y: isVisible ? 0 : -100 }}
|
||||||
transition={{ duration: 0.6, ease: [0.33, 1, 0.68, 1] }}
|
transition={{ duration: 0.6, ease: [0.33, 1, 0.68, 1] }}
|
||||||
className={`fixed top-0 left-0 right-0 z-[100] transition-all duration-500 flex justify-center py-4 px-6 md:px-12`}
|
className={`fixed top-0 left-0 right-0 z-[100] transition-all duration-500 flex justify-center px-6 md:px-12`}
|
||||||
>
|
>
|
||||||
<div className={`w-full flex items-center justify-between bg-white rounded-[2px] transition-all duration-500 border border-[#1A1A1A]/5 ${isScrolled ? 'py-3 px-10' : 'py-5 px-12'}`}>
|
<div className={`w-full mx-auto max-w-[1700px] flex items-center justify-between bg-white rounded-[2px] transition-all duration-500 border border-[#1F1C19]/5 ${isScrolled ? 'py-3 px-10' : 'py-5 px-12'}`}>
|
||||||
{/* LOGO */}
|
{/* LOGO */}
|
||||||
<Link href={`/${lang}`} className="flex items-center group">
|
<Link href={`/${lang}`} className="flex items-center group">
|
||||||
<span className="text-[24px] font-serif tracking-[0.25em] text-[#1A1A1A] uppercase">
|
<span className="text-[36px] font-serif font-bold text-[#1F1C19] ">
|
||||||
AYRIS APART
|
AyrisApart
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ export default function Navbar({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
<Link
|
<Link
|
||||||
key={link.name}
|
key={link.name}
|
||||||
href={link.href}
|
href={link.href}
|
||||||
className="group relative text-[11px] font-bold tracking-[0.35em] uppercase text-[#1A1A1A]/70 hover:text-[#1A1A1A] transition-colors overflow-hidden"
|
className="group relative text-[18px] font-sans uppercase text-[#1F1C19] hover:text-[#1A1A1A] transition-colors overflow-hidden"
|
||||||
>
|
>
|
||||||
<span className="block">{link.name}</span>
|
<span className="block">{link.name}</span>
|
||||||
<span className="absolute bottom-0 left-0 w-full h-[1.5px] bg-[#C88C4B] transform scale-x-0 group-hover:scale-x-100 transition-transform duration-500 origin-left" />
|
<span className="absolute bottom-0 left-0 w-full h-[1.5px] bg-[#C88C4B] transform scale-x-0 group-hover:scale-x-100 transition-transform duration-500 origin-left" />
|
||||||
@@ -101,7 +101,7 @@ export default function Navbar({ lang, dict }: { lang: string, dict: any }) {
|
|||||||
href={`/${lang}/contact`}
|
href={`/${lang}/contact`}
|
||||||
className="hidden lg:flex items-center space-x-3 group"
|
className="hidden lg:flex items-center space-x-3 group"
|
||||||
>
|
>
|
||||||
<span className="text-[11px] font-bold tracking-[0.35em] uppercase text-[#1A1A1A]">{dict.nav.contact}</span>
|
<span className="text-[18px] font-bold uppercase text-[#1F1C19]">{dict.nav.contact}</span>
|
||||||
<div className="w-10 h-10 rounded-full border border-[#1A1A1A]/10 flex items-center justify-center group-hover:bg-[#1A1A1A] group-hover:border-[#1A1A1A] transition-all duration-500">
|
<div className="w-10 h-10 rounded-full border border-[#1A1A1A]/10 flex items-center justify-center group-hover:bg-[#1A1A1A] group-hover:border-[#1A1A1A] transition-all duration-500">
|
||||||
<ArrowRight size={16} className="text-[#1A1A1A] group-hover:text-white transition-colors" />
|
<ArrowRight size={16} className="text-[#1A1A1A] group-hover:text-white transition-colors" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
import { motion } from 'framer-motion'
|
import { motion } from 'framer-motion'
|
||||||
|
|
||||||
export default function QuoteSection() {
|
export default function QuoteSection({ dict }: { dict: any }) {
|
||||||
return (
|
return (
|
||||||
<section className="relative z-60 bg-[#FAF7F0] py-40 flex items-center justify-center text-center px-6">
|
<section className="relative z-60 bg-[#FAF7F0] pt-20 flex items-center justify-center text-center px-6 ">
|
||||||
<motion.h2
|
<motion.h2
|
||||||
initial={{ opacity: 0, y: 40 }}
|
initial={{ opacity: 0, y: 40 }}
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
transition={{ duration: 1.5, ease: [0.33, 1, 0.68, 1] }}
|
transition={{ duration: 1.5, ease: [0.33, 1, 0.68, 1] }}
|
||||||
className="text-4xl md:text-[80px] font-medium text-[#1A1A1A] leading-[1.1] max-w-5xl"
|
className="text-4xl md:text-[80px] font-medium text-[#1A1A1A] leading-[1.1] max-w-5xl w-[800px] mx-auto"
|
||||||
>
|
>
|
||||||
Luxury stays designed for ocean lovers
|
{dict.quote}
|
||||||
</motion.h2>
|
</motion.h2>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ export default function ShowcaseImage() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Slightly increased scales for a better balance
|
// Slightly increased scales for a better balance
|
||||||
const scale = useTransform(scrollYProgress, [0, 0.4], [0.8, 1.0])
|
const scale = useTransform(scrollYProgress, [0, 0.4], [0.1, 1.0])
|
||||||
const opacity = useTransform(scrollYProgress, [0, 0.2], [0, 1])
|
const opacity = useTransform(scrollYProgress, [0, 0.2], [0, 1])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section ref={containerRef} className="relative z-60 bg-[#FAF7F0] pb-32">
|
<section ref={containerRef} className="relative z-60 bg-[#FAF7F0] pb-32">
|
||||||
<div className="max-w-[1400px] mx-auto px-6 overflow-hidden">
|
<div className=" mx-auto px-6 overflow-hidden">
|
||||||
<motion.div
|
<motion.div
|
||||||
style={{
|
style={{
|
||||||
scale,
|
scale,
|
||||||
@@ -26,9 +26,10 @@ export default function ShowcaseImage() {
|
|||||||
className="relative aspect-[16/9] w-full overflow-hidden shadow-xl rounded-sm"
|
className="relative aspect-[16/9] w-full overflow-hidden shadow-xl rounded-sm"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src="https://images.unsplash.com/photo-1571896349842-33c89424de2d?q=80&w=2080&auto=format&fit=crop"
|
src="https://res.cloudinary.com/du7xohbct/image/upload/v1776642098/ayrisapart/hero/photo-1501696461415-6bd6660c6742_rkxjcu.avif"
|
||||||
alt="Luxury Cave Pool Experience"
|
alt="Luxury Cave Pool Experience"
|
||||||
fill
|
fill
|
||||||
|
sizes="(max-width: 768px) calc(100vw - 48px), calc(100vw - 48px)"
|
||||||
className="object-cover"
|
className="object-cover"
|
||||||
priority
|
priority
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ export default function SuitesHighlights({ lang, dict }: { lang: string, dict: a
|
|||||||
{ id: 'arke', number: '03', name: dict.suites.s3.name, desc: dict.suites.s3.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606654/ayrisapart/Daire%203/photo_1_2024-04-05_16-06-09.jpg' },
|
{ id: 'arke', number: '03', name: dict.suites.s3.name, desc: dict.suites.s3.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606654/ayrisapart/Daire%203/photo_1_2024-04-05_16-06-09.jpg' },
|
||||||
{ id: 'harpy', number: '04', name: dict.suites.s4.name, desc: dict.suites.s4.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606661/ayrisapart/Daire%204/photo_1_2024-04-05_16-07-01.jpg' },
|
{ id: 'harpy', number: '04', name: dict.suites.s4.name, desc: dict.suites.s4.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606661/ayrisapart/Daire%204/photo_1_2024-04-05_16-07-01.jpg' },
|
||||||
{ id: 'hydaspes', number: '05', name: dict.suites.s5.name, desc: dict.suites.s5.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606671/ayrisapart/Daire%205/photo_1_2024-05-04_15-32-44.jpg' },
|
{ id: 'hydaspes', number: '05', name: dict.suites.s5.name, desc: dict.suites.s5.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606671/ayrisapart/Daire%205/photo_1_2024-05-04_15-32-44.jpg' },
|
||||||
{ id: 'zephyrus', number: '06', name: dict.suites.s6.name, desc: dict.suites.s6.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606681/ayrisapart/Daire%206/photo_1_2024-05-04_15-32-44.jpg' },
|
{ id: 'zephyrus', number: '06', name: dict.suites.s6.name, desc: dict.suites.s6.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606681/ayrisapart/Daire%206/photo_1_2024-05-04_15-33-08.jpg' },
|
||||||
{ id: 'pothos', number: '07', name: dict.suites.s7.name, desc: dict.suites.s7.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606689/ayrisapart/Daire%207/photo_1_2024-05-04_15-33-34.jpg' },
|
{ id: 'pothos', number: '07', name: dict.suites.s7.name, desc: dict.suites.s7.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606689/ayrisapart/Daire%207/photo_8_2024-05-04_15-33-34.jpg' },
|
||||||
{ id: 'thaumas', number: '08', name: dict.suites.s8.name, desc: dict.suites.s8.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606696/ayrisapart/Daire%208/photo_1_2024-05-04_15-33-34.jpg' },
|
{ id: 'thaumas', number: '08', name: dict.suites.s8.name, desc: dict.suites.s8.desc, image: 'https://res.cloudinary.com/du7xohbct/image/upload/v1776606696/ayrisapart/Daire%208/photo_9_2024-05-04_15-33-34.jpg' },
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -100,6 +100,7 @@ function SuiteCard({ suite, index, lang, dict }: { suite: Suite, index: number,
|
|||||||
src={suite.image}
|
src={suite.image}
|
||||||
alt={suite.name}
|
alt={suite.name}
|
||||||
fill
|
fill
|
||||||
|
sizes="(max-width: 768px) 100vw, 50vw"
|
||||||
className="object-cover"
|
className="object-cover"
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Link from 'next/link'
|
|||||||
|
|
||||||
export default function Welcome({ lang, dict }: { lang: string, dict: any }) {
|
export default function Welcome({ lang, dict }: { lang: string, dict: any }) {
|
||||||
return (
|
return (
|
||||||
<section className="relative z-[70] bg-[#FAF7F0] mt-24 md:mt-32 rounded-t-[40px] md:rounded-t-[100px] py-32 md:py-48 px-6 md:px-12 flex flex-col items-center text-center shadow-[0_-40px_100px_rgba(0,0,0,0.1)] overflow-hidden">
|
<section className="relative z-[70] bg-[#FAF7F0] mt-24 md:mt-32 rounded-t-[40px] md:rounded-t-[100px] py-16 md:py-8 px-6 md:px-12 flex flex-col items-center text-center shadow-[0_-40px_100px_rgba(0,0,0,0.1)] overflow-hidden">
|
||||||
{/* Lotus/Floral Icon */}
|
{/* Lotus/Floral Icon */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 30 }}
|
initial={{ opacity: 0, y: 30 }}
|
||||||
|
|||||||
+137
-29
@@ -2,12 +2,12 @@
|
|||||||
"nav": {
|
"nav": {
|
||||||
"about": "About",
|
"about": "About",
|
||||||
"suites": "Suites",
|
"suites": "Suites",
|
||||||
"news": "News",
|
"news": "Blog",
|
||||||
"contact": "Contact",
|
"contact": "Contact",
|
||||||
"home": "Home"
|
"home": "Home"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"title": "Ayris Apart",
|
"title": "AyrisApart",
|
||||||
"desc": "In the heart of Muğla Milas Ören, discover refined suites and unforgettable comfort. Your luxury vacation awaits.",
|
"desc": "In the heart of Muğla Milas Ören, discover refined suites and unforgettable comfort. Your luxury vacation awaits.",
|
||||||
"explore": "Explore Suites"
|
"explore": "Explore Suites"
|
||||||
},
|
},
|
||||||
@@ -21,14 +21,18 @@
|
|||||||
"others": "Others",
|
"others": "Others",
|
||||||
"utility": "Utility",
|
"utility": "Utility",
|
||||||
"socials": "Socials",
|
"socials": "Socials",
|
||||||
"desc": "Book today and discover seaside luxury, breathtaking views, and unforgettable moments on the shores of Oren."
|
"desc": "Book today and discover seaside luxury, breathtaking views, and unforgettable moments on the shores of Oren.",
|
||||||
|
"services": "Services",
|
||||||
|
"activities": "Activities",
|
||||||
|
"gallery": "Gallery",
|
||||||
|
"license": "License"
|
||||||
},
|
},
|
||||||
"contact": {
|
"contact": {
|
||||||
"title": "Contact Us",
|
"title": "Contact Us",
|
||||||
"subtitle": "Let's Stay Connected",
|
"subtitle": "Let's Stay Connected",
|
||||||
"visit": {
|
"visit": {
|
||||||
"t": "Visit Us",
|
"t": "Visit Us",
|
||||||
"d": "Oren District, Orta Iskele Street No:51 Ayris Apart 48220 Milas/Mugla"
|
"d": "Oren District, Orta Iskele Street No:71 Ayris Apart 48220 Milas/Mugla"
|
||||||
},
|
},
|
||||||
"call": {
|
"call": {
|
||||||
"t": "Call Us",
|
"t": "Call Us",
|
||||||
@@ -69,10 +73,22 @@
|
|||||||
},
|
},
|
||||||
"why": {
|
"why": {
|
||||||
"title": "Why Ayris Apart?",
|
"title": "Why Ayris Apart?",
|
||||||
"1": { "t": "Premium Location", "d": "Easy access to the sea and everywhere in the quietest part of Oren" },
|
"1": {
|
||||||
"2": { "t": "Modern Design", "d": "Comfortable and stylish rooms with contemporary architecture" },
|
"t": "Premium Location",
|
||||||
"3": { "t": "24/7 Service", "d": "Our experienced team is with you at every moment" },
|
"d": "Easy access to the sea and everywhere in the quietest part of Oren"
|
||||||
"4": { "t": "Secure Payment", "d": "SSL certified secure reservation system" }
|
},
|
||||||
|
"2": {
|
||||||
|
"t": "Modern Design",
|
||||||
|
"d": "Comfortable and stylish rooms with contemporary architecture"
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"t": "24/7 Service",
|
||||||
|
"d": "Our experienced team is with you at every moment"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"t": "Secure Payment",
|
||||||
|
"d": "SSL certified secure reservation system"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"vision": {
|
"vision": {
|
||||||
"title": "Our Vision",
|
"title": "Our Vision",
|
||||||
@@ -80,30 +96,102 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"suites": {
|
"suites": {
|
||||||
"s1": { "name": "Iris", "desc": "Our most special suite carrying the colors of the rainbow, shining with uninterrupted ocean views." },
|
"s1": {
|
||||||
"s2": { "name": "Electra", "desc": "A bright living space adorned with amber tones, where peace and elegance meet." },
|
"name": "Iris",
|
||||||
"s3": { "name": "Arke", "desc": "A sanctuary that rests your soul with its design giving a sense of lightness and freedom." },
|
"desc": "Our most special suite carrying the colors of the rainbow, shining with uninterrupted ocean views."
|
||||||
"s4": { "name": "Harpy", "desc": "The suite that combines the power of the storm and the energy of the sea in a single panoramic view." },
|
},
|
||||||
"s5": { "name": "Hydaspes", "desc": "A room designed for those seeking serenity, reflecting the fluidity and purity of water." },
|
"s2": {
|
||||||
"s6": { "name": "Zephyrus", "desc": "Our breeze suite that brings the coolness of the west wind and the freshness of the garden to your balcony." },
|
"name": "Electra",
|
||||||
"s7": { "name": "Pothos", "desc": "Accommodation where you will feel luxury in every detail, where desire and passion meet aesthetics." },
|
"desc": "A bright living space adorned with amber tones, where peace and elegance meet."
|
||||||
"s8": { "name": "Thaumas", "desc": "The suite with the widest-angle coastal view of Oren, where you will witness the wonders of the sea." },
|
},
|
||||||
|
"s3": {
|
||||||
|
"name": "Arke",
|
||||||
|
"desc": "A sanctuary that rests your soul with its design giving a sense of lightness and freedom."
|
||||||
|
},
|
||||||
|
"s4": {
|
||||||
|
"name": "Harpy",
|
||||||
|
"desc": "The suite that combines the power of the storm and the energy of the sea in a single panoramic view."
|
||||||
|
},
|
||||||
|
"s5": {
|
||||||
|
"name": "Hydaspes",
|
||||||
|
"desc": "A room designed for those seeking serenity, reflecting the fluidity and purity of water."
|
||||||
|
},
|
||||||
|
"s6": {
|
||||||
|
"name": "Zephyrus",
|
||||||
|
"desc": "Our breeze suite that brings the coolness of the west wind and the freshness of the garden to your balcony."
|
||||||
|
},
|
||||||
|
"s7": {
|
||||||
|
"name": "Pothos",
|
||||||
|
"desc": "Accommodation where you will feel luxury in every detail, where desire and passion meet aesthetics."
|
||||||
|
},
|
||||||
|
"s8": {
|
||||||
|
"name": "Thaumas",
|
||||||
|
"desc": "The suite with the widest-angle coastal view of Oren, where you will witness the wonders of the sea."
|
||||||
|
},
|
||||||
"btn": {
|
"btn": {
|
||||||
"more": "Learn More"
|
"more": "Learn More"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"suites_page": {
|
"suites_page": {
|
||||||
"title": "Our Suites",
|
"title": "Our Suites",
|
||||||
"subtitle": "Enjoy characterful design, peaceful ocean views, and a mythological atmosphere. Each of our rooms tells its own unique story.",
|
"subtitle": "Enjoy characterful design, peaceful ocean views, and a mythological atmosphere. Each of our rooms tells its own unique story.",
|
||||||
"list": {
|
"list": {
|
||||||
"s1": { "name": "Iris", "desc": "Named after the rainbow messenger, this suite comes alive every morning with colors rising from the sea.", "bed": "1 King-size bed", "guests": "2 Guests" },
|
"s1": {
|
||||||
"s2": { "name": "Electra", "desc": "A comfort zone that embraces golden sunsets, enchanting with its brilliance.", "bed": "1 King-size bed", "guests": "2 Guests" },
|
"name": "Iris",
|
||||||
"s3": { "name": "Arke", "desc": "A suite that invites the light breeze of the Aegean in, standing out with its minimalist and spacious design.", "bed": "1 Queen-size bed", "guests": "2 Guests" },
|
"desc": "Named after the rainbow messenger, this suite comes alive every morning with colors rising from the sea.",
|
||||||
"s4": { "name": "Harpy", "desc": "A room with a dynamic atmosphere where you can listen to the song of sea waves and the wind.", "bed": "1 King-size bed", "guests": "2 Guests" },
|
"bed": "1 King-size bed",
|
||||||
"s5": { "name": "Hydaspes", "desc": "Peaceful interiors adorned with the sounds of water, reflecting the stillness of ancient rivers.", "bed": "1 King-size bed", "guests": "2 Guests" },
|
"guests": "2 Guests",
|
||||||
"s6": { "name": "Zephyrus", "desc": "An experience intertwined with nature, offering the scent of garden flowers and the coolness of the west wind.", "bed": "1 King-size bed", "guests": "2 Guests" },
|
"price": "$110"
|
||||||
"s7": { "name": "Pothos", "desc": "A special living space designed with an aesthetic longing, bringing romance and elegance together.", "bed": "1 King-size bed", "guests": "2 Guests" },
|
},
|
||||||
"s8": { "name": "Thaumas", "desc": "Our most comfortable and spacious suite, laying the wonders of the sea at your feet.", "bed": "2 King-size beds", "guests": "4 Guests" }
|
"s2": {
|
||||||
|
"name": "Electra",
|
||||||
|
"desc": "A comfort zone that embraces golden sunsets, enchanting with its brilliance.",
|
||||||
|
"bed": "1 King-size bed",
|
||||||
|
"guests": "2 Guests",
|
||||||
|
"price": "$110"
|
||||||
|
},
|
||||||
|
"s3": {
|
||||||
|
"name": "Arke",
|
||||||
|
"desc": "A suite that invites the light breeze of the Aegean in, standing out with its minimalist and spacious design.",
|
||||||
|
"bed": "1 Queen-size bed",
|
||||||
|
"guests": "2 Guests",
|
||||||
|
"price": "$110"
|
||||||
|
},
|
||||||
|
"s4": {
|
||||||
|
"name": "Harpy",
|
||||||
|
"desc": "A room with a dynamic atmosphere where you can listen to the song of sea waves and the wind.",
|
||||||
|
"bed": "1 King-size bed",
|
||||||
|
"guests": "2 Guests",
|
||||||
|
"price": "$110"
|
||||||
|
},
|
||||||
|
"s5": {
|
||||||
|
"name": "Hydaspes",
|
||||||
|
"desc": "Peaceful interiors adorned with the sounds of water, reflecting the stillness of ancient rivers.",
|
||||||
|
"bed": "1 King-size bed",
|
||||||
|
"guests": "2 Guests",
|
||||||
|
"price": "$110"
|
||||||
|
},
|
||||||
|
"s6": {
|
||||||
|
"name": "Zephyrus",
|
||||||
|
"desc": "An experience intertwined with nature, offering the scent of garden flowers and the coolness of the west wind.",
|
||||||
|
"bed": "1 King-size bed",
|
||||||
|
"guests": "2 Guests",
|
||||||
|
"price": "$110"
|
||||||
|
},
|
||||||
|
"s7": {
|
||||||
|
"name": "Pothos",
|
||||||
|
"desc": "A special living space designed with an aesthetic longing, bringing romance and elegance together.",
|
||||||
|
"bed": "1 King-size bed",
|
||||||
|
"guests": "2 Guests",
|
||||||
|
"price": "$110"
|
||||||
|
},
|
||||||
|
"s8": {
|
||||||
|
"name": "Thaumas",
|
||||||
|
"desc": "Our most comfortable and spacious suite, laying the wonders of the sea at your feet.",
|
||||||
|
"bed": "2 King-size beds",
|
||||||
|
"guests": "4 Guests",
|
||||||
|
"price": "$110"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"details": "Explore Details"
|
"details": "Explore Details"
|
||||||
},
|
},
|
||||||
@@ -112,11 +200,31 @@
|
|||||||
"excerpt": "Discover stories filled with coastal charm, travel inspiration, and insider tips.",
|
"excerpt": "Discover stories filled with coastal charm, travel inspiration, and insider tips.",
|
||||||
"read": "Read More",
|
"read": "Read More",
|
||||||
"list": {
|
"list": {
|
||||||
"n1": { "title": "Hidden Gems of Oren", "excerpt": "Discover secret coves known only to locals.", "author": "Ayris Team" },
|
"n1": {
|
||||||
"n2": { "title": "Summer Cocktails", "excerpt": "Meet our new season menu.", "author": "Chef Rez" },
|
"title": "Hidden Gems of Oren",
|
||||||
"n3": { "title": "Luxury Interior Trends", "excerpt": "The design story of Ayris Apart.", "author": "Design Team" }
|
"excerpt": "Discover secret coves known only to locals.",
|
||||||
|
"author": "Ayris Team"
|
||||||
|
},
|
||||||
|
"n2": {
|
||||||
|
"title": "Summer Cocktails",
|
||||||
|
"excerpt": "Meet our new season menu.",
|
||||||
|
"author": "Chef Rez"
|
||||||
|
},
|
||||||
|
"n3": {
|
||||||
|
"title": "Luxury Interior Trends",
|
||||||
|
"excerpt": "The design story of Ayris Apart.",
|
||||||
|
"author": "Design Team"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"quote": "Luxury stays designed for ocean lovers",
|
||||||
|
"experiences": {
|
||||||
|
"title": "Discover experiences beyond the shore",
|
||||||
|
"e1": { "title": "Akbük Koyu", "desc": "Swim towards the horizon in our stunning heated infinity pool, overlooking the turquoise expanse of the Aegean Sea." },
|
||||||
|
"e2": { "title": "Ören Sahili", "desc": "Discover vibrant marine life, swim through crystal-clear waters, and experience the wonder of ocean." },
|
||||||
|
"e3": { "title": "Alatepe Paraşüt", "desc": "Balance your soul and body while gliding over calm morning waves on our premium paddle boards." },
|
||||||
|
"e4": { "title": "Çökertme Koyu", "desc": "Join our local experts for an authentic Mediterranean fishing experience at sunrise." }
|
||||||
|
},
|
||||||
"amenities": {
|
"amenities": {
|
||||||
"title": "Amenities",
|
"title": "Amenities",
|
||||||
"cctv": "CCTV Security",
|
"cctv": "CCTV Security",
|
||||||
@@ -129,4 +237,4 @@
|
|||||||
"fire_ext": "Fire Extinguisher",
|
"fire_ext": "Fire Extinguisher",
|
||||||
"wifi": "Free Wi-Fi"
|
"wifi": "Free Wi-Fi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+136
-28
@@ -2,12 +2,12 @@
|
|||||||
"nav": {
|
"nav": {
|
||||||
"about": "Hakkımızda",
|
"about": "Hakkımızda",
|
||||||
"suites": "Odalar",
|
"suites": "Odalar",
|
||||||
"news": "Haberler",
|
"news": "Blog",
|
||||||
"contact": "İletişim",
|
"contact": "İletişim",
|
||||||
"home": "Anasayfa"
|
"home": "Anasayfa"
|
||||||
},
|
},
|
||||||
"hero": {
|
"hero": {
|
||||||
"title": "Ayris Apart",
|
"title": "AyrisApart",
|
||||||
"desc": "Muğla Milas Ören'in kalbinde, rafine suitler ve unutulmaz bir konforu keşfedin. Lüks tatiliniz sizi bekliyor.",
|
"desc": "Muğla Milas Ören'in kalbinde, rafine suitler ve unutulmaz bir konforu keşfedin. Lüks tatiliniz sizi bekliyor.",
|
||||||
"explore": "Odaları Keşfedin"
|
"explore": "Odaları Keşfedin"
|
||||||
},
|
},
|
||||||
@@ -21,14 +21,18 @@
|
|||||||
"others": "Diğer",
|
"others": "Diğer",
|
||||||
"utility": "Yardımcı",
|
"utility": "Yardımcı",
|
||||||
"socials": "Sosyal Medya",
|
"socials": "Sosyal Medya",
|
||||||
"desc": "Bugün rezervasyon yapın ve Ören kıyılarında deniz kenarı lüksünü, nefes kesen manzaraları ve unutulmaz anları keşfedin."
|
"desc": "Bugün rezervasyon yapın ve Ören kıyılarında deniz kenarı lüksünü, nefes kesen manzaraları ve unutulmaz anları keşfedin.",
|
||||||
|
"services": "Hizmetler",
|
||||||
|
"activities": "Aktiviteler",
|
||||||
|
"gallery": "Galeri",
|
||||||
|
"license": "Lisans"
|
||||||
},
|
},
|
||||||
"contact": {
|
"contact": {
|
||||||
"title": "Bize Ulaşın",
|
"title": "Bize Ulaşın",
|
||||||
"subtitle": "Bağlantıda Kalalım",
|
"subtitle": "Bağlantıda Kalalım",
|
||||||
"visit": {
|
"visit": {
|
||||||
"t": "Bizi Ziyaret Edin",
|
"t": "Bizi Ziyaret Edin",
|
||||||
"d": "Ören Mahallesi, Orta İskele Caddesi No:51 Ayris Apart 48220 Milas/Muğla"
|
"d": "Ören Mahallesi, Orta İskele Caddesi No:71 Ayris Apart 48220 Milas/Muğla"
|
||||||
},
|
},
|
||||||
"call": {
|
"call": {
|
||||||
"t": "Bizi Arayın",
|
"t": "Bizi Arayın",
|
||||||
@@ -69,10 +73,22 @@
|
|||||||
},
|
},
|
||||||
"why": {
|
"why": {
|
||||||
"title": "Neden Ayris Apart?",
|
"title": "Neden Ayris Apart?",
|
||||||
"1": { "t": "Premium Konum", "d": "Ören'in en sakin bölgesinde, denize ve her yere kolay ulaşım imkanı" },
|
"1": {
|
||||||
"2": { "t": "Modern Tasarım", "d": "Çağdaş mimariye sahip, konforlu ve şık odalar" },
|
"t": "Premium Konum",
|
||||||
"3": { "t": "24/7 Hizmet", "d": "Her an yanınızda olan deneyimli ekibimiz" },
|
"d": "Ören'in en sakin bölgesinde, denize ve her yere kolay ulaşım imkanı"
|
||||||
"4": { "t": "Güvenli Ödeme", "d": "SSL sertifikalı güvenli rezervasyon sistemi" }
|
},
|
||||||
|
"2": {
|
||||||
|
"t": "Modern Tasarım",
|
||||||
|
"d": "Çağdaş mimariye sahip, konforlu ve şık odalar"
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"t": "24/7 Hizmet",
|
||||||
|
"d": "Her an yanınızda olan deneyimli ekibimiz"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"t": "Güvenli Ödeme",
|
||||||
|
"d": "SSL sertifikalı güvenli rezervasyon sistemi"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"vision": {
|
"vision": {
|
||||||
"title": "Vizyonumuz",
|
"title": "Vizyonumuz",
|
||||||
@@ -80,14 +96,38 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"suites": {
|
"suites": {
|
||||||
"s1": { "name": "Iris", "desc": "Gökkuşağının renklerini taşıyan, kesintisiz deniz manzarasıyla parlayan en özel suitimiz." },
|
"s1": {
|
||||||
"s2": { "name": "Electra", "desc": "Kehribar tonlarıyla bezenmiş, huzur ve zarafetin buluştuğu aydınlık bir yaşam alanı." },
|
"name": "Iris",
|
||||||
"s3": { "name": "Arke", "desc": "Hafiflik ve özgürlük hissi veren tasarımıyla, ruhunuzu dinlendiren bir sığınak." },
|
"desc": "Gökkuşağının renklerini taşıyan, kesintisiz deniz manzarasıyla parlayan en özel suitimiz."
|
||||||
"s4": { "name": "Harpy", "desc": "Fırtınanın gücünü ve denizin enerjisini tek bir panoramik manzarada birleştiren suit." },
|
},
|
||||||
"s5": { "name": "Hydaspes", "desc": "Suyun akışkanlığını ve saflığını yansıtan, dinginlik arayanlar için tasarlanmış oda." },
|
"s2": {
|
||||||
"s6": { "name": "Zephyrus", "desc": "Batı rüzgarının serinliğini ve bahçenin ferahlığını balkonunuza taşıyan meltem suitimiz." },
|
"name": "Electra",
|
||||||
"s7": { "name": "Pothos", "desc": "Arzu ve tutkunun estetikle buluştuğu, her detayında lüksü hissedeceğiniz konaklama." },
|
"desc": "Kehribar tonlarıyla bezenmiş, huzur ve zarafetin buluştuğu aydınlık bir yaşam alanı."
|
||||||
"s8": { "name": "Thaumas", "desc": "Denizin mucizelerine tanıklık edeceğiniz, Ören'in en geniş açılı sahil manzarasına sahip suit." },
|
},
|
||||||
|
"s3": {
|
||||||
|
"name": "Arke",
|
||||||
|
"desc": "Hafiflik ve özgürlük hissi veren tasarımıyla, ruhunuzu dinlendiren bir sığınak."
|
||||||
|
},
|
||||||
|
"s4": {
|
||||||
|
"name": "Harpy",
|
||||||
|
"desc": "Fırtınanın gücünü ve denizin enerjisini tek bir panoramik manzarada birleştiren suit."
|
||||||
|
},
|
||||||
|
"s5": {
|
||||||
|
"name": "Hydaspes",
|
||||||
|
"desc": "Suyun akışkanlığını ve saflığını yansıtan, dinginlik arayanlar için tasarlanmış oda."
|
||||||
|
},
|
||||||
|
"s6": {
|
||||||
|
"name": "Zephyrus",
|
||||||
|
"desc": "Batı rüzgarının serinliğini ve bahçenin ferahlığını balkonunuza taşıyan meltem suitimiz."
|
||||||
|
},
|
||||||
|
"s7": {
|
||||||
|
"name": "Pothos",
|
||||||
|
"desc": "Arzu ve tutkunun estetikle buluştuğu, her detayında lüksü hissedeceğiniz konaklama."
|
||||||
|
},
|
||||||
|
"s8": {
|
||||||
|
"name": "Thaumas",
|
||||||
|
"desc": "Denizin mucizelerine tanıklık edeceğiniz, Ören'in en geniş açılı sahil manzarasına sahip suit."
|
||||||
|
},
|
||||||
"btn": {
|
"btn": {
|
||||||
"more": "Daha Fazla"
|
"more": "Daha Fazla"
|
||||||
}
|
}
|
||||||
@@ -96,14 +136,62 @@
|
|||||||
"title": "Odalarımız",
|
"title": "Odalarımız",
|
||||||
"subtitle": "Karakterli tasarımın, huzurlu okyanus manzaralarının ve mitolojik bir atmosferin tadını çıkarın. Her odamız kendine has bir hikaye anlatır.",
|
"subtitle": "Karakterli tasarımın, huzurlu okyanus manzaralarının ve mitolojik bir atmosferin tadını çıkarın. Her odamız kendine has bir hikaye anlatır.",
|
||||||
"list": {
|
"list": {
|
||||||
"s1": { "name": "Iris", "desc": "Gökkuşağı postacısının adını taşıyan bu suit, her sabah denizden doğan renklerle canlanır.", "bed": "1 King-size yatak", "guests": "2 Misafir" },
|
"s1": {
|
||||||
"s2": { "name": "Electra", "desc": "Altın sarısı gün batımlarını kucaklayan, parlaklığıyla büyüleyen bir konfor alanı.", "bed": "1 King-size yatak", "guests": "2 Misafir" },
|
"name": "Iris",
|
||||||
"s3": { "name": "Arke", "desc": "Ege'nin hafif meltemini içeri davet eden, minimalist ve ferah tasarımıyla öne çıkan suit.", "bed": "1 Queen-size yatak", "guests": "2 Misafir" },
|
"desc": "Gökkuşağı postacısının adını taşıyan bu suit, her sabah denizden doğan renklerle canlanır.",
|
||||||
"s4": { "name": "Harpy", "desc": "Deniz dalgalarının ve rüzgarın şarkısını dinleyebileceğiniz, dinamik bir atmosfere sahip oda.", "bed": "1 King-size yatak", "guests": "2 Misafir" },
|
"bed": "1 King-size yatak",
|
||||||
"s5": { "name": "Hydaspes", "desc": "Antik nehirlerin dinginliğini yansıtan, huzur dolu su sesleriyle bezenmiş iç mekanlar.", "bed": "1 King-size yatak", "guests": "2 Misafir" },
|
"guests": "2 Misafir",
|
||||||
"s6": { "name": "Zephyrus", "desc": "Bahçe çiçeklerinin kokusunu ve batı rüzgarının serinliğini sunan, doğayla iç içe bir deneyim.", "bed": "1 King-size yatak", "guests": "2 Misafir" },
|
"price": "5000 TL"
|
||||||
"s7": { "name": "Pothos", "desc": "Estetik bir özlemle tasarlanmış, romantizm ve şıklığı bir araya getiren özel yaşam alanı.", "bed": "1 King-size yatak", "guests": "2 Misafir" },
|
},
|
||||||
"s8": { "name": "Thaumas", "desc": "Denizin harikalarını ayaklarınızın altına seren, en üst düzey konforlu ve geniş suitimiz.", "bed": "2 King-size yatak", "guests": "4 Misafir" }
|
"s2": {
|
||||||
|
"name": "Electra",
|
||||||
|
"desc": "Altın sarısı gün batımlarını kucaklayan, parlaklığıyla büyüleyen bir konfor alanı.",
|
||||||
|
"bed": "1 King-size yatak",
|
||||||
|
"guests": "2 Misafir",
|
||||||
|
"price": "5000 TL"
|
||||||
|
},
|
||||||
|
"s3": {
|
||||||
|
"name": "Arke",
|
||||||
|
"desc": "Ege'nin hafif meltemini içeri davet eden, minimalist ve ferah tasarımıyla öne çıkan suit.",
|
||||||
|
"bed": "1 Queen-size yatak",
|
||||||
|
"guests": "2 Misafir",
|
||||||
|
"price": "5000 TL"
|
||||||
|
},
|
||||||
|
"s4": {
|
||||||
|
"name": "Harpy",
|
||||||
|
"desc": "Deniz dalgalarının ve rüzgarın şarkısını dinleyebileceğiniz, dinamik bir atmosfere sahip oda.",
|
||||||
|
"bed": "1 King-size yatak",
|
||||||
|
"guests": "2 Misafir",
|
||||||
|
"price": "5000 TL"
|
||||||
|
},
|
||||||
|
"s5": {
|
||||||
|
"name": "Hydaspes",
|
||||||
|
"desc": "Antik nehirlerin dinginliğini yansıtan, huzur dolu su sesleriyle bezenmiş iç mekanlar.",
|
||||||
|
"bed": "1 King-size yatak",
|
||||||
|
"guests": "2 Misafir",
|
||||||
|
"price": "5000 TL"
|
||||||
|
},
|
||||||
|
"s6": {
|
||||||
|
"name": "Zephyrus",
|
||||||
|
"desc": "Bahçe çiçeklerinin kokusunu ve batı rüzgarının serinliğini sunan, doğayla iç içe bir deneyim.",
|
||||||
|
"bed": "1 King-size yatak",
|
||||||
|
"guests": "2 Misafir",
|
||||||
|
"price": "5000 TL"
|
||||||
|
},
|
||||||
|
"s7": {
|
||||||
|
"name": "Pothos",
|
||||||
|
"desc": "Estetik bir özlemle tasarlanmış, romantizm ve şıklığı bir araya getiren özel yaşam alanı.",
|
||||||
|
"bed": "1 King-size yatak",
|
||||||
|
"guests": "2 Misafir",
|
||||||
|
"price": "5000 TL"
|
||||||
|
},
|
||||||
|
"s8": {
|
||||||
|
"name": "Thaumas",
|
||||||
|
"desc": "Denizin harikalarını ayaklarınızın altına seren, en üst düzey konforlu ve geniş suitimiz.",
|
||||||
|
"bed": "2 King-size yatak",
|
||||||
|
"guests": "4 Misafir",
|
||||||
|
"price": "5000 TL"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"details": "Detayları Keşfet"
|
"details": "Detayları Keşfet"
|
||||||
},
|
},
|
||||||
@@ -112,11 +200,31 @@
|
|||||||
"excerpt": "Sahil cazibesi, seyahat ilhamı ve içeriden ipuçları ile dolu hikayeleri keşfedin.",
|
"excerpt": "Sahil cazibesi, seyahat ilhamı ve içeriden ipuçları ile dolu hikayeleri keşfedin.",
|
||||||
"read": "Yazıyı Oku",
|
"read": "Yazıyı Oku",
|
||||||
"list": {
|
"list": {
|
||||||
"n1": { "title": "Ören'in Gizli Cevherleri", "excerpt": "Sadece yerellerin bildiği gizli koyları keşfedin.", "author": "Ayris Ekibi" },
|
"n1": {
|
||||||
"n2": { "title": "Yaz Kokteylleri", "excerpt": "Yeni sezon menümüzle tanışın.", "author": "Şef Rez" },
|
"title": "Ören'in Gizli Cevherleri",
|
||||||
"n3": { "title": "Lüks İç Mekan Trendleri", "excerpt": "Ayris Apart'ın tasarım hikayesi.", "author": "Tasarım Ekibi" }
|
"excerpt": "Sadece yerellerin bildiği gizli koyları keşfedin.",
|
||||||
|
"author": "Ayris Ekibi"
|
||||||
|
},
|
||||||
|
"n2": {
|
||||||
|
"title": "Yaz Kokteylleri",
|
||||||
|
"excerpt": "Yeni sezon menümüzle tanışın.",
|
||||||
|
"author": "Şef Rez"
|
||||||
|
},
|
||||||
|
"n3": {
|
||||||
|
"title": "Lüks İç Mekan Trendleri",
|
||||||
|
"excerpt": "Ayris Apart'ın tasarım hikayesi.",
|
||||||
|
"author": "Tasarım Ekibi"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"quote": "Okyanus severler için tasarlanmış lüks konaklamalar",
|
||||||
|
"experiences": {
|
||||||
|
"title": "Kıyının ötesinde deneyimler keşfedin",
|
||||||
|
"e1": { "title": "Akbük Koyu", "desc": "Ege Denizi'nin turkuaz genişliğine bakan sonsuzluk havuzumuzda ufka doğru yüzün." },
|
||||||
|
"e2": { "title": "Ören Sahili", "desc": "Canlı deniz yaşamını keşfedin, kristal berraklığında sularda yüzün ve okyanusun harikasını yaşayın." },
|
||||||
|
"e3": { "title": "Alatepe Paraşüt", "desc": "Premium kürekli tahtalarda sakin sabah dalgaları üzerinde süzülerek ruhunuzu ve bedeninizi dengeleyin." },
|
||||||
|
"e4": { "title": "Çökertme Koyu", "desc": "Gün doğumunda otantik bir Akdeniz balıkçılık deneyimi için yerel uzmanlarımıza katılın." }
|
||||||
|
},
|
||||||
"amenities": {
|
"amenities": {
|
||||||
"title": "Sunulan Olanaklar",
|
"title": "Sunulan Olanaklar",
|
||||||
"cctv": "Güvenlik Kamerası",
|
"cctv": "Güvenlik Kamerası",
|
||||||
@@ -129,4 +237,4 @@
|
|||||||
"fire_ext": "Yangın Tüpü",
|
"fire_ext": "Yangın Tüpü",
|
||||||
"wifi": "Ücretsiz Wi-Fi"
|
"wifi": "Ücretsiz Wi-Fi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg'
|
||||||
|
import pg from 'pg'
|
||||||
|
|
||||||
|
const globalForPrisma = globalThis as unknown as {
|
||||||
|
prisma: PrismaClient | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Create a pool or connection using the underlying driver
|
||||||
|
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL })
|
||||||
|
|
||||||
|
// 2. Wrap it in the Prisma adapter
|
||||||
|
const adapter = new PrismaPg(pool)
|
||||||
|
|
||||||
|
// 3. Pass the adapter to the PrismaClient constructor
|
||||||
|
export const prisma =
|
||||||
|
globalForPrisma.prisma ??
|
||||||
|
new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
|
||||||
|
})
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
|
output: 'standalone',
|
||||||
|
serverExternalPackages: ['@prisma/client', 'pg'],
|
||||||
|
experimental: {
|
||||||
|
serverActions: {
|
||||||
|
bodySizeLimit: '10mb',
|
||||||
|
},
|
||||||
|
},
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
|
|||||||
Generated
+1819
-15
File diff suppressed because it is too large
Load Diff
@@ -9,23 +9,32 @@
|
|||||||
"lint": "eslint"
|
"lint": "eslint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@prisma/adapter-pg": "^7.7.0",
|
||||||
|
"@prisma/client": "^7.7.0",
|
||||||
"cloudinary": "^2.9.0",
|
"cloudinary": "^2.9.0",
|
||||||
"dotenv": "^17.4.2",
|
"dotenv": "^17.4.2",
|
||||||
"framer-motion": "^12.38.0",
|
"framer-motion": "^12.38.0",
|
||||||
"lucide-react": "^1.8.0",
|
"lucide-react": "^1.8.0",
|
||||||
"next": "16.2.4",
|
"next": "16.2.4",
|
||||||
"next-cloudinary": "^6.17.5",
|
"next-cloudinary": "^6.17.5",
|
||||||
|
"pg": "^8.20.0",
|
||||||
"react": "19.2.4",
|
"react": "19.2.4",
|
||||||
"react-dom": "19.2.4"
|
"react-dom": "19.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
|
"@types/pg": "^8.20.0",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.2.4",
|
"eslint-config-next": "16.2.4",
|
||||||
|
"prisma": "^7.7.0",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
|
"tsx": "^4.21.0",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "tsx prisma/seed.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// This file was generated by Prisma, and assumes you have installed the following:
|
||||||
|
// npm install --save-dev prisma dotenv
|
||||||
|
import "dotenv/config";
|
||||||
|
import { defineConfig } from "prisma/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: "prisma/schema.prisma",
|
||||||
|
migrations: {
|
||||||
|
path: "prisma/migrations",
|
||||||
|
seed: "tsx prisma/seed.ts",
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
url: process.env["DATABASE_URL"],
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// This is your Prisma schema file,
|
||||||
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
}
|
||||||
|
|
||||||
|
model Post {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
slug String @unique
|
||||||
|
excerpt String
|
||||||
|
content String?
|
||||||
|
image String?
|
||||||
|
author String @default("Ayris Apart")
|
||||||
|
lang String @default("tr") // 'tr' or 'en'
|
||||||
|
published Boolean @default(false)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@index([slug, lang])
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case we want to store Room/Suite data in DB later, we can add it here.
|
||||||
|
model Suite {
|
||||||
|
id String @id
|
||||||
|
name String
|
||||||
|
description String
|
||||||
|
price String
|
||||||
|
image String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg'
|
||||||
|
import pg from 'pg'
|
||||||
|
import "dotenv/config";
|
||||||
|
|
||||||
|
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL })
|
||||||
|
const adapter = new PrismaPg(pool)
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log('Seeding blog posts...')
|
||||||
|
|
||||||
|
// Clear existing posts to avoid unique constraint issues on slug during re-seed
|
||||||
|
try {
|
||||||
|
await prisma.post.deleteMany({})
|
||||||
|
console.log('Cleaned existing posts.')
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Skipping deleteMany, table might not exist yet.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const posts = [
|
||||||
|
{
|
||||||
|
title: "Ören'in Gizli Cevherleri: Akbük ve Ötesi",
|
||||||
|
slug: "orenin-gizli-cevherleri",
|
||||||
|
excerpt: "Sadece yerellerin bildiği, turkuaz suları ve sakinliği ile büyüleyen o gizli koyları keşfedin.",
|
||||||
|
content: "Ören Mahallesi'nin kalbinde yer alan Ayris Apart'tan çıktığınızda, sizi sadece bir deniz değil, binlerce yıllık bir hikaye karşılar. Akbük Koyu'nun dinginliğinden Alatepe'nin yamaç paraşütü heyecanına kadar, bu rehberimizde Ören'in en özel noktalarını derledik...",
|
||||||
|
image: "https://res.cloudinary.com/du7xohbct/image/upload/v1776642502/ayrisapart/experiences/oren_d2pxcy.jpg",
|
||||||
|
lang: "tr",
|
||||||
|
published: true,
|
||||||
|
author: "Ayris Ekibi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Hidden Gems of Oren: Akbuk and Beyond",
|
||||||
|
slug: "hidden-gems-of-oren",
|
||||||
|
excerpt: "Discover the secret coves known only to locals, enchanting with their turquoise waters and serenity.",
|
||||||
|
content: "When you step out of Ayris Apart, located in the heart of Oren, you are greeted not just by a sea, but by a story of thousands of years. From the serenity of Akbuk Bay to the paragliding excitement of Alatepe, we have compiled the most special spots of Oren in this guide...",
|
||||||
|
image: "https://res.cloudinary.com/du7xohbct/image/upload/v1776642502/ayrisapart/experiences/oren_d2pxcy.jpg",
|
||||||
|
lang: "en",
|
||||||
|
published: true,
|
||||||
|
author: "Ayris Team"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Ayris Apart'ta Mimari ve Konfor",
|
||||||
|
slug: "mimari-ve-konfor",
|
||||||
|
excerpt: "Modern tasarımın mitolojik isimlerle buluştuğu suitlerimizin hikayesini keşfedin.",
|
||||||
|
content: "Ayris Apart sadece bir konaklama noktası değil, bir yaşam alanıdır. Her bir suitimizin ismi (Iris, Electra, Arke...) Yunan mitolojisinden esinlenerek seçildi. Bu yazımızda, odalarımızın dekorasyonunda kullandığımız malzemeleri ve tasarım felsefemizi anlatıyoruz...",
|
||||||
|
image: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/1_cxfvrw.jpg",
|
||||||
|
lang: "tr",
|
||||||
|
published: true,
|
||||||
|
author: "Tasarım Ekibi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Architecture and Comfort at Ayris Apart",
|
||||||
|
slug: "architecture-and-comfort",
|
||||||
|
excerpt: "Discover the story of our suites where modern design meets mythological names.",
|
||||||
|
content: "Ayris Apart is not just an accommodation point, it is a living space. The name of each of our suites (Iris, Electra, Arke...) was chosen inspired by Greek mythology. In this article, we describe the materials we use in the decoration of our rooms and our design philosophy...",
|
||||||
|
image: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/1_cxfvrw.jpg",
|
||||||
|
lang: "en",
|
||||||
|
published: true,
|
||||||
|
author: "Design Team"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const post of posts) {
|
||||||
|
await prisma.post.create({
|
||||||
|
data: post
|
||||||
|
})
|
||||||
|
console.log(`Created post: ${post.title}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Seed completed successfully!')
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
.finally(async () => {
|
||||||
|
await prisma.$disconnect()
|
||||||
|
await pool.end()
|
||||||
|
})
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Ayris Apart - Luxury Seaside Accommodation in Ören, Muğla
|
||||||
|
|
||||||
|
Ayris Apart offers refined suites and unforgettable comfort in the heart of Milas Ören, Muğla. Established in 2021, we combine modern design with traditional Turkish hospitality.
|
||||||
|
|
||||||
|
## Core Values
|
||||||
|
- **Premium Location:** Situated in the quietest part of Ören with easy access to the sea.
|
||||||
|
- **Modern Design:** Contemporary architecture with comfortable and stylish rooms.
|
||||||
|
- **24/7 Service:** Dedicated team available at all times.
|
||||||
|
- **Mythological Theme:** Each suite is named after mythological figures (Iris, Electra, Arke, Harpy, Hydaspes, Zephyrus, Pothos, Thaumas).
|
||||||
|
|
||||||
|
## Contact Information
|
||||||
|
- **Address:** Ören Mahallesi, Orta İskele Caddesi No:51 Ayris Apart 48220 Milas/Muğla, Turkey
|
||||||
|
- **Phone:** Available for 7/24 service.
|
||||||
|
- **Check-in:** 14:00 | **Check-out:** 11:00
|
||||||
|
|
||||||
|
## Suites Overview
|
||||||
|
- **Iris:** Uninterrupted sea view.
|
||||||
|
- **Electra:** Bright living space with amber tones.
|
||||||
|
- **Arke:** Minimalist and spacious design.
|
||||||
|
- **Harpy:** Dynamic atmosphere with panoramic views.
|
||||||
|
- **Hydaspes:** Tranquil interiors reflecting the purity of water.
|
||||||
|
- **Zephyrus:** Garden freshness and western winds.
|
||||||
|
- **Pothos:** Luxury, romance, and aesthetic elegance.
|
||||||
|
- **Thaumas:** Widest beach view in Ören.
|
||||||
|
|
||||||
|
## Amenities
|
||||||
|
- Free Wi-Fi, Kitchen, Air Conditioning, Free Parking, Security Cameras, Fire Alarms.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
- [Home](https://ayrisapart.com/)
|
||||||
|
- [Suites](https://ayrisapart.com/suites)
|
||||||
|
- [About Us](https://ayrisapart.com/about)
|
||||||
|
- [Contact](https://ayrisapart.com/contact)
|
||||||
|
- [Pricing](/pricing.md)
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# Pricing & Suites - Ayris Apart
|
||||||
|
|
||||||
|
Ayris Apart provides luxury suite accommodations in Ören, Muğla. Below are the details for each suite.
|
||||||
|
|
||||||
|
## General Pricing
|
||||||
|
- **Standard Nightly Rate:** 5,000 TL (may vary by season)
|
||||||
|
- **Currency:** Turkish Lira (TL)
|
||||||
|
|
||||||
|
## Suite Details
|
||||||
|
|
||||||
|
### Iris Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 2 Guests
|
||||||
|
- **Bedding:** 1 King-size bed
|
||||||
|
- **Highlights:** Uninterrupted sea view, named after the rainbow messenger.
|
||||||
|
|
||||||
|
### Electra Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 2 Guests
|
||||||
|
- **Bedding:** 1 King-size bed
|
||||||
|
- **Highlights:** Bright space, golden sunset views.
|
||||||
|
|
||||||
|
### Arke Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 2 Guests
|
||||||
|
- **Bedding:** 1 Queen-size bed
|
||||||
|
- **Highlights:** Minimalist design, Aegean breeze.
|
||||||
|
|
||||||
|
### Harpy Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 2 Guests
|
||||||
|
- **Bedding:** 1 King-size bed
|
||||||
|
- **Highlights:** Dynamic atmosphere, panoramic view.
|
||||||
|
|
||||||
|
### Hydaspes Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 2 Guests
|
||||||
|
- **Bedding:** 1 King-size bed
|
||||||
|
- **Highlights:** Tranquil interiors, water-inspired design.
|
||||||
|
|
||||||
|
### Zephyrus Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 2 Guests
|
||||||
|
- **Bedding:** 1 King-size bed
|
||||||
|
- **Highlights:** Garden view, western wind theme.
|
||||||
|
|
||||||
|
### Pothos Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 2 Guests
|
||||||
|
- **Bedding:** 1 King-size bed
|
||||||
|
- **Highlights:** Romantic and aesthetic luxury.
|
||||||
|
|
||||||
|
### Thaumas Suite
|
||||||
|
- **Price:** 5,000 TL
|
||||||
|
- **Capacity:** 4 Guests
|
||||||
|
- **Bedding:** 2 King-size beds
|
||||||
|
- **Highlights:** Widest beach view, spacious comfort.
|
||||||
|
|
||||||
|
## Policies
|
||||||
|
- **Check-in:** 14:00
|
||||||
|
- **Check-out:** 11:00
|
||||||
|
- **Cancellation:** Please contact us for details.
|
||||||
|
|
||||||
|
## Booking
|
||||||
|
For reservations, please contact us via WhatsApp or Phone through our [Contact Page](https://ayrisapart.com/contact).
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Allow AI crawlers to discover Ayris Apart content
|
||||||
|
User-agent: GPTBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: ChatGPT-User
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: PerplexityBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: ClaudeBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: anthropic-ai
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Google-Extended
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Bingbot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
Sitemap: https://ayrisapart.com/sitemap.xml
|
||||||
Reference in New Issue
Block a user