about complex page starting
@@ -1,6 +1,7 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="https://static.zohocdn.com/zohocrm/v6.0/sdk/2.0.0/zohocrmsdk-6-0.js"></script>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
|
After Width: | Height: | Size: 286 KiB |
|
After Width: | Height: | Size: 191 KiB |
|
After Width: | Height: | Size: 196 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 210 KiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 318 KiB |
|
After Width: | Height: | Size: 318 KiB |
|
After Width: | Height: | Size: 420 KiB |
|
After Width: | Height: | Size: 420 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 184 KiB |
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 174 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 1.6 MiB |
@@ -0,0 +1,118 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useSwipeable } from "react-swipeable";
|
||||
import { useLayoutEffect, useRef, useState } from "react";
|
||||
import { Image } from "../../types/image";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import Button from "../Button";
|
||||
import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon";
|
||||
import RightArrowSliderIcon from "../icons/RightArrowSliderIcon";
|
||||
|
||||
const images: Image[] = [
|
||||
{ id: "1", src: "/images/aboutCompany/livingSolutionsSlider/1.png" },
|
||||
{ id: "2", src: "/images/aboutCompany/livingSolutionsSlider/2.png" },
|
||||
{ id: "3", src: "/images/aboutCompany/livingSolutionsSlider/3.png" },
|
||||
{ id: "4", src: "/images/aboutCompany/livingSolutionsSlider/4.png" },
|
||||
];
|
||||
|
||||
const getGapOffset = (screenWidth: number) => {
|
||||
if (screenWidth > 1600) return 16;
|
||||
if (screenWidth > 1280) return 24;
|
||||
if (screenWidth > 640) return 16;
|
||||
return 16;
|
||||
};
|
||||
|
||||
const LivingSolutionSlider = () => {
|
||||
const [selectedImageIndex, setSelectedImageIndex] = useState(-1);
|
||||
const [rightImageOffset, setRightImageOffset] = useState("");
|
||||
const [imageWidth, setImageWidth] = useState(0);
|
||||
const imageRef = useRef<HTMLImageElement>(null);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!imageRef.current?.src) return;
|
||||
const width = imageRef.current.width;
|
||||
setImageWidth(width);
|
||||
}, [imageRef.current, window.innerWidth]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const screenWidth = window.innerWidth;
|
||||
const gapOffset = getGapOffset(screenWidth);
|
||||
|
||||
const _rightImageOffset =
|
||||
screenWidth > 1280
|
||||
? `${"calc(clamp(315px, 7.0317rem + 19.0319vw, 485px)"} + ${
|
||||
// ? `${"calc(clamp(315px, 6.9317rem + 17.0319vw, 420px)"} + ${
|
||||
selectedImageIndex * (imageWidth + gapOffset)
|
||||
}px)`
|
||||
: `${(selectedImageIndex + 1) * (imageWidth + gapOffset)}px`;
|
||||
|
||||
setRightImageOffset(_rightImageOffset);
|
||||
}, [imageWidth, selectedImageIndex, window.innerWidth]);
|
||||
|
||||
const handlers = useSwipeable({
|
||||
onSwipedLeft: next,
|
||||
onSwipedRight: prev,
|
||||
trackMouse: true,
|
||||
});
|
||||
|
||||
function next() {
|
||||
const lastIndex = isMobile ? images.length - 2 : images.length - 3;
|
||||
|
||||
if (selectedImageIndex === lastIndex) return;
|
||||
setSelectedImageIndex((prev) => prev + 1);
|
||||
}
|
||||
|
||||
function prev() {
|
||||
if (selectedImageIndex === -1) return;
|
||||
setSelectedImageIndex((prev) => prev - 1);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 " {...handlers}>
|
||||
<div
|
||||
className="relative col-span-full overflow-x-hidden flex flex-col"
|
||||
style={{ height: "clamp(30rem, 12.6318rem + 21.6933vw, 75rem)" }}
|
||||
>
|
||||
<div
|
||||
className={`flex gap-4 w-full absolute h-full transition-all duration-300 ease-in-out select-none xl:px-0 px-4`}
|
||||
style={{
|
||||
right: `${rightImageOffset}`,
|
||||
}}
|
||||
>
|
||||
{images.map((image) => (
|
||||
<img
|
||||
ref={imageRef}
|
||||
src={image.src}
|
||||
alt=""
|
||||
key={image.id}
|
||||
className="rounded-2xl sm:aspect-[6/5] object-cover 2xl:w-[calc(100vw*1/2)] xl:w-[calc(100vw*5/12)] pointer-events-none select-none w-[calc(100%-16px)]"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
onClick={prev}
|
||||
icon={<LeftArrowSliderIcon />}
|
||||
className="absolute text-[#73787C] top-[calc(50%-22px)] xl:left-solution-slider-btn-offset left-6 hidden sm:block"
|
||||
/>
|
||||
<Button
|
||||
onClick={next}
|
||||
icon={<RightArrowSliderIcon />}
|
||||
className="absolute text-[#73787C] top-[calc(50%-22px)] right-6 hidden sm:block"
|
||||
/>
|
||||
</div>
|
||||
<div className="self-center gap-1 sm:hidden flex">
|
||||
{images.map((image, index) => (
|
||||
<div
|
||||
key={image.id}
|
||||
className={`transition-all duration-300 ease-in-out rounded-full h-2 ${
|
||||
index - 1 === selectedImageIndex
|
||||
? "w-6 bg-[#0D1922]"
|
||||
: "w-2 bg-[#0D192266]"
|
||||
}`}
|
||||
></div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LivingSolutionSlider;
|
||||
@@ -4,16 +4,21 @@ interface ApartmentDescriptionProps {
|
||||
|
||||
const ApartmentDescription = ({ isVisible }: ApartmentDescriptionProps) => {
|
||||
return (
|
||||
<div className="p-6 bg-black">
|
||||
<div className="p-6 py-3">
|
||||
<div
|
||||
className={`bg-white rounded-lg p-6 flex flex-col text-subheadline-s relative text-nowrap desc-shadow py-2 ${
|
||||
isVisible ? "opacity-100" : "opacity-0"
|
||||
} duration-300 ease-in-out transition-opacity`}
|
||||
>
|
||||
<h2 className="text-[#0D1922] font-semibold pb-4 border-b">
|
||||
1 bedroom, 609 Sqft
|
||||
</h2>
|
||||
<p className="font-semibold pt-4">AED 1,668,888</p>
|
||||
<h2 className="text-[#0D1922] font-semibold">1 bedroom, 609 Sqft</h2>
|
||||
<div className="flex gap-2 items-center text-caption-m font-semibold pt-1 border-b pb-4 justify-center">
|
||||
<p className="text-[#0D1922B2]">East Wing</p>
|
||||
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
|
||||
<p className="text-[#0D1922B2]">Floor 11</p>
|
||||
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
|
||||
<p className="text-[#0D1922B2]">E-213</p>
|
||||
</div>
|
||||
<p className="font-semibold pt-4 text-[#00BED7]">AED 1,668,888</p>
|
||||
<div className="w-0 h-0 border-transparent border-t-[14px] border-x-[6px] border-b-0 absolute left-6 -bottom-[13px] border-t-white"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,17 +25,9 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
|
||||
}
|
||||
|
||||
function handleMouseMove(e: MouseEvent) {
|
||||
const top = window.innerWidth / 2 - window.innerHeight / 2;
|
||||
// setMousePos([e.clientX - 752, e.clientY - Math.abs(top) + 5]);
|
||||
const y = e.clientY - 210;
|
||||
const x = e.clientX - 800;
|
||||
const y = e.clientY - 170;
|
||||
const x = e.clientX - window.innerWidth / 2 - 50;
|
||||
setMousePos([x, y]);
|
||||
console.log("e.clientX", e.clientX);
|
||||
console.log("e.clientY", e.clientY);
|
||||
// setMousePos([
|
||||
// e.clientX - window.innerWidth / 2 - 48,
|
||||
// e.clientY - window.innerHeight / 2 - top,
|
||||
// ]);
|
||||
}
|
||||
|
||||
function handleOnMouseOut(): void {
|
||||
@@ -53,64 +45,67 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute h-full right-0 w-full z-30 bg-[#F3F3F2] p-6 flex flex-col top-[56px] "
|
||||
onMouseOver={onMouseEnter}
|
||||
>
|
||||
<div className="flex justify-between pb-4">
|
||||
<div className="flex flex-col">
|
||||
<h1 className="text-subheadline-m font-semibold text-[#0D1922]">
|
||||
{currentFloor?.floor} Floor
|
||||
</h1>
|
||||
<p className="text-s text-[#73787C]">{currentFloor?.wing}</p>
|
||||
<>
|
||||
<div
|
||||
className="absolute z-[99999] w-fit h-fit top-0 left-0"
|
||||
style={{ top: `${mousePos[1]}px`, left: `${mousePos[0]}px` }}
|
||||
>
|
||||
<ApartmentDescription isVisible={isDescVisible} />
|
||||
</div>
|
||||
<div
|
||||
className="absolute h-full right-0 w-full z-30 bg-[#F3F3F2] p-6 flex flex-col top-[56px] "
|
||||
onMouseOver={onMouseEnter}
|
||||
>
|
||||
<div className="flex justify-between pb-4">
|
||||
<div className="flex flex-col">
|
||||
<h1 className="text-subheadline-m font-semibold text-[#0D1922]">
|
||||
{currentFloor?.floor} Floor
|
||||
</h1>
|
||||
<p className="text-s text-[#73787C]">{currentFloor?.wing}</p>
|
||||
</div>
|
||||
<div className="bg-[#00BED7] text-white text-s px-2 py-[3px] rounded-3xl flex h-fit">
|
||||
<div className="leading-5">234 units</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#00BED7] text-white text-s px-2 py-[3px] rounded-3xl flex h-fit">
|
||||
<div className="leading-5">234 units</div>
|
||||
<div className="px-4 py-[18px] bg-white flex gap-6 text-[#73787C] font-semibold text-caption-m rounded-lg mb-2">
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#A19E9E] w-3 h-3"></div>
|
||||
<p>Studio Flex</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#8299AD] w-3 h-3"></div>
|
||||
<p>Studio</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#A19E9E] w-3 h-3"></div>
|
||||
<p>1 Bedroom</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#BFC9D1] w-3 h-3"></div>
|
||||
<p>1 Bedroom</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#B2B8C4] w-3 h-3"></div>
|
||||
<p>2 Bedroom</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="px-10 bg-white flex gap-6 font-semibold text-caption-m rounded-lg justify-center items-center flex-1 py-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 645 269"
|
||||
>
|
||||
<FloorWestWingLayout />
|
||||
<FloorWestWingHighlighting
|
||||
handleOnApartmentClick={handleOnApartmentClick}
|
||||
handleOnMouseOut={handleOnMouseOut}
|
||||
handleOnMouseOver={handleOnMouseOver}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-4 py-[18px] bg-white flex gap-6 text-[#73787C] font-semibold text-caption-m rounded-lg mb-2">
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#A19E9E] w-3 h-3"></div>
|
||||
<p>Studio Flex</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#8299AD] w-3 h-3"></div>
|
||||
<p>Studio</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#A19E9E] w-3 h-3"></div>
|
||||
<p>1 Bedroom</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#BFC9D1] w-3 h-3"></div>
|
||||
<p>1 Bedroom</p>
|
||||
</div>
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="rounded-full bg-[#B2B8C4] w-3 h-3"></div>
|
||||
<p>2 Bedroom</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-10 bg-white flex gap-6 font-semibold text-caption-m rounded-lg justify-center items-center flex-1 py-4">
|
||||
<div
|
||||
className="absolute z-[99999] w-fit h-fit top-0 right-0"
|
||||
style={{ top: `${mousePos[1]}px`, right: `${-mousePos[0]}px` }}
|
||||
>
|
||||
<ApartmentDescription isVisible={isDescVisible} />
|
||||
</div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 645 269"
|
||||
>
|
||||
<FloorWestWingLayout />
|
||||
<FloorWestWingHighlighting
|
||||
handleOnApartmentClick={handleOnApartmentClick}
|
||||
handleOnMouseOut={handleOnMouseOut}
|
||||
handleOnMouseOver={handleOnMouseOver}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -159,13 +159,13 @@ const SequenceWing = () => {
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out lg:flex hidden bg-black ${
|
||||
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out lg:flex hidden ${
|
||||
currentHoveredFloor?.floor === skyGardenFloor && isWrapperHovered
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
}`}
|
||||
style={{
|
||||
top: mousePos[1],
|
||||
top: mousePos[1] - 25,
|
||||
left: `${
|
||||
isSkygardenSidebar || isFloorSidebar
|
||||
? `calc(${mousePos[0]}px + 25%)`
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
const ArrowLeftIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M15.625 10C15.625 9.65482 15.3452 9.375 15 9.375L6.57394 9.375L10.7318 5.45474C10.9829 5.21795 10.9946 4.82239 10.7578 4.57124C10.521 4.32009 10.1254 4.30846 9.87427 4.54525L4.57124 9.54526C4.446 9.66334 4.375 9.82786 4.375 10C4.375 10.1721 4.446 10.3367 4.57124 10.4547L9.87427 15.4547C10.1254 15.6915 10.521 15.6799 10.7578 15.4288C10.9946 15.1776 10.9829 14.7821 10.7318 14.5453L6.57394 10.625L15 10.625C15.3452 10.625 15.625 10.3452 15.625 10Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default ArrowLeftIcon;
|
||||
@@ -0,0 +1,20 @@
|
||||
const MapVectorIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="27"
|
||||
height="25"
|
||||
fill="none"
|
||||
viewBox="0 0 27 25"
|
||||
>
|
||||
<path
|
||||
fill="#00BED7"
|
||||
stroke="#fff"
|
||||
strokeWidth="1.931"
|
||||
d="M2.057 20.798l10.47-18.483c.566-1 2.014-.981 2.554.034l9.881 18.568c.626 1.177-.524 2.507-1.779 2.057l-8.659-3.105a3.389 3.389 0 00-2.288 0l-8.419 3.02c-1.272.456-2.427-.915-1.76-2.091z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default MapVectorIcon;
|
||||
@@ -41,7 +41,9 @@ const LabelMarker = ({ sphereLink, apartment }: LaberlMarkerProps) => {
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div className="text-white ">{currentSphere?.roomType}</div>
|
||||
<div className="text-white font-semibold">
|
||||
{currentSphere?.roomType}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Html>
|
||||
|
||||
@@ -5,12 +5,15 @@ import Button from "../Button";
|
||||
import BookingIcon from "../icons/BookingIcon";
|
||||
import ChevronDownIcon from "../icons/ChevronDownIcon";
|
||||
import HeartIcon from "../icons/Heart";
|
||||
import MapVectorIcon from "../icons/MapVectorIcon";
|
||||
import useCompass from "../../store/useCompass";
|
||||
|
||||
interface VirtualTourSidebarProps {
|
||||
currentAppartment: null | IAppartmentSphere;
|
||||
}
|
||||
|
||||
const VirtualTourSidebar = ({ currentAppartment }: VirtualTourSidebarProps) => {
|
||||
const { currentCompassRotate } = useCompass();
|
||||
const [isActive, setIsActive] = useState(false);
|
||||
const { setSelectedSphere, selectedSphere } = useSphere();
|
||||
const handleOnShowClick = () => {
|
||||
@@ -53,8 +56,18 @@ const VirtualTourSidebar = ({ currentAppartment }: VirtualTourSidebarProps) => {
|
||||
!isActive ? "max-h-0 opacity-0" : "max-h-screen opacity-100"
|
||||
}`}
|
||||
>
|
||||
<div className="aspect-square w-full bg-black my-4">
|
||||
<img src="" alt="" />
|
||||
<div className="my-4 relative">
|
||||
<img src="/images/virtual-tour/studio1/map.jpg" alt="" />
|
||||
<div
|
||||
className="absolute"
|
||||
style={{
|
||||
top: `${selectedSphere?.mapPosition[1]}px`,
|
||||
left: `${selectedSphere?.mapPosition[0]}px`,
|
||||
transform: `rotate(${-currentCompassRotate + 90}deg)`,
|
||||
}}
|
||||
>
|
||||
<MapVectorIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-4 border-t">
|
||||
<div className="flex flex-col gap-3">
|
||||
@@ -80,13 +93,13 @@ const VirtualTourSidebar = ({ currentAppartment }: VirtualTourSidebarProps) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-14 absolute -bottom-14 left-0 w-full flex justify-between">
|
||||
<div className="flex gap-1 py-2 items-start flex-wrap ">
|
||||
<div className="flex gap-1 py-2 items-start flex-wrap pr-[9px]">
|
||||
{currentAppartment &&
|
||||
currentAppartment.spheres.map((sphere) => {
|
||||
return (
|
||||
<div
|
||||
onClick={() => handleOnLabelClick(sphere)}
|
||||
className={` font-semibold text-caption-s py-0.5 px-2 w-fit rounded-full cursor-pointer pointer-events-auto select-none text-white ${
|
||||
className={`font-semibold text-caption-s py-0.5 px-2 w-fit rounded-full cursor-pointer pointer-events-auto select-none text-white ${
|
||||
selectedSphere?.id === sphere.id
|
||||
? "bg-[#00BED7]"
|
||||
: "bg-[#0D192266]"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"sphereImage": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-01.jpg",
|
||||
"roomType": "entrance",
|
||||
"position": [-14.16, 0, 24.11],
|
||||
"mapPosition": [120, 240],
|
||||
"links": [
|
||||
{
|
||||
"id": "studio-1_sp-02",
|
||||
@@ -25,6 +26,7 @@
|
||||
"sphereImage": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-02.jpg",
|
||||
"roomType": "bathroom",
|
||||
"position": [-14.16, 0, 24.11],
|
||||
"mapPosition": [160, 240],
|
||||
"links": [
|
||||
{
|
||||
"id": "studio-1_sp-01",
|
||||
@@ -38,6 +40,7 @@
|
||||
"sphereImage": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-03.jpg",
|
||||
"roomType": "kitchen",
|
||||
"position": [-14.16, 0, 24.11],
|
||||
"mapPosition": [120, 175],
|
||||
"links": [
|
||||
{
|
||||
"id": "studio-1_sp-04",
|
||||
@@ -56,6 +59,7 @@
|
||||
"sphereImage": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-04.jpg",
|
||||
"roomType": "bedroom 1",
|
||||
"position": [-14.16, 0, 24.11],
|
||||
"mapPosition": [125, 155],
|
||||
"links": [
|
||||
{
|
||||
"id": "studio-1_sp-05",
|
||||
@@ -74,6 +78,7 @@
|
||||
"sphereImage": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-05.jpg",
|
||||
"roomType": "bedroom 2",
|
||||
"position": [-14.16, 0, 24.11],
|
||||
"mapPosition": [115, 125],
|
||||
"links": [
|
||||
{
|
||||
"id": "studio-1_sp-06",
|
||||
@@ -92,6 +97,7 @@
|
||||
"sphereImage": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-06.jpg",
|
||||
"roomType": "glass doors",
|
||||
"position": [-14.16, 0, 24.11],
|
||||
"mapPosition": [115, 55],
|
||||
"links": [
|
||||
{
|
||||
"id": "studio-1_sp-07",
|
||||
@@ -110,6 +116,7 @@
|
||||
"sphereImage": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-07.jpg",
|
||||
"roomType": "balcony",
|
||||
"position": [-14.16, 0, 24.11],
|
||||
"mapPosition": [165, 14],
|
||||
"links": [
|
||||
{
|
||||
"id": "studio-1_sp-06",
|
||||
|
||||
@@ -82,6 +82,10 @@ html {
|
||||
left: clamp(230px, 0.5927rem + 17.2144vw, 370px);
|
||||
}
|
||||
|
||||
.left-solution-slider-btn-offset {
|
||||
left: clamp(230px, 0.3927rem + 15.5144vw, 370px);
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import SearchParticularApartments from "./pages/SearchParticularApartments";
|
||||
import SearchApartment from "./pages/SearchApartment";
|
||||
import Favorites from "./pages/Favorites";
|
||||
import VirtualTour from "./pages/VirtualTour";
|
||||
import AboutComplex from "./pages/AboutComplex";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@@ -29,6 +30,10 @@ const router = createBrowserRouter([
|
||||
path: "/masterplan/:complexId",
|
||||
element: <Complex />,
|
||||
},
|
||||
{
|
||||
path: "/masterplan/:complexId/aboutComplex",
|
||||
element: <AboutComplex />,
|
||||
},
|
||||
{
|
||||
path: "/masterplan/:complexId/wing",
|
||||
element: <ComplexWing />,
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
import { isMobile } from "react-device-detect";
|
||||
import Footer from "../components/Footer";
|
||||
import Button from "../components/Button";
|
||||
import LeftArrowIcon from "../components/icons/LeftArrowIcon";
|
||||
import { Project } from "../types/project";
|
||||
import LivingSolutionSlider from "../components/aboutComplex/LivingSolutionSlider";
|
||||
|
||||
interface ICityItem {
|
||||
time: number;
|
||||
title: string;
|
||||
id: string;
|
||||
image: string;
|
||||
}
|
||||
|
||||
const roveAroundTheCity: ICityItem[] = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Burj Khalifa",
|
||||
time: 10,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/1.png",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "The Dubai Fountain",
|
||||
time: 10,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/2.png",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Dubai Mall",
|
||||
time: 8,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/3.png",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Dubai Opera",
|
||||
time: 11,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/4.png",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
title: "Marasi Promenade",
|
||||
time: 4,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/5.png",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "Rove Downtown Hotel",
|
||||
time: 10,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/6.png",
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
title: "Rove City Walk Hotel",
|
||||
time: 12,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/7.png",
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
title: "City Walk",
|
||||
time: 12,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/8.png",
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
title: "Coca Cola arena",
|
||||
time: 14,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/9.png",
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
title: " Dubai International Airport",
|
||||
time: 10,
|
||||
image: "/images/aboutCompany/roveAroundTheCity/10.png",
|
||||
},
|
||||
];
|
||||
|
||||
interface IAdvantages {
|
||||
title: string;
|
||||
image: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
const advantages: IAdvantages[] = [
|
||||
{
|
||||
title: "Community",
|
||||
image: "/images/aboutCompany/advantages/1.png",
|
||||
id: "1",
|
||||
},
|
||||
{
|
||||
title: "Rove-Inspired design",
|
||||
image: "/images/aboutCompany/advantages/2.png",
|
||||
id: "2",
|
||||
},
|
||||
{
|
||||
title: "Fully loaded amenities",
|
||||
image: "/images/aboutCompany/advantages/3.png",
|
||||
id: "3",
|
||||
},
|
||||
{
|
||||
title: "Add-on services",
|
||||
image: "/images/aboutCompany/advantages/4.png",
|
||||
id: "4",
|
||||
},
|
||||
{
|
||||
title: "Central urban location",
|
||||
image: "/images/aboutCompany/advantages/5.png",
|
||||
id: "5",
|
||||
},
|
||||
];
|
||||
|
||||
interface IUnitDesc {
|
||||
title: string;
|
||||
desc: string;
|
||||
id: string;
|
||||
sqft: number;
|
||||
aed: number;
|
||||
image: string;
|
||||
}
|
||||
|
||||
const unitsDesc: IUnitDesc[] = [
|
||||
{
|
||||
id: "1",
|
||||
image: "/images/aboutCompany/unitsDescription/1.png",
|
||||
aed: 1048888,
|
||||
title: "Studio flex",
|
||||
sqft: 341,
|
||||
desc: "Live in the future, today. In Studio Flex explore the ORI Cloud Bed, optimizing your living space with functionality and smart living. Every inch is designed to provide more space for comfort and convenience. This feature increase your unit size by 33%",
|
||||
},
|
||||
];
|
||||
|
||||
const advStyles = [
|
||||
"xl:col-start-3 xl:col-end-7",
|
||||
"xl:col-span-4",
|
||||
"xl:col-start-5 xl:col-end-9",
|
||||
"xl:col-span-4",
|
||||
"xl:col-start-3 xl:col-span-4",
|
||||
];
|
||||
|
||||
const AboutComplex = () => {
|
||||
return (
|
||||
<section
|
||||
className={`xl:pt-16 pt-10 font-usual ${
|
||||
isMobile ? "pt-24" : ""
|
||||
} grid grid-cols-12`}
|
||||
>
|
||||
<div className="flex px-6 py-4 col-span-full h-16 relative">
|
||||
<div className="fixed">
|
||||
<Button text="Masterplan" icon={<LeftArrowIcon />} buttonType="cta" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="uppercase xl:rubber-headline-indent text-headline-s xl:px-6 px-4 col-span-full pb-6">
|
||||
Rove Home this residence a complete ecosystem that has everything you’ll
|
||||
ever need. This isn’t just where you’ll live. It’s where you’ll thrive.
|
||||
</h1>
|
||||
|
||||
<div className="col-span-full px-6 grid grid-cols-12">
|
||||
<div className="text-caption-m font-semibold text-[#73787C] col-span-1 uppercase">
|
||||
About rove home
|
||||
</div>
|
||||
<div className="col-start-3 col-span-full grid grid-cols-10 gap-6 pb-[100px]">
|
||||
<img
|
||||
src="/images/aboutCompany/rovehome.png"
|
||||
alt=""
|
||||
className="col-span-full"
|
||||
/>
|
||||
<div className="col-span-4 text-l text-[#73787C]">
|
||||
Embrace Rove’s forever-young spirit at Rove Home, where inspiring
|
||||
design and vibrant art installations converge with an exceptional
|
||||
location and an extended playlist of life-enhancing{" "}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-full">
|
||||
<img src="/images/aboutCompany/rovehome_roof.png" alt="" />
|
||||
</div>
|
||||
<div className="col-span-full px-6 grid grid-cols-12 pt-[100px]">
|
||||
<div className="text-caption-m font-semibold text-[#73787C] col-span-1 uppercase">
|
||||
ROVE AROUND THE CITY
|
||||
</div>
|
||||
<div className="col-start-3 col-span-full grid grid-cols-10 gap-6 ">
|
||||
<div className="col-span-4 grid grid-cols-4 gap-4">
|
||||
{roveAroundTheCity.map((item) => (
|
||||
<div
|
||||
className="col-span-2 bg-white rounded-lg flex flex-col p-3"
|
||||
key={item.id}
|
||||
>
|
||||
<div className="flex gap-1 items-center">
|
||||
<div className="bg-[#00BED7] w-3 h-3 rounded-full"></div>
|
||||
<div className="text-[#0D1922] text-m">{item.title}</div>
|
||||
</div>
|
||||
<p className="text-s text-[#73787C]">{item.time} mins</p>
|
||||
<img className="w-16 h-16 self-end" src={item.image} alt="" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="col-span-full col-start-5">
|
||||
<img src="/images/aboutCompany/Map.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-full grid grid-cols-12 px-6 gap-x-4 pt-[140px]">
|
||||
<div className="uppercase text-[#73787C] font-semibold col-span-1 pb-3 text-caption-m">
|
||||
ADVANTAGES
|
||||
</div>
|
||||
<p className="text-subheadline-m font-semibold col-start-3 col-span-full pb-6 text-[#00BED7]">
|
||||
What makes a rove home?
|
||||
</p>
|
||||
{advantages.map((adv, index) => {
|
||||
const styles = `${advStyles[index]} sm:col-start-1 ${
|
||||
index === advantages.length - 1 ? "" : "pb-14"
|
||||
}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col ${styles} col-span-4 col-start-1`}
|
||||
key={adv.id}
|
||||
>
|
||||
<img
|
||||
src={adv.image}
|
||||
alt={adv.title}
|
||||
className="rounded-2xl object-cover aspect-[5/3]"
|
||||
/>
|
||||
<div className="flex gap-1 pt-3 items-center">
|
||||
<div className="rounded-full bg-[#00BED7] w-3 h-3"></div>
|
||||
<div className="text-m">{adv.title}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<h1 className="uppercase xl:rubber-headline-indent text-headline-s xl:px-6 px-4 col-span-full pb-6 pt-[140px]">
|
||||
Live in the future, today. Designed to embody Rove’s unique look and
|
||||
feel, the interiors will feature intelligent and modular living
|
||||
solutions by ORI, never seen before in UAE and the region.
|
||||
</h1>
|
||||
<div className="col-span-full grid grid-cols-12 px-6">
|
||||
<div className="text-caption-m font-semibold text-[#73787C] col-span-2 uppercase col-start-1">
|
||||
EXPANDABLE LIVING SOLUTIONS
|
||||
</div>
|
||||
<div className="flex flex-col gap-6 col-start-3 col-span-4">
|
||||
<div className="text-[#00BED7] text-subheadline-m">
|
||||
ORI introduces a revolutionary solution to apartment living, where
|
||||
space is not just a constraint but an opportunity.{" "}
|
||||
</div>
|
||||
<div className="flex gap-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="bg-[#00BED7] rounded-full w-3 h-3"></div>
|
||||
<p className="text-[#0D1922] text-m">Simple</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="bg-[#00BED7] rounded-full w-3 h-3"></div>
|
||||
<p className="text-[#0D1922] text-m">Safe</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="bg-[#00BED7] rounded-full w-3 h-3"></div>
|
||||
<p className="text-[#0D1922] text-m">Effortless</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-full pt-6">
|
||||
<LivingSolutionSlider />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-full px-6 grid grid-cols-12 pt-[100px]">
|
||||
<div className="text-caption-m font-semibold text-[#73787C] col-span-1 uppercase">
|
||||
ROVE AROUND THE CITY
|
||||
</div>
|
||||
<div className="col-start-3 col-span-full grid grid-cols-10 gap-6">
|
||||
{unitsDesc.map((unit) => (
|
||||
<div className="col-span-5 grid relative grid-cols-5">
|
||||
<div className="col-span-3 h-full bg-white rounded-se-lg rounded-ee-lg">
|
||||
sdfsdfdsfsd
|
||||
</div>
|
||||
<img
|
||||
src={unit.image}
|
||||
alt=""
|
||||
className="absolute right-0 top-0 -z-40"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="col-span-5"></div>
|
||||
<div className="col-span-5"></div>
|
||||
<div className="col-span-5"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutComplex;
|
||||
@@ -9,6 +9,7 @@ interface ISphere {
|
||||
sphereImage: string;
|
||||
roomType: string;
|
||||
position: [number, number, number];
|
||||
mapPosition: [number, number];
|
||||
links: ISphereLink[];
|
||||
}
|
||||
|
||||
|
||||