feat: moible dubai-marina in process
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 817 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 900 KiB |
@@ -1,15 +1,19 @@
|
|||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import ArrowLeftIcon from './icons/ArrowLeftIcon';
|
import ArrowLeftIcon from './icons/ArrowLeftIcon';
|
||||||
import ArrowRightIcon from './icons/map/ArrowRightIcon';
|
import ArrowRightIcon from './icons/map/ArrowRightIcon';
|
||||||
import { dubaiMarinaWellnessSlides } from '../data/aboutDubaiMarina';
|
import { dubaiMarinaSlider } from '../data/aboutDubaiMarina';
|
||||||
import { AnimatePresence, motion } from 'motion/react';
|
import { AnimatePresence, motion } from 'motion/react';
|
||||||
|
|
||||||
function Slider() {
|
function Slider({
|
||||||
|
categoryName,
|
||||||
|
}: {
|
||||||
|
categoryName: 'Wellness' | 'Fitness' | 'Community' | 'Convenience';
|
||||||
|
}) {
|
||||||
const [currentSlide, setCurrentSlide] = useState(0);
|
const [currentSlide, setCurrentSlide] = useState(0);
|
||||||
const [direction, setDirection] = useState(-1);
|
const [direction, setDirection] = useState(-1);
|
||||||
|
|
||||||
const handleNextSlide = () => {
|
const handleNextSlide = () => {
|
||||||
if (currentSlide < dubaiMarinaWellnessSlides.length - 1) {
|
if (currentSlide < dubaiMarinaSlider[categoryName].length - 1) {
|
||||||
setDirection(1);
|
setDirection(1);
|
||||||
setCurrentSlide(currentSlide + 1);
|
setCurrentSlide(currentSlide + 1);
|
||||||
}
|
}
|
||||||
@@ -22,6 +26,10 @@ function Slider() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentSlide(0);
|
||||||
|
}, [categoryName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative w-[63.333vw] h-[27.639vw] rounded-3xl overflow-hidden'>
|
<div className='relative w-[63.333vw] h-[27.639vw] rounded-3xl overflow-hidden'>
|
||||||
<AnimatePresence custom={direction}>
|
<AnimatePresence custom={direction}>
|
||||||
@@ -29,7 +37,7 @@ function Slider() {
|
|||||||
key={currentSlide}
|
key={currentSlide}
|
||||||
className='absolute inset-0 bg-cover bg-no-repeat bg-center'
|
className='absolute inset-0 bg-cover bg-no-repeat bg-center'
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url(${dubaiMarinaWellnessSlides[currentSlide].image})`,
|
backgroundImage: `url(${dubaiMarinaSlider[categoryName][currentSlide].image})`,
|
||||||
}}
|
}}
|
||||||
custom={direction}
|
custom={direction}
|
||||||
initial={{ x: direction > 0 ? '100%' : '-100%' }}
|
initial={{ x: direction > 0 ? '100%' : '-100%' }}
|
||||||
@@ -51,19 +59,19 @@ function Slider() {
|
|||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
>
|
>
|
||||||
{dubaiMarinaWellnessSlides[currentSlide].title}
|
{dubaiMarinaSlider[categoryName][currentSlide].title}
|
||||||
</motion.h3>
|
</motion.h3>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
<AnimatePresence mode='wait'>
|
<AnimatePresence mode='wait'>
|
||||||
<motion.p
|
<motion.p
|
||||||
key={`desc-${currentSlide}`}
|
key={`desc-${currentSlide}`}
|
||||||
className='text-s w-[19.861vw] tracking-[-0.07em] leading-[140%]'
|
className='text-s w-[19.861vw] tracking-[-0.02em] leading-[140%]'
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: 1 }}
|
animate={{ opacity: 1 }}
|
||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
>
|
>
|
||||||
{dubaiMarinaWellnessSlides[currentSlide].description}
|
{dubaiMarinaSlider[categoryName][currentSlide].description}
|
||||||
</motion.p>
|
</motion.p>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,7 +86,7 @@ function Slider() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='text-s'>
|
<div className='text-s'>
|
||||||
{currentSlide + 1}/{dubaiMarinaWellnessSlides.length}
|
{currentSlide + 1}/{dubaiMarinaSlider[categoryName].length}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className='w-10 h-10 rounded-xl text-[#0D1922] bg-white flex items-center justify-center cursor-pointer hover:bg-[#F3F3F2] transition-all duration-200'
|
className='w-10 h-10 rounded-xl text-[#0D1922] bg-white flex items-center justify-center cursor-pointer hover:bg-[#F3F3F2] transition-all duration-200'
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export default function ArrowRightIcon() {
|
export default function ArrowRightIcon() {
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||||
<path
|
<path
|
||||||
fillRule="evenodd"
|
fillRule='evenodd'
|
||||||
clipRule="evenodd"
|
clipRule='evenodd'
|
||||||
d="M5.25 12c0 .414.336.75.75.75h10.111l-4.99 4.704a.75.75 0 1 0 1.03 1.092l6.364-6a.75.75 0 0 0 0-1.092l-6.364-6a.75.75 0 1 0-1.03 1.092l4.99 4.704H6a.75.75 0 0 0-.75.75"
|
d='M5.25 12c0 .414.336.75.75.75h10.111l-4.99 4.704a.75.75 0 1 0 1.03 1.092l6.364-6a.75.75 0 0 0 0-1.092l-6.364-6a.75.75 0 1 0-1.03 1.092l4.99 4.704H6a.75.75 0 0 0-.75.75'
|
||||||
fill="#fff"
|
fill='currentColor'
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
function TextBox({ text }: { text: string }) {
|
function TextBox({ text }: { text: string }) {
|
||||||
return (
|
return (
|
||||||
<div className='text-caption-m px-4 py-1.5 border border-[#E2E2DC] rounded-[40px] w-fit text-[#0D1922]'>
|
<div className='text-caption-m px-4 py-1.5 border border-[#E2E2DC] rounded-[40px] w-fit text-[#0D1922] max-md:text-caption-s'>
|
||||||
{text}
|
{text}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -4,19 +4,6 @@ export const roveHomeDescription = [
|
|||||||
'Inspiring design',
|
'Inspiring design',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const wellnessDescription = [
|
|
||||||
'Vitality Pool',
|
|
||||||
'Reflexology Pool',
|
|
||||||
'Cold Plunge Pool',
|
|
||||||
'Convertible Indoor Infinity Pool',
|
|
||||||
'Zen Library Area',
|
|
||||||
'Finnish Sauna Pod',
|
|
||||||
'Aroma Steam Pod',
|
|
||||||
'Salt Steam Pod',
|
|
||||||
'Ultra Shield Oxygen Pod',
|
|
||||||
'Experience Shower Pods',
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export const dubaiMarinaFeatures = [
|
export const dubaiMarinaFeatures = [
|
||||||
{
|
{
|
||||||
name: 'Life-enhancing Amenties',
|
name: 'Life-enhancing Amenties',
|
||||||
@@ -59,17 +46,113 @@ export const dubaiMarinaDescription = [
|
|||||||
},
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const dubaiMarinaWellnessSlides = [
|
export const dubaiMarinaSlider = {
|
||||||
{
|
Wellness: [
|
||||||
title: 'Indoor Infinity Pool',
|
{
|
||||||
description:
|
title: 'Indoor Infinity Pool',
|
||||||
'Breezy and open in winter and closed in summer – this one-of-a-kind convertible pool takes relaxation to new heights, 165 meters to be precise!',
|
description:
|
||||||
image: '/images/about-complex/dubai-marina/pool1.jpg',
|
'Breezy and open in winter and closed in summer – this one-of-a-kind convertible pool takes relaxation to new heights, 165 meters to be precise!',
|
||||||
},
|
image: '/images/about-complex/dubai-marina/pool1.jpg',
|
||||||
{
|
},
|
||||||
title: 'Multi-sensory wellness pods',
|
{
|
||||||
description:
|
title: 'Multi-sensory wellness pods',
|
||||||
'Set against a backdrop of dream-worthy views, immerse yourself in diverse wellness experiences including ultrashield oxygen, cold bucket showers and more.',
|
description:
|
||||||
image: '/images/about-complex/dubai-marina/pool2.jpg',
|
'Set against a backdrop of dream-worthy views, immerse yourself in diverse wellness experiences including ultrashield oxygen, cold bucket showers and more.',
|
||||||
},
|
image: '/images/about-complex/dubai-marina/pool2.jpg',
|
||||||
] as const;
|
},
|
||||||
|
],
|
||||||
|
Fitness: [
|
||||||
|
{
|
||||||
|
title: 'Semi-Olympic Leisure Pool',
|
||||||
|
description:
|
||||||
|
'Overlooking the city, enjoy a leisurely swim, do your daily 25-meter laps or just unwind at one of the cozy cabanas,',
|
||||||
|
image: '/images/about-complex/dubai-marina/fitness1.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Boutique Fitness Studio',
|
||||||
|
description:
|
||||||
|
'Elevate your fitness regime at flagship Crank Ride & Shape studios – blending fitness, fun, and thrill vibes.',
|
||||||
|
image: '/images/about-complex/dubai-marina/fitness2.jpg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Community: [
|
||||||
|
{
|
||||||
|
title: 'Multi-Purpose Hall',
|
||||||
|
description:
|
||||||
|
'Designed for gatherings, gamings, and entertainment, step into a vibrant multi-functional indoor and outdoor space that can be rented for special events.',
|
||||||
|
image: '/images/about-complex/dubai-marina/community1.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Lobby Lounge',
|
||||||
|
description:
|
||||||
|
'Enjoy multi-level seating, reading nooks, co-working spaces, Rove Café and more, for an unforgettable welcome, every time you come home.',
|
||||||
|
image: '/images/about-complex/dubai-marina/community2.jpg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
Convenience: [
|
||||||
|
{
|
||||||
|
title: 'Rentable Guest Room',
|
||||||
|
description:
|
||||||
|
'A private space for guests to relax and unwind, complete with a comfortable seating area, a flat-screen TV, and a private bathroom.',
|
||||||
|
image: '/images/about-complex/dubai-marina/convenience1.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Entrance & Concierge',
|
||||||
|
description: 'An unforgettable welcome, every time you come home.',
|
||||||
|
image: '/images/about-complex/dubai-marina/convenience2.jpg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const sliderBadgesCategory = {
|
||||||
|
Wellness: [
|
||||||
|
'Vitality Pool',
|
||||||
|
'Reflexology Pool',
|
||||||
|
'Cold Plunge Pool',
|
||||||
|
'Convertible Indoor Infinity Pool',
|
||||||
|
'Zen Library Area',
|
||||||
|
'Finnish Sauna Pod',
|
||||||
|
'Aroma Steam Pod',
|
||||||
|
'Salt Steam Pod',
|
||||||
|
'Ultra Shield Oxygen Pod',
|
||||||
|
'Experience Shower Pods',
|
||||||
|
],
|
||||||
|
Fitness: [
|
||||||
|
'State-of-the-Art Gym',
|
||||||
|
'Crank Fitness Studios – Bike & Shape',
|
||||||
|
'Counter-current Pool',
|
||||||
|
'Rowing Workout',
|
||||||
|
'Aqua Cycling',
|
||||||
|
'Outdoor Semi-olympic Leisure Pool',
|
||||||
|
'Outdoor Gym Park',
|
||||||
|
'Pedal-powered Workstations',
|
||||||
|
],
|
||||||
|
Community: [
|
||||||
|
'Multipurpose Area',
|
||||||
|
'Rentable Kitchen',
|
||||||
|
'Gaming Lounge',
|
||||||
|
'Arcade Zone and PlayStation',
|
||||||
|
'Indoor Cinema',
|
||||||
|
'Suspended Net Lounge',
|
||||||
|
'Karaoke Studios',
|
||||||
|
'Outdoor Cinema & Ampitheatre',
|
||||||
|
'Rove Café and Energise Bar',
|
||||||
|
'Co-working Spaces',
|
||||||
|
'Meeting Rooms & Pods',
|
||||||
|
'Lobby Lounge',
|
||||||
|
'Marina Views Chill Zone',
|
||||||
|
'Allotment Gardens',
|
||||||
|
],
|
||||||
|
Convenience: [
|
||||||
|
'Smart Home Digital Features',
|
||||||
|
'Organic Smart Gardens',
|
||||||
|
'Electric Vehicle Charging Stations',
|
||||||
|
'Bike/Scooter Rental and Storage',
|
||||||
|
'Free Wi-fi',
|
||||||
|
'24x7 Convenience Store',
|
||||||
|
'Rentable Guest Rooms',
|
||||||
|
'Changing Rooms',
|
||||||
|
'Rentable Storage',
|
||||||
|
'Concierge',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|||||||
@@ -16,104 +16,60 @@ button {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer utilities {
|
@utility text-h1 {
|
||||||
.text-headline-l {
|
@apply 2xl:text-[3.889vw] text-[56px] leading-none;
|
||||||
@apply 2xl:text-[clamp(56px,3.889vw,68px)] md:max-2xl:text-[clamp(44px,6.366vw,56px)] text-[44px] leading-none;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.text-h4 {
|
@utility text-h15 {
|
||||||
@apply 2xl:text-[clamp(20px,1.389vw,28px)] text-[20px] leading-[120%];
|
@apply 2xl:text-[2.778vw] text-[40px] leading-[135%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-h5 {
|
@utility text-h2 {
|
||||||
@apply 2xl:text-[clamp(14px,0.972vw,20px)] text-[14px] leading-[125%];
|
@apply 2xl:text-[2.222vw] text-[32px] leading-[125%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-subheadline-l {
|
@utility text-h3 {
|
||||||
@apply 2xl:text-[clamp(40px,2.778vw,48px)] md:max-2xl:text-[clamp(32px,4.63vw,40px)] text-[32px] leading-[135%];
|
@apply 2xl:text-[1.667vw] text-[24px] leading-[135%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-subheadline-m {
|
@utility text-h4 {
|
||||||
@apply 2xl:text-[clamp(24px,1.667vw,28px)] md:max-2xl:text-[clamp(20px,2.894vw,24px)] text-xl leading-[135%];
|
@apply 2xl:text-[1.389vw] text-[20px] leading-[120%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-subheadline-s {
|
@utility text-h5 {
|
||||||
@apply 2xl:text-[clamp(20px,1.389vw,24px)] md:max-2xl:text-[clamp(16px,2.315vw,20px)] text-xl leading-[140%];
|
@apply 2xl:text-[0.972vw] text-sm leading-[125%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-m {
|
@utility text-l {
|
||||||
@apply 2xl:text-[clamp(16px,1.111vw,19px)] md:max-2xl:text-[clamp(13px,1.881vw,16px)] text-[13px] leading-[125%];
|
@apply 2xl:text-[1.389vw] text-[20px] leading-[135%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-s {
|
@utility text-m {
|
||||||
@apply 2xl:text-[clamp(14px,0.972vw,16px)] md:max-2xl:text-[clamp(12px,1.737vw,14px)] text-sm leading-[140%];
|
@apply 2xl:text-[1.111vw] leading-[125%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-caption-m {
|
@utility text-s {
|
||||||
@apply 2xl:text-[clamp(12px,0.833vw,14px)] md:max-2xl:text-[clamp(12px,1.563vw,12px)] text-[clamp(12px,3.333vw,12px)] leading-[135%];
|
@apply 2xl:text-[0.972vw] text-sm leading-[140%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-caption-s {
|
@utility text-btn-l {
|
||||||
@apply 2xl:text-[clamp(10px,0.694vw,12px)] text-[10px] leading-[135%];
|
@apply 2xl:text-[1.111vw] leading-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
@utility text-btn-m {
|
||||||
|
@apply 2xl:text-[0.972vw] text-sm leading-none;
|
||||||
|
}
|
||||||
|
|
||||||
.text-h1 {
|
@utility text-btn-s {
|
||||||
@apply 2xl:text-[3.889vw] text-[56px] leading-none;
|
@apply 2xl:text-[0.833vw] text-xs leading-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-h15 {
|
@utility text-caption-m {
|
||||||
@apply 2xl:text-[2.778vw] text-[40px] leading-[135%];
|
@apply 2xl:text-[0.833vw] text-xs leading-[135%];
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-h2 {
|
@utility text-caption-s {
|
||||||
@apply 2xl:text-[2.222vw] text-[32px] leading-[125%];
|
@apply 2xl:text-[0.694vw] text-[10px] leading-[135%];
|
||||||
}
|
|
||||||
|
|
||||||
.text-h3 {
|
|
||||||
@apply 2xl:text-[1.667vw] text-[24px] leading-[135%];
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-h4 {
|
|
||||||
@apply 2xl:text-[1.389vw] text-[20px] leading-[120%];
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-h5 {
|
|
||||||
@apply 2xl:text-[0.972vw] text-sm leading-[125%];
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-l {
|
|
||||||
@apply 2xl:text-[1.389vw] text-[20px] leading-[135%];
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-m {
|
|
||||||
@apply 2xl:text-[1.111vw] leading-[125%];
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-s {
|
|
||||||
@apply 2xl:text-[0.972vw] text-sm leading-[140%];
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-btn-l {
|
|
||||||
@apply 2xl:text-[1.111vw] leading-none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-bnt-m {
|
|
||||||
@apply 2xl:text-[0.972vw] text-sm leading-none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-btn-s {
|
|
||||||
@apply 2xl:text-[0.833vw] text-xs leading-none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-caption-m {
|
|
||||||
@apply 2xl:text-[0.833vw] text-xs leading-[135%];
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-caption-s {
|
|
||||||
@apply 2xl:text-[0.694vw] text-[10px] leading-[135%];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility font-mixcase-unmixed {
|
@utility font-mixcase-unmixed {
|
||||||
|
|||||||
@@ -1,22 +1,34 @@
|
|||||||
import { useScroll, useTransform, motion, useInView } from 'motion/react';
|
import {
|
||||||
import { useRef } from 'react';
|
useScroll,
|
||||||
|
useTransform,
|
||||||
|
motion,
|
||||||
|
useInView,
|
||||||
|
AnimatePresence,
|
||||||
|
} from 'motion/react';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
dubaiMarinaFeatures,
|
dubaiMarinaFeatures,
|
||||||
dubaiMarinaDescription,
|
dubaiMarinaDescription,
|
||||||
roveHomeDescription,
|
roveHomeDescription,
|
||||||
wellnessDescription,
|
dubaiMarinaSlider,
|
||||||
|
sliderBadgesCategory,
|
||||||
} from '../data/aboutDubaiMarina';
|
} from '../data/aboutDubaiMarina';
|
||||||
|
|
||||||
import EqualIcon from '../components/icons/EqualIcon';
|
import EqualIcon from '../components/icons/EqualIcon';
|
||||||
import TextBox from '../components/TextBox';
|
import TextBox from '../components/ui/TextBox';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import Slider from '../components/Slider';
|
import Slider from '../components/Slider';
|
||||||
import PlusIcon from '../components/icons/map/PlusIcon';
|
import PlusIcon from '../components/icons/map/PlusIcon';
|
||||||
|
import useWindowSize from '../hooks/useWindowSize';
|
||||||
|
|
||||||
function AboutComplexPage() {
|
function AboutComplexPage() {
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
const sliderRef = useRef(null);
|
const sliderRef = useRef(null);
|
||||||
const mapRef = useRef(null);
|
const mapRef = useRef(null);
|
||||||
|
const { width } = useWindowSize();
|
||||||
|
|
||||||
|
const [selectedCategorySlider, setSelectedCategorySlider] =
|
||||||
|
useState<keyof typeof dubaiMarinaSlider>('Wellness');
|
||||||
|
|
||||||
const { scrollYProgress } = useScroll({
|
const { scrollYProgress } = useScroll({
|
||||||
target: containerRef,
|
target: containerRef,
|
||||||
@@ -43,26 +55,27 @@ function AboutComplexPage() {
|
|||||||
return (
|
return (
|
||||||
<div className='relative bg-white' ref={containerRef}>
|
<div className='relative bg-white' ref={containerRef}>
|
||||||
<motion.section
|
<motion.section
|
||||||
className='h-[calc(100dvh-4.444vw)] w-full bg-white text-black fixed top-[4.444vw] left-0 right-0 z-0'
|
className='2xl:h-[calc(100dvh-4.444vw)] w-full bg-white text-black 2xl:fixed top-[4.444vw] left-0 right-0 z-0 max-md:top-[15.556vw]]
|
||||||
|
max-md:bg-[url(/images/about-complex/dubai-marina/tower-mobile.png)] max-md:bg-cover max-md:bg-top max-md:bg-no-repeat max-md:aspect-[360/584]'
|
||||||
style={{
|
style={{
|
||||||
opacity: firstSectionOpacity,
|
opacity: width > 768 ? firstSectionOpacity : 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='absolute inset-0'>
|
<div className='absolute inset-0 max-md:relative'>
|
||||||
<img
|
<img
|
||||||
src='/images/about-complex/dubai-marina/tower.jpg'
|
src='/images/about-complex/dubai-marina/tower.jpg'
|
||||||
alt='dubai marina about'
|
alt='dubai marina about'
|
||||||
className='h-full w-full object-contain object-top'
|
className='h-full w-full object-cover object-top max-md:hidden'
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src='/images/about-complex/dubai-marina/logo.png'
|
src='/images/about-complex/dubai-marina/logo.png'
|
||||||
alt='dubai marina about'
|
alt='dubai marina about'
|
||||||
className='absolute top-[5vw] right-[2.778vw] w-[9.931vw] h-[4.444vw]'
|
className='absolute top-[5vw] right-[2.778vw] w-[9.931vw] h-[4.444vw] max-md:top-[6.667vw] max-md:right-[4.444vw] max-md:w-[21.389vw] max-md:h-[9.444vw]'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='relative flex flex-col justify-between gap-[4.444vw] flex-1 w-full h-full pt-[5vw] pb-[2.5vw] pl-[2.222vw]'>
|
<div className='relative h-full flex flex-col justify-between 2xl:gap-[4.444vw] flex-1 w-full pt-[5vw] pb-[2.5vw] pl-[2.222vw] max-md:px-[4.444vw] max-md:block '>
|
||||||
<div className='text-2xl font-bold whitespace-pre-line space-y-8'>
|
<div className='font-bold whitespace-pre-line space-y-8 max-md:space-y-4'>
|
||||||
<h1 className='text-[5vw] leading-none tracking-[-0.07em] font-mixcase-unmixed font-[500]'>
|
<h1 className='text-[5vw] leading-none tracking-[-0.07em] font-mixcase-unmixed font-[500] max-md:text-[8.889vw]'>
|
||||||
{`Rove Home
|
{`Rove Home
|
||||||
Dubai Marina`}
|
Dubai Marina`}
|
||||||
</h1>
|
</h1>
|
||||||
@@ -72,12 +85,12 @@ function AboutComplexPage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='space-y-8'>
|
<div className='space-y-8 max-md:hidden'>
|
||||||
<h4 className='text-h4 text-[#00BED7] w-[20.486vw] font-[500] '>
|
<h4 className='text-h4 text-[#00BED7] font-[500] whitespace-pre-line'>
|
||||||
{`Own the last slice of
|
{`Own the last slice of
|
||||||
Dubai Marina, ROVE Style`}
|
Dubai Marina, ROVE Style`}
|
||||||
</h4>
|
</h4>
|
||||||
<p className='text-s text-[#0D1922B2] whitespace-pre-line'>
|
<p className='text-s text-[#0D1922B2] whitespace-pre-line '>
|
||||||
{`With an extended playlist of life-enhancing
|
{`With an extended playlist of life-enhancing
|
||||||
amenities, Rove Home is a complete ecosystem
|
amenities, Rove Home is a complete ecosystem
|
||||||
that has everything you'll ever need.`}
|
that has everything you'll ever need.`}
|
||||||
@@ -86,16 +99,27 @@ function AboutComplexPage() {
|
|||||||
</div>
|
</div>
|
||||||
</motion.section>
|
</motion.section>
|
||||||
<motion.section
|
<motion.section
|
||||||
className='w-full text-white bg-white flex justify-center top-[4.444vw] left-0 right-0'
|
className='w-full text-white bg-white flex justify-center top-[4.444vw] left-0 right-0 max-md:top-0 overflow-x-hidden'
|
||||||
style={{
|
style={{
|
||||||
y: secondSectionY,
|
y: width > 768 ? secondSectionY : 0,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
<div className='flex flex-col items-center gap-[2.222vw] w-full pb-[3.75vw]'>
|
<div className='flex flex-col items-center gap-[2.222vw] w-full max-md:py-[8.889vw] max-md:px-[4.444vw]'>
|
||||||
<div className='px-8 flex pt-[7.222vw] flex-col items-center gap-[2.222vw]'>
|
<div className='space-y-8 2xl:hidden self-start'>
|
||||||
<h1 className='text-[3.889vw] text-[#0D1922] font-mixcase-unmixed'>
|
<h4 className='text-h4 text-[#00BED7] font-[500] whitespace-pre-line'>
|
||||||
|
{`Own the last slice of Dubai
|
||||||
|
Marina, ROVE Style`}
|
||||||
|
</h4>
|
||||||
|
<p className='text-s text-[#0D1922B2] whitespace-pre-line '>
|
||||||
|
{`With an extended playlist of life-enhancing
|
||||||
|
amenities, Rove Home is a complete ecosystem
|
||||||
|
that has everything you'll ever need.`}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className='2xl:px-[2.222vw] flex pt-[7.222vw] flex-col items-center gap-[2.222vw] max-md:pt-[17.778vw]'>
|
||||||
|
<h1 className='text-[3.889vw] text-[#0D1922] font-mixcase-unmixed max-md:text-[6.667vw]'>
|
||||||
Rove Home has it all
|
Rove Home has it all
|
||||||
</h1>
|
</h1>
|
||||||
<p className='text-s text-[#0D1922B2] text-center tracking-[-0.02em] whitespace-pre-line'>
|
<p className='text-s text-[#0D1922B2] text-center tracking-[-0.02em] whitespace-pre-line'>
|
||||||
@@ -104,11 +128,12 @@ function AboutComplexPage() {
|
|||||||
and social lifestyle.`}
|
and social lifestyle.`}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex gap-[0.556vw] mt-[0.833vw] h-[26.667vw] w-full px-[2.222vw]'>
|
|
||||||
|
<div className='max-md:overflow-x-auto max-md:self-start max-md:w-screen max-md:-ml-[4.444vw] flex gap-[0.556vw] mt-[0.833vw] 2xl:h-[26.667vw] px-[2.222vw] max-md:pl-[4.444vw] max-md:pr-[2vw] max-md:gap-[2.222vw] max-md:snap-x'>
|
||||||
{dubaiMarinaFeatures.map((feature) => (
|
{dubaiMarinaFeatures.map((feature) => (
|
||||||
<div
|
<div
|
||||||
key={feature.name}
|
key={feature.name}
|
||||||
className={`rounded-3xl flex-1 h-[26.667vw] w-full flex flex-col items-center py-[1.667vw] justify-end bg-cover bg-center bg-no-repeat`}
|
className={`rounded-3xl flex-1 2xl:h-[26.667vw] w-full flex flex-col items-center py-[1.667vw] justify-end bg-cover bg-center bg-no-repeat max-md:w-[91.111vw] max-md:flex-none aspect-[328/287] max-md:snap-always max-md:snap-center`}
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url(${feature.image})`,
|
backgroundImage: `url(${feature.image})`,
|
||||||
}}
|
}}
|
||||||
@@ -120,18 +145,24 @@ function AboutComplexPage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col items-center pt-[4.444vw] h-auto px-8 gap-[4.444vw]'>
|
<div className='flex flex-col items-center pt-[4.444vw] h-auto px-8 gap-[4.444vw] max-md:hidden'>
|
||||||
<h1 className='font-mixcase-unmixed text-[3.889vw] text-[#0D1922]'>
|
<h1 className='font-mixcase-unmixed text-[3.889vw] text-[#0D1922] tracking-[-0.05em]'>
|
||||||
Dubai, <span className='text-[#0D192266]'>within reach</span>
|
Dubai, <span className='text-[#0D192266]'>within reach</span>
|
||||||
</h1>
|
</h1>
|
||||||
<div className='flex w-full text-[#0D192266] gap-[1.111vw]'>
|
<div className='flex w-full text-[#0D192266] gap-[1.111vw]'>
|
||||||
{dubaiMarinaDescription.map((descriptionItem) => (
|
{dubaiMarinaDescription.map((descriptionItem) => (
|
||||||
<div className='flex-1 text-center flex flex-col gap-[1.111vw]'>
|
<div
|
||||||
|
className='flex-1 text-center flex flex-col gap-[1.111vw] cursor-pointer hover:text-[#0D1922B2] transition-all duration-200'
|
||||||
|
onClick={() =>
|
||||||
|
setSelectedCategorySlider(descriptionItem.title)
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className='h-[2px] bg-gray-300 w-full'></div>
|
<div className='h-[2px] bg-gray-300 w-full'></div>
|
||||||
<h5
|
<h5
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'text-h5 tracking-[-0.02em] mt-[0.556vw] font-[500] ',
|
'text-h5 tracking-[-0.02em] mt-[0.556vw] font-[500]',
|
||||||
descriptionItem.title === 'Wellness' && 'text-[#00BED7]'
|
descriptionItem.title === selectedCategorySlider &&
|
||||||
|
'text-[#00BED7]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{descriptionItem.title}
|
{descriptionItem.title}
|
||||||
@@ -139,7 +170,8 @@ function AboutComplexPage() {
|
|||||||
<p
|
<p
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'text-s leading-[125%] tracking-[-0.02em]',
|
'text-s leading-[125%] tracking-[-0.02em]',
|
||||||
descriptionItem.title === 'Wellness' && 'text-[#0D1922] '
|
descriptionItem.title === selectedCategorySlider &&
|
||||||
|
'text-[#0D1922]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{descriptionItem.description}
|
{descriptionItem.description}
|
||||||
@@ -147,22 +179,44 @@ function AboutComplexPage() {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<motion.div
|
<AnimatePresence mode='wait'>
|
||||||
ref={sliderRef}
|
<div ref={sliderRef} className='flex flex-col gap-8'>
|
||||||
initial={{ opacity: 0, y: 40 }}
|
<motion.div
|
||||||
animate={
|
key={`slider-${selectedCategorySlider}`}
|
||||||
isSliderInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 140 }
|
initial={{ opacity: 0, y: 40 }}
|
||||||
}
|
animate={
|
||||||
transition={{ duration: 0.6, ease: 'easeOut' }}
|
isSliderInView
|
||||||
className='flex flex-col gap-8'
|
? { opacity: 1, y: 0 }
|
||||||
>
|
: { opacity: 0, y: 140 }
|
||||||
<Slider />
|
}
|
||||||
<div className='flex gap-[0.556vw] w-[63.333vw] flex-wrap justify-center'>
|
exit={{ opacity: 0, y: -40 }}
|
||||||
{wellnessDescription.map((wellnessItem) => (
|
transition={{ duration: 0.6, ease: 'easeIn' }}
|
||||||
<TextBox text={wellnessItem} />
|
>
|
||||||
))}
|
<Slider categoryName={selectedCategorySlider} />
|
||||||
|
</motion.div>
|
||||||
|
<motion.div
|
||||||
|
key={`badges-${selectedCategorySlider}`}
|
||||||
|
className='flex gap-[0.556vw] w-[63.333vw] flex-wrap justify-center'
|
||||||
|
>
|
||||||
|
{sliderBadgesCategory[selectedCategorySlider].map(
|
||||||
|
(badgeItem, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={badgeItem}
|
||||||
|
initial={{ opacity: 0, y: 10 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{
|
||||||
|
duration: 0.3,
|
||||||
|
delay: index * 0.1,
|
||||||
|
ease: 'easeOut',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextBox text={badgeItem} />
|
||||||
|
</motion.div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
<div className='text-center w-full flex flex-col items-center gap-[2.222vw] bg-white'>
|
<div className='text-center w-full flex flex-col items-center gap-[2.222vw] bg-white'>
|
||||||
<h1 className='font-mixcase-unmixed text-[3.889vw] text-[#0D1922] w-[44.861vw] leading-[100%] tracking-[-0.05em] pt-[8.056vw]'>
|
<h1 className='font-mixcase-unmixed text-[3.889vw] text-[#0D1922] w-[44.861vw] leading-[100%] tracking-[-0.05em] pt-[8.056vw]'>
|
||||||
@@ -232,7 +286,7 @@ function AboutComplexPage() {
|
|||||||
<h1 className='font-mixcase-unmixed text-[3.889vw] text-[#0D1922] w-[44.861vw] leading-[100%] tracking-[-0.05em] pt-[7.222vw]'>
|
<h1 className='font-mixcase-unmixed text-[3.889vw] text-[#0D1922] w-[44.861vw] leading-[100%] tracking-[-0.05em] pt-[7.222vw]'>
|
||||||
Live central. Live centred
|
Live central. Live centred
|
||||||
</h1>
|
</h1>
|
||||||
<p className='text-s w-[35.278vw] text-[#0D1922B2] leading-[140%] tracking-[-0.02em] text-center whitespace-pre-line'>
|
<p className='text-s text-[#0D1922B2] leading-[140%] tracking-[-0.02em] text-center whitespace-pre-line'>
|
||||||
{`Located in the heart of Dubai Marina, Rove Home Dubai Marina is where active
|
{`Located in the heart of Dubai Marina, Rove Home Dubai Marina is where active
|
||||||
living meets modern convenience. Enjoy an energetic lifestyle surrounded by
|
living meets modern convenience. Enjoy an energetic lifestyle surrounded by
|
||||||
trendy cafés, shops, and entertainment options – all within reach.`}
|
trendy cafés, shops, and entertainment options – all within reach.`}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from "react";
|
import FloorSelect from '../components/FloorSelect';
|
||||||
import FloorSelect from "../components/FloorSelect";
|
import { useParams } from 'react-router';
|
||||||
import { useParams } from "react-router";
|
|
||||||
|
|
||||||
function FloorsPage() {
|
function FloorsPage() {
|
||||||
const { complexName } = useParams();
|
const { complexName } = useParams();
|
||||||
|
|||||||