- 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>
125 lines
4.5 KiB
TypeScript
125 lines
4.5 KiB
TypeScript
'use client'
|
|
|
|
import { motion, useScroll, useTransform } from 'framer-motion'
|
|
import { useRef } from 'react'
|
|
import Link from 'next/link'
|
|
import Image from 'next/image'
|
|
|
|
const images = [
|
|
{
|
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/1_cxfvrw.jpg",
|
|
w: 305, h: 425,
|
|
tx: -550, ty: -350,
|
|
rotate: -2
|
|
},
|
|
{
|
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/7_yuouc0.jpg",
|
|
w: 325, h: 425,
|
|
tx: 550, ty: -350,
|
|
rotate: 1
|
|
},
|
|
{
|
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641695/ayrisapart/hero/2_dfrmwi.jpg",
|
|
w: 385, h: 485,
|
|
tx: -550, ty: 350,
|
|
rotate: -1
|
|
},
|
|
{
|
|
src: "https://res.cloudinary.com/du7xohbct/image/upload/v1776641696/ayrisapart/hero/8_kjih1z.jpg",
|
|
w: 425, h: 365,
|
|
tx: 550, ty: 350,
|
|
rotate: 2
|
|
},
|
|
]
|
|
|
|
export default function CallToAction({ lang, dict }: { lang: string, dict: any }) {
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
|
|
const { scrollYProgress } = useScroll({
|
|
target: containerRef,
|
|
offset: ["start start", "end end"]
|
|
})
|
|
|
|
// Title: Stays hit at 0 until scroll hits 30%, then reveals quickly.
|
|
const entranceOpacity = useTransform(scrollYProgress, [0.85, 0.95, 1], [0, 1, 1])
|
|
|
|
// Description / Button: Reveals even later, ensuring images are already scattering
|
|
const textOpacity = useTransform(scrollYProgress, [0.5, 0.7, 1], [0, 1, 1])
|
|
const textY = useTransform(scrollYProgress, [0.5, 0.7, 1], [50, 0, 0])
|
|
|
|
// Scatter range: Images start dispersing at 20% to clear the path for text
|
|
const scatterRange = [0.2, 0.95]
|
|
const scatterTLX = useTransform(scrollYProgress, scatterRange, [0, -580])
|
|
const scatterTLY = useTransform(scrollYProgress, scatterRange, [0, -380])
|
|
|
|
const scatterTRX = useTransform(scrollYProgress, scatterRange, [0, 580])
|
|
const scatterTRY = useTransform(scrollYProgress, scatterRange, [0, -380])
|
|
|
|
const scatterBLX = useTransform(scrollYProgress, scatterRange, [0, -580])
|
|
const scatterBLY = useTransform(scrollYProgress, scatterRange, [0, 380])
|
|
|
|
const scatterBRX = useTransform(scrollYProgress, scatterRange, [0, 580])
|
|
const scatterBRY = useTransform(scrollYProgress, scatterRange, [0, 380])
|
|
|
|
const scatterX = [scatterTLX, scatterTRX, scatterBLX, scatterBRX]
|
|
const scatterY = [scatterTLY, scatterTRY, scatterBLY, scatterBRY]
|
|
|
|
return (
|
|
<section ref={containerRef} className="relative h-[300vh] bg-white z-60">
|
|
<div className="sticky top-0 h-screen flex items-center justify-center overflow-hidden">
|
|
|
|
{/* SCATTERING POLAROIDS */}
|
|
{images.map((img, i) => (
|
|
<motion.div
|
|
key={i}
|
|
style={{
|
|
x: scatterX[i],
|
|
y: scatterY[i],
|
|
rotate: img.rotate
|
|
}}
|
|
className="absolute z-10"
|
|
>
|
|
<div className={`relative shadow-2xl p-4 bg-white`} style={{ width: img.w, height: img.h }}>
|
|
<div className="relative w-full h-full">
|
|
<Image src={img.src} alt="Ayris" fill sizes="(max-width: 768px) 100vw, 50vw" className="object-cover" />
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
|
|
{/* REVEALING CENTER CONTENT */}
|
|
<motion.div
|
|
style={{ opacity: entranceOpacity }}
|
|
className="relative z-20 text-center max-w-4xl px-8"
|
|
>
|
|
<div className="space-y-12">
|
|
<h2 className="text-6xl md:text-[110px] font-serif text-[#1A1A1A] leading-[1] tracking-tight uppercase">
|
|
{dict.hero.title}
|
|
</h2>
|
|
|
|
<div className="flex flex-col items-center space-y-12">
|
|
<motion.p
|
|
style={{ opacity: textOpacity, y: textY }}
|
|
className="text-[#1A1A1A]/60 text-xl md:text-2xl font-medium max-w-xl italic leading-relaxed"
|
|
>
|
|
"{dict.footer.desc}"
|
|
</motion.p>
|
|
|
|
<motion.div style={{ opacity: textOpacity, y: textY }}>
|
|
<Link
|
|
href={`/${lang}/reservation`}
|
|
className="inline-flex items-center space-x-3 group text-[14px] font-bold tracking-[0.4em] text-[#1A1A1A] uppercase border-b-2 border-[#1A1A1A] pb-3"
|
|
>
|
|
<span className="text-[#C88C4B] text-xl transform group-hover:translate-x-1.5 transition-transform duration-500">↳</span>
|
|
<span>{dict.footer.book}</span>
|
|
</Link>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|