diff --git a/src/components/AboutHQ.tsx b/src/components/AboutHQ.tsx
index e30b8d9..383c16c 100644
--- a/src/components/AboutHQ.tsx
+++ b/src/components/AboutHQ.tsx
@@ -26,7 +26,7 @@ export default function AboutHQ() {
);
return (
-
+
{/* Hero */}
@@ -40,8 +40,8 @@ export default function AboutHQ() {
{`Rove Home HQ —
- Work looks different
- here`}
+ Work looks different
+ here`}
@@ -55,7 +55,7 @@ export default function AboutHQ() {
{`Welcome to the office you
actually want to show up for`}
-
+
HQ by Rove was born out of a question: what if the office could
feel alive again? Now, the first ever hospitality-branded office
building in Dubai is here to answer it. Starting in Marasi Bay
@@ -68,20 +68,6 @@ export default function AboutHQ() {
className="absolute 2xl:top-[1.806vw] 2xl:right-[2.222vw] 2xl:w-[6.111vw] md:max-2xl:hidden w-[17.778vw] max-md:left-1/2 max-md:top-[39.444vw] max-md:-translate-x-1/2"
/>
-
-
-
-
- {`Welcome to the office you
- actually want to show up for`}
-
-
- HQ by Rove was born out of a question: what if the office could
- feel alive again? Now, the first ever hospitality-branded office
- building in Dubai is here to answer it. Starting in Marasi Bay
-
-
-
{/* Slider */}
@@ -96,10 +82,10 @@ export default function AboutHQ() {
More than an office, {" "}
a lifestyle.
-
+
{`Living rooms became boardrooms, kitchens became creative hubs.
- But as the world returned, the office didn’t keep up. HQ by Rove is the
- answer - an office with a living touch.`}
+ But as the world returned, the office didn’t keep up. HQ by Rove is the
+ answer - an office with a living touch.`}
@@ -313,6 +299,6 @@ export default function AboutHQ() {
-
+
);
}
diff --git a/src/components/AboutMarasiDrive.tsx b/src/components/AboutMarasiDrive.tsx
index a8a3bef..a53bfca 100644
--- a/src/components/AboutMarasiDrive.tsx
+++ b/src/components/AboutMarasiDrive.tsx
@@ -53,7 +53,7 @@ function AboutMarasiDrive() {
{`A home for the young
and young in heart`}
-
+
The dynamic essence of Rove comes to life at our new location in
Marasi Drive, Business Bay. Enjoy an urban living experience
beyond the ordinary.
@@ -62,12 +62,12 @@ function AboutMarasiDrive() {
-
+
{`A home for the young
and young in heart`}
-
+
The dynamic essence of Rove comes to life at our new location in
Marasi Drive, Business Bay. Enjoy an urban living experience
beyond the ordinary.
@@ -79,11 +79,11 @@ function AboutMarasiDrive() {
-
+
{`What makes
a Rove Home?`}
-
+
{`Experience the difference with Rove Home where modern amenities, trendy
interiors, and smart features cater to your unique style. Rove Home is your
destination for artful inspiration and cleverly activated spaces.`}
@@ -118,11 +118,11 @@ function AboutMarasiDrive() {
-
+
{`Expandable living
solutions`}
-
+
{`ORI introduces a revolutionary solution to apartment living,
where space is not just a constraint but an opportunity.`}
@@ -158,10 +158,10 @@ function AboutMarasiDrive() {
-
+
Inspired interiors
-
+
{`Smart, flexible designs maximize every inch. The ORI Cloud Bed
expands space by 33%, while the Flexibed transforms living areas
into bedrooms. Multipurpose layouts adapt effortlessly—blending
@@ -173,14 +173,14 @@ function AboutMarasiDrive() {
-
+
-
+
{`A home for the young
and young in heart`}
-
+
{`The dynamic essence of Rove comes to life at our new
location in Marasi Drive, Business Bay. Enjoy an urban
living experience beyond the ordinary.`}
@@ -201,7 +201,7 @@ function AboutMarasiDrive() {
{`Explore the neighbourhood`}
-
+
{`With Dubai's trendiest spots right at your doorstep, explore nearby
entertainment and dining experiences in just 15 minutes. Live your best life
at Rove Home Marasi Drive!`}
@@ -229,7 +229,7 @@ function AboutMarasiDrive() {
{marasiDriveMapCards.map((card) => (
))}
-
+
-
+
{`Live Different
with Rove Home`}
@@ -268,8 +268,8 @@ function AboutMarasiDrive() {
link="/files/marasi-drive/Main Brochure.pdf"
/>
void;
}
-function getAmentiesCount(complexName: string, title: string) {
- const amenties = projects.find(
+function getAmenitiesCount(complexName: string, title: string) {
+ const amenities = projects.find(
(proj) => proj.slug === complexName
- )?.amentiesFloors;
- return amenties?.find((amenty) => amenty.title === title);
+ )?.amenitiesFloors;
+ return amenities?.find((amenity) => amenity.title === title);
}
function FloorPopup({ title, complexName, data, onSelect }: FloorPopupProps) {
const { setPopup } = usePopupStore();
- const amentiesCount = useMemo(
+ const amenitiesCount = useMemo(
() =>
Number.isNaN(+title.at(-1)!)
- ? getAmentiesCount(complexName, title)
+ ? getAmenitiesCount(complexName, title)
: null,
[title, complexName]
);
@@ -35,16 +35,16 @@ function FloorPopup({ title, complexName, data, onSelect }: FloorPopupProps) {
- {amentiesCount ? title : `${title.split(" ").at(-1)} floor`}
+ {amenitiesCount ? title : `${title.split(" ").at(-1)} floor`}
- {complexName === "marasi-drive" && !amentiesCount && (
+ {complexName === "marasi-drive" && !amenitiesCount && (
{title.split(" ")[0]} Wing
)}
- {amentiesCount !== null
- ? `${amentiesCount?.total} Amenties`
+ {amenitiesCount !== null
+ ? `${amenitiesCount?.total} Amenities`
: `${
complexName === "marasi-drive" && data
? data[
@@ -57,7 +57,7 @@ function FloorPopup({ title, complexName, data, onSelect }: FloorPopupProps) {
: data?.others.totalUnits
} apartments`}
- {!amentiesCount && (
+ {!amenitiesCount && (
@@ -66,12 +66,12 @@ function FloorPopup({ title, complexName, data, onSelect }: FloorPopupProps) {
)}
- {((amentiesCount?.indoor && amentiesCount?.outdoor) ||
- !amentiesCount) && (
+ {((amenitiesCount?.indoor && amenitiesCount?.outdoor) ||
+ !amenitiesCount) && (
)}
- {!amentiesCount && data ? (
+ {!amenitiesCount && data ? (
Object.entries(
data[
title.split(" ")[0] === "East"
@@ -92,20 +92,20 @@ function FloorPopup({ title, complexName, data, onSelect }: FloorPopupProps) {
))
) : (
<>
- {amentiesCount?.indoor && (
+ {amenitiesCount?.indoor && (
- {amentiesCount.indoor}
+ {amenitiesCount.indoor}
-
Indoor Amenties
+
Indoor Amenities
)}
- {amentiesCount?.outdoor && (
+ {amenitiesCount?.outdoor && (
- {amentiesCount.outdoor}
+ {amenitiesCount.outdoor}
-
Outdoor Amenties
+
Outdoor Amenities
)}
>
diff --git a/src/components/floor-plans/AmenitiesFloorView.tsx b/src/components/floor-plans/AmenitiesFloorView.tsx
new file mode 100644
index 0000000..93ab6b9
--- /dev/null
+++ b/src/components/floor-plans/AmenitiesFloorView.tsx
@@ -0,0 +1,142 @@
+import { useState } from "react";
+import { AmenitiesFloorData } from "../../types/Floor";
+import Badge from "../ui/Badge";
+import Button from "../ui/Button";
+import PlayIcon from "../icons/PlayIcon";
+import useModalStore from "../../stores/useModalStore";
+import VideoModal from "../VideoModal";
+import ViewToggleButtons from "./ViewToggleButtons";
+import AmentitiesBadge from "../AmentitiesCard";
+import AmenitiesBadge from "../icons/AmenitiesBadge";
+import AmentitiesContentSlider from "../AmentitiesContentSlider";
+
+interface AmenitiesFloorViewProps {
+ floor: AmenitiesFloorData;
+}
+
+function AmenitiesFloorView({ floor }: AmenitiesFloorViewProps) {
+ const { setModal } = useModalStore();
+ const [currentView, setCurrentView] = useState<"exterior" | "interior">(
+ "exterior"
+ );
+
+ const hasInteriorView = !!floor.images.interior;
+ const currentImage =
+ currentView === "interior" && floor.images.interior
+ ? floor.images.interior
+ : floor.images.main;
+
+ // Split amenities into indoor and outdoor if counts are provided
+ const hasIndoorOutdoorSplit =
+ floor.amenitiesCount.indoor !== undefined &&
+ floor.amenitiesCount.outdoor !== undefined;
+
+ const indoorAmenities = hasIndoorOutdoorSplit
+ ? floor.amenitiesList.slice(0, floor.amenitiesCount.indoor)
+ : [];
+
+ const outdoorAmenities = hasIndoorOutdoorSplit
+ ? floor.amenitiesList.slice(floor.amenitiesCount.indoor)
+ : floor.amenitiesList;
+
+ return (
+
+
+
+
{floor.displayName}
+
+
+
+ {hasIndoorOutdoorSplit && (
+
+ )}
+
+
+
+
+
+
+ {floor.video && (
+
setModal( )}
+ >
+
+
+
+
+ )}
+
+
+
+ {hasIndoorOutdoorSplit && indoorAmenities.length > 0 && (
+
+
Indoor Amenities
+
+ {indoorAmenities.map((amenity, index) => (
+
+ ))}
+
+
+ )}
+
+ {hasIndoorOutdoorSplit && indoorAmenities.length > 0 && (
+
+ )}
+
+
+
+ {hasIndoorOutdoorSplit ? "Outdoor Amenities" : "Amenities"}
+
+
+ {outdoorAmenities.map((amenity, index) => (
+
+ ))}
+
+
+
+ {floor.images.content.length > 1 ? (
+
+ ) : (
+ floor.images.content.length === 1 && (
+
+ )
+ )}
+
+ );
+}
+
+export default AmenitiesFloorView;
diff --git a/src/components/floor-plans/FloorPlanViewer.tsx b/src/components/floor-plans/FloorPlanViewer.tsx
new file mode 100644
index 0000000..e596b86
--- /dev/null
+++ b/src/components/floor-plans/FloorPlanViewer.tsx
@@ -0,0 +1,46 @@
+import { FloorData } from "../../types/Floor";
+import { Unit } from "../../types/IUnit";
+import { ComplexName } from "../../types/ComplexName";
+import { FloorsData } from "../FloorSelect";
+import ResidentialFloorView from "./ResidentialFloorView";
+import AmenitiesFloorView from "./AmenitiesFloorView";
+
+interface FloorPlanViewerProps {
+ floor: FloorData;
+ complexName: ComplexName;
+ unitsOnFloor?: Unit[];
+ floorsData?: FloorsData[];
+ selectedFloor: string;
+ onFloorSelect: (floor: string) => void;
+}
+
+function FloorPlanViewer({
+ floor,
+ complexName,
+ unitsOnFloor,
+ floorsData,
+ selectedFloor,
+ onFloorSelect,
+}: FloorPlanViewerProps) {
+ if (floor.type === "residential") {
+ return (
+
+ );
+ }
+
+ if (floor.type === "amenities") {
+ return
;
+ }
+
+ // This should never happen with proper TypeScript typing
+ return null;
+}
+
+export default FloorPlanViewer;
diff --git a/src/components/floor-plans/ResidentialFloorView.tsx b/src/components/floor-plans/ResidentialFloorView.tsx
new file mode 100644
index 0000000..00cd0e2
--- /dev/null
+++ b/src/components/floor-plans/ResidentialFloorView.tsx
@@ -0,0 +1,283 @@
+import { useState } from "react";
+import { ResidentialFloorData } from "../../types/Floor";
+import { Unit } from "../../types/IUnit";
+import { ComplexName } from "../../types/ComplexName";
+import { FloorsData } from "../FloorSelect";
+import Badge from "../ui/Badge";
+import Select from "../ui/Select";
+import UnitTypeBadge from "../UnitTypeBadge";
+import Button from "../ui/Button";
+import { usePopupStore } from "../../stores/usePopupStore";
+import { isMobile } from "react-device-detect";
+
+// Import floor plan components
+import FloorPlanMarasiDriveEast from "../FloorPlanMarasiDriveEast";
+import FloorPlanMarasiDriveWestLower from "../FloorPlanMarasiDriveWestLower";
+import FloorPlanMarasiDriveWestUpper from "../FloorPlanMarasiDriveWestUpper";
+import FloorPlanDubaiMarina7_38 from "../FloorPlanDubaiMarina7_38";
+import FloorPlanDubaiMarina7_38Comb from "../FloorPlanDubaiMarina7_38Comb";
+import FloorPlanDubaiMarina39_40 from "../FloorPlanDubaiMarina39_40";
+import FloorPlanDubaiMarina41_42 from "../FloorPlanDubaiMarina41_42";
+
+interface ResidentialFloorViewProps {
+ floor: ResidentialFloorData;
+ complexName: ComplexName;
+ unitsOnFloor?: Unit[];
+ floorsData?: FloorsData[];
+ selectedFloor: string;
+ onFloorSelect: (floor: string) => void;
+}
+
+function ResidentialFloorView({
+ floor,
+ complexName,
+ unitsOnFloor,
+ floorsData,
+ selectedFloor,
+ onFloorSelect,
+}: ResidentialFloorViewProps) {
+ const { setPopup, setPosition } = usePopupStore();
+ const [isCombinable, setIsCombinable] = useState(false);
+
+ // Marasi Drive specific logic
+ if (complexName === "marasi-drive") {
+ const floorNumber = floor.floorNumber;
+ const wing = floor.wing || selectedFloor.split(" ")[0];
+ const currentFloorData = floorsData?.find(
+ (item) => item.floor === floorNumber
+ );
+
+ const totalUnits =
+ (currentFloorData?.East?.totalUnits || 0) +
+ (currentFloorData?.West?.totalUnits || 0);
+
+ const wingData =
+ currentFloorData?.[selectedFloor.split(" ")[0] as "West" | "East"];
+
+ return (
+
setPopup(null)}>
+
+
{floorNumber} floor
+
+
+
+
+
+
+
[
+ `East ${item.floor}`,
+ `West ${item.floor}`,
+ ]) || []
+ }
+ defaultOption={selectedFloor?.toString() || ""}
+ onSelect={onFloorSelect}
+ className="2xl:w-[8.333vw] md:max-2xl:w-[120px] w-full"
+ maxOptionsCount={7}
+ />
+
+
+
+
+
+
+
+
+
+
+ !isMobile && setPosition({ x: e.clientX, y: e.clientY })
+ }
+ >
+ {unitsOnFloor && wing === "East" && (
+
+ )}
+ {wing === "West" && unitsOnFloor && (
+ <>
+ {floorNumber < 24 ? (
+
+ ) : (
+
+ )}
+ >
+ )}
+
+
+ );
+ }
+
+ // Dubai Marina specific logic
+ if (complexName === "dubai-marina") {
+ const floorNumber = floor.floorNumber;
+ const currentFloorData = floorsData?.find(
+ (item) => item.floor === floorNumber
+ );
+
+ const isSpecialFloor =
+ selectedFloor === "39-40" || selectedFloor === "41-42";
+
+ return (
+
setPopup(null)}>
+
+
{selectedFloor} floor
+
+
+ {!isSpecialFloor && }
+
+
+
+
+
+
{
+ if (item.floor === 39) {
+ return "39-40";
+ }
+ if (item.floor === 41) {
+ return "41-42";
+ }
+ return item.floor.toString();
+ }) || []
+ }
+ defaultOption={selectedFloor?.toString() || ""}
+ onSelect={onFloorSelect}
+ className="2xl:w-[8.333vw] md:max-xl:w-[120px] w-full"
+ maxOptionsCount={7}
+ />
+
+
+
+ item.floor ===
+ parseInt(selectedFloor!.split(" ").at(-1)!)
+ )?.others.types["Studio2"] || 0
+ }
+ />
+
+ item.floor ===
+ parseInt(selectedFloor!.split(" ").at(-1)!)
+ )?.others.types["One Bedroom2"] || 0
+ }
+ />
+
+ item.floor ===
+ parseInt(selectedFloor!.split(" ").at(-1)!)
+ )?.others.types["One Bedroom Loft"] || 0
+ }
+ />
+
+ item.floor ===
+ parseInt(selectedFloor!.split(" ").at(-1)!)
+ )?.others.types["Two Bedroom Loft"] || 0
+ }
+ />
+
+
+ {!isSpecialFloor && (
+
+ setIsCombinable(false)}
+ >
+ Standard
+
+ setIsCombinable(true)}
+ >
+ Combinable
+
+
+ )}
+
+ !isMobile && setPosition({ x: e.clientX, y: e.clientY })
+ }
+ >
+ {selectedFloor && unitsOnFloor && (
+ <>
+ {+selectedFloor >= 7 && +selectedFloor < 39 && (
+ <>
+ {!isCombinable ? (
+
+ ) : (
+
+ )}
+ >
+ )}
+ {selectedFloor === "39-40" && (
+
+ )}
+ {selectedFloor === "41-42" && (
+
+ )}
+ >
+ )}
+
+
+
+ );
+ }
+
+ // Default fallback
+ return
Unsupported complex: {complexName}
;
+}
+
+export default ResidentialFloorView;
diff --git a/src/components/floor-plans/ViewToggleButtons.tsx b/src/components/floor-plans/ViewToggleButtons.tsx
new file mode 100644
index 0000000..ea94d95
--- /dev/null
+++ b/src/components/floor-plans/ViewToggleButtons.tsx
@@ -0,0 +1,47 @@
+import clsx from "clsx";
+import Button from "../ui/Button";
+
+interface ViewToggleButtonsProps {
+ currentView: "exterior" | "interior";
+ onViewChange: (view: "exterior" | "interior") => void;
+ hasInteriorView: boolean;
+}
+
+function ViewToggleButtons({
+ currentView,
+ onViewChange,
+ hasInteriorView,
+}: ViewToggleButtonsProps) {
+ if (!hasInteriorView) {
+ return null;
+ }
+
+ return (
+
+ onViewChange("exterior")}
+ className={clsx(
+ "2xl:px-[1.111vw] 2xl:py-[0.556vw] px-4 py-2",
+ currentView === "exterior" && "!bg-[#0D1922] !text-white"
+ )}
+ >
+ Exterior View
+
+ onViewChange("interior")}
+ className={clsx(
+ "2xl:px-[1.111vw] 2xl:py-[0.556vw] px-4 py-2",
+ currentView === "interior" && "!bg-[#0D1922] !text-white"
+ )}
+ >
+ Interior View
+
+
+ );
+}
+
+export default ViewToggleButtons;
diff --git a/src/components/floor-plans/dubai-marina/GroundDubaiMarina.tsx b/src/components/floor-plans/dubai-marina/GroundDubaiMarina.tsx
index 828085d..d910769 100644
--- a/src/components/floor-plans/dubai-marina/GroundDubaiMarina.tsx
+++ b/src/components/floor-plans/dubai-marina/GroundDubaiMarina.tsx
@@ -13,7 +13,7 @@ function GroundDubaiMarina() {
diff --git a/src/components/floor-plans/dubai-marina/RooftopDubaiMarina.tsx b/src/components/floor-plans/dubai-marina/RooftopDubaiMarina.tsx
index d94661e..b5a649b 100644
--- a/src/components/floor-plans/dubai-marina/RooftopDubaiMarina.tsx
+++ b/src/components/floor-plans/dubai-marina/RooftopDubaiMarina.tsx
@@ -30,7 +30,7 @@ function RooftopDubaiMarina() {
-
Amenties
+
Amenities
} title="Rove Café" />
} title="Lobby Lounge" />
diff --git a/src/components/floor-plans/marasi-drive/PodiumMarasiDrive.tsx b/src/components/floor-plans/marasi-drive/PodiumMarasiDrive.tsx
index 6e3d0ad..6fd060d 100644
--- a/src/components/floor-plans/marasi-drive/PodiumMarasiDrive.tsx
+++ b/src/components/floor-plans/marasi-drive/PodiumMarasiDrive.tsx
@@ -41,7 +41,7 @@ function PodiumMarasiDrive() {
@@ -76,7 +76,7 @@ function PodiumMarasiDrive() {
-
Indoor Amenties
+
Indoor Amenities
} title="Indoor Lounge" />
} title="Monkey Bars" />
@@ -110,7 +110,7 @@ function PodiumMarasiDrive() {
-
Outdoor Amenties
+
Outdoor Amenities
}
diff --git a/src/components/floor-plans/marasi-drive/RooftopMarasiDrive.tsx b/src/components/floor-plans/marasi-drive/RooftopMarasiDrive.tsx
index fe0e391..3d9207c 100644
--- a/src/components/floor-plans/marasi-drive/RooftopMarasiDrive.tsx
+++ b/src/components/floor-plans/marasi-drive/RooftopMarasiDrive.tsx
@@ -23,7 +23,7 @@ function RooftopMarasiDrive() {
-
Amenties
+
Amenities
} title="Stargazing Point" />
} title="BBQ Terrace" />
diff --git a/src/components/floor-plans/marasi-drive/SkyGardenMarasiDrive.tsx b/src/components/floor-plans/marasi-drive/SkyGardenMarasiDrive.tsx
index 8cb9769..70d4966 100644
--- a/src/components/floor-plans/marasi-drive/SkyGardenMarasiDrive.tsx
+++ b/src/components/floor-plans/marasi-drive/SkyGardenMarasiDrive.tsx
@@ -32,7 +32,7 @@ function SkyGardenMarasiDrive() {
@@ -67,7 +67,7 @@ function SkyGardenMarasiDrive() {
-
Indoor Amenties
+
Indoor Amenities
} title="Indoor Lap Pool" />
} title="Wellness Features" />
@@ -76,7 +76,7 @@ function SkyGardenMarasiDrive() {
-
Outdoor Amenties
+
Outdoor Amenities
} title="Padel Pong" />
} title="Sun Lounging Deck" />
diff --git a/src/components/header/BrochuresDropdown.tsx b/src/components/header/BrochuresDropdown.tsx
index 5511795..131ee9c 100644
--- a/src/components/header/BrochuresDropdown.tsx
+++ b/src/components/header/BrochuresDropdown.tsx
@@ -37,7 +37,7 @@ export default function BrochuresDropdown() {
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ bounce: 0, duration: 0.3 }}
- className="max-2xl:hidden p-[1.667vw] flex gap-[1.111vw] justify-stretch items-stretch fixed top-[calc(3.889vw+20px)] left-[40vw] w-[50vw] rounded-[1.111vw] bg-white shadow-[0_2px_8px_rgba(0,0,0,0.15)]"
+ className="max-2xl:hidden p-[1.111vw] flex gap-[1.111vw] justify-stretch items-stretch fixed top-[calc(3.889vw+20px)] left-[21%] rounded-[1.111vw] bg-white shadow-[0_2px_8px_rgba(0,0,0,0.15)]"
>
{projectBrochures.map((project, index) => (
- {projectTitle}
+
+
{projectTitle}
{brochures.map((brochure, index) => (
- {title}
+ {title}
diff --git a/src/data/aboutDubaiMarina.ts b/src/data/aboutDubaiMarina.ts
index c25ed5f..ce933fb 100644
--- a/src/data/aboutDubaiMarina.ts
+++ b/src/data/aboutDubaiMarina.ts
@@ -8,8 +8,8 @@ export const dubaiMarinaDescriptionBadges = [
export const dubaiMarinaFeatures = [
{
- name: "Life-enhancing Amenties",
- image: "/images/about-complex/dubai-marina/amenties.jpg",
+ name: "Life-enhancing Amenities",
+ image: "/images/about-complex/dubai-marina/amenities.jpg",
},
{
name: "Community",
diff --git a/src/data/aboutMarasiDrive.ts b/src/data/aboutMarasiDrive.ts
index 730ad88..da88d7b 100644
--- a/src/data/aboutMarasiDrive.ts
+++ b/src/data/aboutMarasiDrive.ts
@@ -14,8 +14,8 @@ export const marasiDriveFeatures = [
image: "/images/about-complex/marasi-drive/location.jpg",
},
{
- name: "Fully Loaded Amenties",
- image: "/images/about-complex/marasi-drive/amenties.jpg",
+ name: "Fully Loaded Amenities",
+ image: "/images/about-complex/marasi-drive/amenities.jpg",
},
{
name: "Rove-Inspired Design",
diff --git a/src/data/brochures.ts b/src/data/brochures.ts
index e290f00..44ce5f6 100644
--- a/src/data/brochures.ts
+++ b/src/data/brochures.ts
@@ -24,14 +24,6 @@ export const projectBrochures: ProjectBrochures[] = [
title: "Technical Brochure",
link: "/files/brochures/marasi-drive/Technical Brochure.pdf",
},
- {
- title: "Factsheet",
- link: "/files/brochures/marasi-drive/Factsheet.pdf",
- },
- {
- title: "Reasons to buy",
- link: "/files/brochures/marasi-drive/Reasons to buy.pdf",
- },
],
},
{
@@ -46,24 +38,8 @@ export const projectBrochures: ProjectBrochures[] = [
link: "/files/brochures/downtown/Amenities Brochure.pdf",
},
{
- title: "Unit Plans",
- link: "/files/brochures/downtown/Unit Plan.pdf",
- },
- {
- title: "Typical Floor plan 2-13",
- link: "/files/brochures/downtown/Typical Floor plan 2-13.pdf",
- },
- {
- title: "Typical Floor plan 14-19",
- link: "/files/brochures/downtown/Typical Floor plan 14-19.pdf",
- },
- {
- title: "Factsheet",
- link: "/files/brochures/downtown/Factsheet.pdf",
- },
- {
- title: "Reasons to buy",
- link: "/files/brochures/downtown/Reasons to buy.pdf",
+ title: "Technical Brochure",
+ link: "/files/brochures/downtown/Technical Brochure.pdf",
},
],
},
@@ -82,21 +58,18 @@ export const projectBrochures: ProjectBrochures[] = [
title: "Technical Brochure",
link: "/files/brochures/dubai-marina/Technical Brochure.pdf",
},
+ ],
+ },
+ {
+ projectTitle: "Rove Home HQ",
+ brochures: [
{
- title: "Factsheet",
- link: "/files/brochures/dubai-marina/Factsheet.pdf",
+ title: "Main Brochure",
+ link: "/files/brochures/hq/Main Brochure.pdf",
},
{
- title: "RHDM Arabic",
- link: "/files/brochures/dubai-marina/RHDM Arabic.pdf",
- },
- {
- title: "RHDM Turkish",
- link: "/files/brochures/dubai-marina/RHDM Turkish.pdf",
- },
- {
- title: "RHDM Russian",
- link: "/files/brochures/dubai-marina/RHDM Russian.pdf",
+ title: "Technical Brochure",
+ link: "/files/brochures/hq/Technical Brochure.pdf",
},
],
},
diff --git a/src/data/floors/dubai-marina.ts b/src/data/floors/dubai-marina.ts
new file mode 100644
index 0000000..98d7b09
--- /dev/null
+++ b/src/data/floors/dubai-marina.ts
@@ -0,0 +1,156 @@
+import { FloorData } from "../../types/Floor";
+
+export const dubaiMarinaFloors: FloorData[] = [
+ // Ground Level
+ {
+ id: "ground-level",
+ name: "Ground Level",
+ displayName: "Ground Level",
+ type: "amenities",
+ amenitiesCount: {
+ total: 14,
+ },
+ amenitiesList: [
+ { icon: "text", title: "Residential Entrance" },
+ { icon: "text", title: "Multifunctional Feature Staircase" },
+ { icon: "text", title: "Lobby Lounge & Concierge" },
+ { icon: "text", title: "Outdoor Landscape Seating Area" },
+ { icon: "text", title: "Lift Lobby" },
+ { icon: "text", title: "Rove Cafe & Energize Bar" },
+ { icon: "text", title: "Organic Smart Gardens & Seating" },
+ { icon: "text", title: "Co-working Area " },
+ { icon: "text", title: "24x7 Convenience Store" },
+ { icon: "text", title: "WCs" },
+ { icon: "text", title: "Visitor Parking" },
+ { icon: "text", title: "EV Charging Stations" },
+ { icon: "text", title: "Bicycle/Scooter Rental & Storage" },
+ { icon: "text", title: "Drop-off Area" },
+ ],
+ images: {
+ main: "/images/floor-plans/dubai-marina/ground.png",
+ content: ["/images/floor-plans/dubai-marina/ground/content.jpg"],
+ },
+ video: "/videos/dubai-marina/GroundDubaiMarina.mp4",
+ },
+
+ // Podium Level
+ {
+ id: "podium-level",
+ name: "Podium Level",
+ displayName: "Podium Level",
+ type: "amenities",
+ amenitiesCount: {
+ total: 14,
+ indoor: 3,
+ outdoor: 12,
+ },
+ amenitiesList: [
+ // Indoor
+ { icon: "text", title: "Multipurpose Hall" },
+ { icon: "text", title: "Gaming Lounge" },
+ { icon: "text", title: "State-of-the-art Gym" },
+ { icon: "text", title: "7m Climbing Wall" },
+ { icon: "text", title: "Changing Rooms & Lockers" },
+ { icon: "text", title: "Hydration Station" },
+ { icon: "text", title: "Boutique Fitness Studio - Crank" },
+ { icon: "text", title: "Rentable Guest Rooms" },
+ // Outdoor
+ { icon: "text", title: "Semi-Olympic Leisure Pool" },
+ { icon: "text", title: "Outdoor Cinema & Amphitheatre" },
+ { icon: "text", title: "Water Feature Wall" },
+ { icon: "text", title: "Multipurpose Fitness Pool" },
+ { icon: "text", title: "Communal Gardens" },
+ { icon: "text", title: "BBQ & Social Zone" },
+ { icon: "text", title: "Popsicle Cart" },
+ { icon: "text", title: "Gaming Lounge - Terrace" },
+ { icon: "text", title: "Zen Library" },
+ { icon: "text", title: "Co-working Area" },
+ { icon: "text", title: "Multipurpose Hall with Terrace" },
+ { icon: "text", title: "Marina View Chill Zone" },
+ { icon: "text", title: "Outdoor Gym" },
+ ],
+ images: {
+ main: "/images/floor-plans/dubai-marina/podium.png",
+ content: [
+ "/images/floor-plans/dubai-marina/podium/content1.jpg",
+ "/images/floor-plans/dubai-marina/podium/content2.jpg",
+ "/images/floor-plans/dubai-marina/podium/content3.jpg",
+ ],
+ },
+ video: "/videos/dubai-marina/PodiumDubaiMarina.mp4",
+ },
+
+ // Residential floors 7-20
+ ...Array.from({ length: 14 }, (_, i) => {
+ const floor = i + 7;
+ return {
+ id: `floor-${floor}`,
+ name: `${floor}`,
+ displayName: `${floor}`,
+ type: "residential" as const,
+ floorNumber: floor,
+ };
+ }),
+
+ // Residential floors 22-38
+ ...Array.from({ length: 17 }, (_, i) => {
+ const floor = i + 22;
+ return {
+ id: `floor-${floor}`,
+ name: `${floor}`,
+ displayName: `${floor}`,
+ type: "residential" as const,
+ floorNumber: floor,
+ };
+ }),
+
+ // Residential floors 39-40 (special layout)
+ {
+ id: "floor-39-40",
+ name: "39-40",
+ displayName: "39-40",
+ type: "residential",
+ floorNumber: 39,
+ },
+
+ // Residential floors 41-42 (special layout)
+ {
+ id: "floor-41-42",
+ name: "41-42",
+ displayName: "41-42",
+ type: "residential",
+ floorNumber: 41,
+ },
+
+ // Rooftop (Sky 44)
+ {
+ id: "rooftop",
+ name: "Rooftop",
+ displayName: "Sky 44 - Rooftop",
+ type: "amenities",
+ amenitiesCount: {
+ total: 14,
+ },
+ amenitiesList: [
+ { icon: "text", title: "Sky Viewing Lounges" },
+ { icon: "text", title: "Convertible Indoor Infinity Pool" },
+ { icon: "text", title: "Marina View Amphitheatre" },
+ { icon: "text", title: "Ultra Shield Oxygen Pod" },
+ { icon: "text", title: "Aroma Steam Pod" },
+ { icon: "text", title: "Reflexology Pool" },
+ { icon: "text", title: "Cold Bucket Experience Shower Pod" },
+ { icon: "text", title: "Experience Shower Pod" },
+ { icon: "text", title: "Cold Plunge Pool" },
+ { icon: "text", title: "Salt Steam Pod" },
+ { icon: "text", title: "Finnish Sauna Pod" },
+ { icon: "text", title: "Water Feature Wall" },
+ { icon: "text", title: "Vitality Pool" },
+ { icon: "text", title: "Changing Rooms and Lockers" },
+ ],
+ images: {
+ main: "/images/floor-plans/dubai-marina/rooftop.png",
+ content: ["/images/floor-plans/dubai-marina/rooftop/content.jpg"],
+ },
+ video: "/videos/dubai-marina/SkyDubaiMarina.mp4",
+ },
+];
diff --git a/src/data/floors/marasi-drive.ts b/src/data/floors/marasi-drive.ts
new file mode 100644
index 0000000..2ecb928
--- /dev/null
+++ b/src/data/floors/marasi-drive.ts
@@ -0,0 +1,207 @@
+import { FloorData } from "../../types/Floor";
+
+export const marasiDriveFloors: FloorData[] = [
+ // Ground Level
+ {
+ id: "ground-level",
+ name: "Ground Level",
+ displayName: "Ground Level",
+ type: "amenities",
+ amenitiesCount: {
+ total: 7,
+ },
+ amenitiesList: [
+ { icon: "RoveCafe", title: "Rove Café" },
+ { icon: "LoungingSpaceIcon", title: "Lobby Lounge" },
+ { icon: "CoworkingIcon", title: "Coworking Space" },
+ { icon: "LushLandscapeIcon", title: "Outdoor Terrace" },
+ { icon: "PrivateMeetingRoomsIcon", title: "Private Meeting Rooms" },
+ { icon: "ConvenienceIcon", title: "Convenience Store" },
+ { icon: "SoundproofMeetingPodsIcon", title: "Soundproof Meeting Pods" },
+ ],
+ images: {
+ main: "/images/floor-plans/marasi-drive/ground.png",
+ content: [
+ "/images/floor-plans/marasi-drive/ground/content1.jpg",
+ "/images/floor-plans/marasi-drive/ground/content2.jpg",
+ "/images/floor-plans/marasi-drive/ground/content3.jpg",
+ "/images/floor-plans/marasi-drive/ground/content4.jpg",
+ "/images/floor-plans/marasi-drive/ground/content5.jpg",
+ "/images/floor-plans/marasi-drive/ground/content6.jpg",
+ ],
+ },
+ video: "/videos/marasi-drive/GroundMarasiDrive.mp4",
+ },
+
+ // Podium Level
+ {
+ id: "podium-level",
+ name: "Podium Level",
+ displayName: "Podium Level",
+ type: "amenities",
+ amenitiesCount: {
+ total: 27,
+ indoor: 13,
+ outdoor: 14,
+ },
+ amenitiesList: [
+ // Indoor
+ { icon: "LoungeIcon", title: "Indoor Lounge" },
+ { icon: "MonkeyBarsIcon", title: "Monkey Bars" },
+ { icon: "KaraokeIcon", title: "Karaoke Room" },
+ { icon: "ArcadeGameIcon", title: "Arcade Games" },
+ { icon: "ClimbingWallIcon", title: "Climbing Wall" },
+ { icon: "PlaystationIcon", title: "Playstation Deck" },
+ { icon: "FullyEquippedGymIcon", title: "Fully Equipped Gym" },
+ { icon: "ChangingRoomIcon", title: "Changing Rooms" },
+ { icon: "HammockMovieLoungeIcon", title: "Hammock Movie Lounge" },
+ { icon: "GuestRooms", title: "Guest Rooms" },
+ { icon: "MultiballInteractiveGamingIcon", title: "Multi Ball Interactive Gaming" },
+ { icon: "MultiPurposeRoomWithKitchenIcon", title: "Multi-purpose Room for Kitchen" },
+ { icon: "GamingLoungeIcon", title: "Gaming Lounge" },
+ // Outdoor
+ { icon: "UrbanBeachPoolIcon", title: "Urban Beach Pool" },
+ { icon: "JacuzziIcon", title: "Jacuzzi" },
+ { icon: "YogaLoungeIcon", title: "Yoga Lounge" },
+ { icon: "SunLoungeIcon", title: "Sun Lounging Pool" },
+ { icon: "CascadingLeisurePoolIcon", title: "Cascading Leisure Pool" },
+ { icon: "AquaCyclingIcon", title: "AquaCycling" },
+ { icon: "OpenAirGymIcon", title: "Open-Air Gym" },
+ { icon: "RoveBeverageTruckIcon", title: "Rove Beverage Truck" },
+ { icon: "CabanasWithDaybeds", title: "Cabanas with Daybeds" },
+ { icon: "IntegratedLapPoolIcon", title: "Integrated Lap Pool" },
+ { icon: "SunkenGardensIcon", title: "Sunken Gardens" },
+ { icon: "MultiPurposeRoomWithKitchenIcon", title: "Outdoor Multi-Purpose Terrace" },
+ { icon: "GamingTerraceIcon", title: "Outdoor Gaming Terrace" },
+ { icon: "CoworkingIcon", title: "Outdoor Coworking Space" },
+ ],
+ images: {
+ main: "/images/floor-plans/marasi-drive/podium.png",
+ content: [
+ "/images/floor-plans/marasi-drive/podium/content1.jpg",
+ "/images/floor-plans/marasi-drive/podium/content2.jpg",
+ "/images/floor-plans/marasi-drive/podium/content3.jpg",
+ "/images/floor-plans/marasi-drive/podium/content4.jpg",
+ "/images/floor-plans/marasi-drive/podium/content5.jpg",
+ "/images/floor-plans/marasi-drive/podium/content6.jpg",
+ "/images/floor-plans/marasi-drive/podium/content7.jpg",
+ "/images/floor-plans/marasi-drive/podium/content8.jpg",
+ "/images/floor-plans/marasi-drive/podium/content9.jpg",
+ "/images/floor-plans/marasi-drive/podium/content10.jpg",
+ "/images/floor-plans/marasi-drive/podium/content11.jpg",
+ ],
+ },
+ video: "/videos/marasi-drive/PodiumMarasiDrive.mp4",
+ },
+
+ // Residential floors 5-21 East Wing
+ ...Array.from({ length: 17 }, (_, i) => {
+ const floor = i + 5;
+ return {
+ id: `east-${floor}`,
+ name: `East ${floor}`,
+ displayName: `East Wing ${floor}`,
+ type: "residential" as const,
+ floorNumber: floor,
+ wing: "East" as const,
+ };
+ }),
+
+ // Residential floors 5-21 West Wing
+ ...Array.from({ length: 17 }, (_, i) => {
+ const floor = i + 5;
+ return {
+ id: `west-${floor}`,
+ name: `West ${floor}`,
+ displayName: `West Wing ${floor}`,
+ type: "residential" as const,
+ floorNumber: floor,
+ wing: "West" as const,
+ };
+ }),
+
+ // Residential floors 24-31 West Wing (upper)
+ ...Array.from({ length: 8 }, (_, i) => {
+ const floor = i + 24;
+ return {
+ id: `west-${floor}`,
+ name: `West ${floor}`,
+ displayName: `West Wing ${floor}`,
+ type: "residential" as const,
+ floorNumber: floor,
+ wing: "West" as const,
+ };
+ }),
+
+ // Sky Garden
+ {
+ id: "sky-garden",
+ name: "Sky Garden",
+ displayName: "Sky Garden",
+ type: "amenities",
+ amenitiesCount: {
+ total: 15,
+ indoor: 3,
+ outdoor: 12,
+ },
+ amenitiesList: [
+ // Indoor
+ { icon: "PoolIcon", title: "Indoor Lap Pool" },
+ { icon: "WellnessIcon", title: "Wellness Features" },
+ { icon: "ChangingRoomIcon", title: "Changing Rooms" },
+ // Outdoor
+ { icon: "PingPongIcon", title: "Padel Pong" },
+ { icon: "SunLoungeIcon", title: "Sun Lounging Deck" },
+ { icon: "CinemaIcon", title: "Outdoor Cinema" },
+ { icon: "BoulderingWallIcon", title: "Bouldering Wall" },
+ { icon: "PingPongInTubeIcon", title: "Ping Pong in a Tube" },
+ { icon: "AmphitheatreIcon", title: "Amphitheatre" },
+ { icon: "CommunalDiningTablesIcon", title: "Communal Dining Tables" },
+ { icon: "SuspendedLoungingNetsIcon", title: "Suspended Lounging Nets " },
+ { icon: "LushLandscapeIcon", title: "Lush Landscape" },
+ { icon: "RunningWheelIcon", title: "Running Wheel" },
+ { icon: "ChessIcon", title: "Chess Tables" },
+ { icon: "ClimbingWallIcon", title: "Climbing Wall" },
+ { icon: "CoworkingIcon", title: "Outdoor Coworking Space" },
+ { icon: "MultiPurposeIcon", title: "Multi-purpose Court" },
+ ],
+ images: {
+ main: "/images/floor-plans/marasi-drive/sky-garden.png",
+ content: [
+ "/images/floor-plans/marasi-drive/skygarden/content1.jpg",
+ "/images/floor-plans/marasi-drive/skygarden/content2.jpg",
+ "/images/floor-plans/marasi-drive/skygarden/content3.jpg",
+ "/images/floor-plans/marasi-drive/skygarden/content4.jpg",
+ ],
+ },
+ video: "/videos/marasi-drive/SkyGardenMarasiDrive.mp4",
+ },
+
+ // Rooftop
+ {
+ id: "rooftop",
+ name: "Rooftop",
+ displayName: "Rooftop",
+ type: "amenities",
+ amenitiesCount: {
+ total: 10,
+ },
+ amenitiesList: [
+ { icon: "StargazingIcon", title: "Stargazing Point" },
+ { icon: "BBQTerraceIcon", title: "BBQ Terrace" },
+ { icon: "OutdoorKitchenIcon", title: "Outdoor Kitchen" },
+ { icon: "CabanasWithDaybeds", title: "Cabanas with Daybeds" },
+ { icon: "ViewingDeckWithWingsIcon", title: "Viewing Deck with Wings" },
+ { icon: "LoungingSpaceIcon", title: "Lounging Space" },
+ { icon: "SunkenSeatingIcon", title: "Sunken Seating" },
+ { icon: "FirePitIcon", title: "Firepit" },
+ { icon: "RooftopGardenIcon", title: "Rooftop Garden" },
+ { icon: "CommunalDiningTablesRoundedIcon", title: "Communal Dining Tables" },
+ ],
+ images: {
+ main: "/images/floor-plans/marasi-drive/rooftop.png",
+ content: ["/images/floor-plans/marasi-drive/rooftop/content.jpg"],
+ },
+ video: "/videos/marasi-drive/RooftopMarasiDrive.mp4",
+ },
+];
diff --git a/src/data/projects.ts b/src/data/projects.ts
index fb174b4..8863d5d 100644
--- a/src/data/projects.ts
+++ b/src/data/projects.ts
@@ -572,7 +572,7 @@ export const projects: Project[] = [
tourAvailable: true,
},
],
- amentiesFloors: [
+ amenitiesFloors: [
{
title: "Rooftop",
total: 10,
@@ -1971,7 +1971,7 @@ export const projects: Project[] = [
tourAvailable: true,
},
],
- amentiesFloors: [
+ amenitiesFloors: [
{
title: "Rooftop",
total: 14,
@@ -1994,6 +1994,6 @@ export const projects: Project[] = [
img: "/images/search/rove_home_hq.png",
buildingType: "commercial",
types: [],
- amentiesFloors: [],
- }
+ amenitiesFloors: [],
+ },
];
diff --git a/src/pages/FloorsPage.tsx b/src/pages/FloorsPage.tsx
index 1a81f16..5684aee 100644
--- a/src/pages/FloorsPage.tsx
+++ b/src/pages/FloorsPage.tsx
@@ -2,33 +2,16 @@ import FloorSelect, { FloorsData } from "../components/FloorSelect";
import { useParams } from "react-router";
import FloorSidebar from "../components/FloorSidebar";
-import { useEffect, useState } from "react";
-import Select from "../components/ui/Select";
+import { useState, useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import { api } from "../api/ky";
-import UnitTypeBadge from "../components/UnitTypeBadge";
-import FloorPlanMarasiDriveEast from "../components/FloorPlanMarasiDriveEast";
-import RooftopMarasiDrive from "../components/floor-plans/marasi-drive/RooftopMarasiDrive";
-import GroundMarasiDrive from "../components/floor-plans/marasi-drive/GroundMarasiDrive";
-import PodiumMarasiDrive from "../components/floor-plans/marasi-drive/PodiumMarasiDrive";
-import SkyGardenMarasiDrive from "../components/floor-plans/marasi-drive/SkyGardenMarasiDrive";
-import Badge from "../components/ui/Badge";
-import RooftopDubaiMarina from "../components/floor-plans/dubai-marina/RooftopDubaiMarina";
-import GroundDubaiMarina from "../components/floor-plans/dubai-marina/GroundDubaiMarina";
-import PodiumDubaiMarina from "../components/floor-plans/dubai-marina/PodiumDubaiMarina";
-import FloorPlanMarasiDriveWestLower from "../components/FloorPlanMarasiDriveWestLower";
-import FloorPlanMarasiDriveWestUpper from "../components/FloorPlanMarasiDriveWestUpper";
import { SPECIAL_FLOORS } from "../constants/floors";
import { Unit } from "../types/IUnit";
import slugToComplexName from "../utils/slugToComplexName";
-import { usePopupStore } from "../stores/usePopupStore";
-import { isMobile } from "react-device-detect";
-import FloorPlanDubaiMarina41_42 from "../components/FloorPlanDubaiMarina41_42";
-import FloorPlanDubaiMarina39_40 from "../components/FloorPlanDubaiMarina39_40";
-import FloorPlanDubaiMarina7_38Comb from "../components/FloorPlanDubaiMarina7_38Comb";
-import FloorPlanDubaiMarina7_38 from "../components/FloorPlanDubaiMarina7_38";
-import Button from "../components/ui/Button";
import { ComplexName } from "../types/ComplexName";
+import FloorPlanViewer from "../components/floor-plans/FloorPlanViewer";
+import { marasiDriveFloors } from "../data/floors/marasi-drive";
+import { dubaiMarinaFloors } from "../data/floors/dubai-marina";
function FloorsPage() {
const [selectedFloor, setSelectedFloor] = useState(null);
@@ -66,12 +49,22 @@ function FloorsPage() {
.json(),
});
- const { setPosition, setPopup } = usePopupStore();
- const [isCombinable, setIsCombinable] = useState(false);
+ // Get floor data based on complex
+ const allFloors = useMemo(() => {
+ if (complexName === "marasi-drive") {
+ return marasiDriveFloors;
+ }
+ if (complexName === "dubai-marina") {
+ return dubaiMarinaFloors;
+ }
+ return [];
+ }, [complexName]);
- useEffect(() => {
- setIsCombinable(false);
- }, [selectedFloor]);
+ // Find current floor
+ const currentFloor = useMemo(() => {
+ if (!selectedFloor) return null;
+ return allFloors.find((floor) => floor.name === selectedFloor);
+ }, [selectedFloor, allFloors]);
return (
@@ -84,287 +77,20 @@ function FloorsPage() {
isOpen={!!selectedFloor}
onClose={() => setSelectedFloor(null)}
>
- {complexName === "dubai-marina" && (
- <>
- {selectedFloor === "Rooftop" &&
}
- {selectedFloor === "Ground Level" &&
}
- {selectedFloor === "Podium Level" &&
}
- {!!parseInt(selectedFloor!) && (
-
setPopup(null)}
- >
-
-
{selectedFloor} floor
-
- item.floor === parseInt(selectedFloor!),
- )?.others.totalUnits || 0
- } Apartments`}
- />
-
-
-
-
-
-
-
{
- if (item.floor === 39) {
- return "39-40";
- }
- if (item.floor === 41) {
- return "41-42";
- }
- return item.floor.toString();
- }) || []
- }
- defaultOption={selectedFloor?.toString() || ""}
- onSelect={setSelectedFloor}
- className="2xl:w-[8.333vw] md:max-xl:w-[120px] w-full"
- maxOptionsCount={7}
- />
-
-
-
- item.floor ===
- parseInt(selectedFloor!.split(" ").at(-1)!),
- )?.others.types["Studio2"] || 0
- }
- />
-
- item.floor ===
- parseInt(selectedFloor!.split(" ").at(-1)!),
- )?.others.types["One Bedroom2"] || 0
- }
- />
-
- item.floor ===
- parseInt(selectedFloor!.split(" ").at(-1)!),
- )?.others.types["One Bedroom Loft"] || 0
- }
- />
-
- item.floor ===
- parseInt(selectedFloor!.split(" ").at(-1)!),
- )?.others.types["Two Bedroom Loft"] || 0
- }
- />
-
-
- {selectedFloor !== "39-40" && selectedFloor !== "41-42" && (
-
- setIsCombinable(false)}
- >
- Standard
-
- setIsCombinable(true)}
- >
- Combinable
-
-
- )}
-
- !isMobile && setPosition({ x: e.clientX, y: e.clientY })
- }
- >
- {selectedFloor && unitsOnFloor && (
- <>
- {+selectedFloor >= 7 && +selectedFloor < 39 && (
- <>
- {!isCombinable ? (
-
- ) : (
-
- )}
- >
- )}
- {selectedFloor === "39-40" && (
-
- )}
- {selectedFloor === "41-42" && (
-
- )}
- >
- )}
-
-
-
- )}
- >
+ {currentFloor && (
+
)}
- {complexName === "marasi-drive" && (
- <>
- {selectedFloor === "Rooftop" &&
}
- {selectedFloor === "Ground Level" &&
}
- {selectedFloor === "Podium Level" &&
}
- {selectedFloor === "Sky Garden" &&
}
- {selectedFloor && !!parseInt(selectedFloor.split(" ").at(-1)!) && (
-
setPopup(null)}
- >
-
-
- {selectedFloor.split(" ").at(-1)} floor
-
-
-
- item.floor ===
- parseInt(selectedFloor.split(" ").at(-1)!),
- )?.East?.totalUnits || 0) +
- (floorsData?.find(
- (item) =>
- item.floor ===
- parseInt(selectedFloor.split(" ").at(-1)!),
- )?.West?.totalUnits || 0)
- } Apartments`}
- />
- {/* */}
-
-
-
-
-
[
- `East ${item.floor}`,
- `West ${item.floor}`,
- ]) || []
- }
- defaultOption={selectedFloor?.toString() || ""}
- onSelect={setSelectedFloor}
- className="2xl:w-[8.333vw] md:max-2xl:w-[120px] w-full"
- maxOptionsCount={7}
- />
-
-
-
- item.floor ===
- parseInt(selectedFloor.split(" ").at(-1)!),
- )?.[selectedFloor.split(" ")[0] as "West" | "East"]
- .types["Studio Flex"] || 0
- }
- />
-
- item.floor ===
- parseInt(selectedFloor.split(" ").at(-1)!),
- )?.[selectedFloor.split(" ")[0] as "West" | "East"]
- .types["Studio Squared"] || 0
- }
- />
-
- item.floor ===
- parseInt(selectedFloor.split(" ").at(-1)!),
- )?.[selectedFloor.split(" ")[0] as "West" | "East"]
- .types["1 BR Squared"] || 0
- }
- />
-
- item.floor ===
- parseInt(selectedFloor.split(" ").at(-1)!),
- )?.[selectedFloor.split(" ")[0] as "West" | "East"]
- .types["2 BR Squared"] || 0
- }
- />
-
-
-
-
- !isMobile && setPosition({ x: e.clientX, y: e.clientY })
- }
- >
- {unitsOnFloor && selectedFloor.split(" ")[0] === "East" && (
-
- )}
- {selectedFloor.split(" ")[0] === "West" && unitsOnFloor && (
- <>
- {+selectedFloor.split(" ")[1] < 24 ? (
-
- ) : (
-
- )}
- >
- )}
-
-
- )}
- >
+ {!currentFloor && complexName === "hq" && <>HQ>}
+ {!currentFloor && selectedFloor && (
+
Floor not found: {selectedFloor}
)}
- {complexName === "hq" && <>HQ>}
);
diff --git a/src/types/Floor.ts b/src/types/Floor.ts
new file mode 100644
index 0000000..0a1b029
--- /dev/null
+++ b/src/types/Floor.ts
@@ -0,0 +1,36 @@
+// Базовый интерфейс для всех этажей
+export interface BaseFloorData {
+ id: string;
+ name: string; // "1", "Rooftop", "Ground Level" и т.д.
+ displayName: string; // "1st Floor", "Rooftop"
+}
+
+// Жилой этаж с квартирами и SVG масками
+export interface ResidentialFloorData extends BaseFloorData {
+ type: 'residential';
+ floorNumber: number;
+ wing?: 'East' | 'West'; // для Marasi Drive
+}
+
+// Этаж с удобствами
+export interface AmenitiesFloorData extends BaseFloorData {
+ type: 'amenities';
+ amenitiesCount: {
+ total: number;
+ indoor?: number;
+ outdoor?: number;
+ };
+ amenitiesList: {
+ icon: string; // название компонента иконки
+ title: string;
+ }[];
+ images: {
+ main: string; // основное изображение (exterior)
+ interior?: string; // для переключения вида
+ content: string[]; // изображения для слайдера/галереи
+ };
+ video?: string; // путь к видео
+}
+
+// Discriminated union
+export type FloorData = ResidentialFloorData | AmenitiesFloorData;
diff --git a/src/types/Project.ts b/src/types/Project.ts
index bd8c510..bc589ca 100644
--- a/src/types/Project.ts
+++ b/src/types/Project.ts
@@ -1,4 +1,5 @@
import UnitType from "./UnitType";
+import { FloorData } from "./Floor";
export default interface Project {
title: string;
@@ -6,12 +7,13 @@ export default interface Project {
img: string;
buildingType: "residential" | "commercial";
types: UnitType[];
- amentiesFloors: AmentiesFloor[];
+ amenitiesFloors: AmenitiesFloor[];
+ floors?: FloorData[]; // New centralized floor data structure
}
-export interface AmentiesFloor {
+export interface AmenitiesFloor {
title: string;
total: number;
indoor?: number;
outdoor?: number;
-}
\ No newline at end of file
+}