Fixes
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/irth.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>Rove Home</title>
|
||||
</head>
|
||||
|
||||
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 836 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 797 KiB |
|
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 849 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 820 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 850 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 856 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 896 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 648 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 600 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 504 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 885 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 951 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 828 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 609 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 633 KiB |
|
After Width: | Height: | Size: 460 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { formattedUnitTypes } from "../data/formattedUnitTypes";
|
||||
import { usePopupStore } from "../stores/usePopupStore";
|
||||
import getAmentiesCount, { AmentiesCount } from "../utils/getAmentiesCount";
|
||||
import { FloorsData } from "./FloorSelect";
|
||||
import ArrowRightIcon from "./icons/ArrowRightIcon";
|
||||
import HumanIcon from "./icons/HumanIcon";
|
||||
@@ -14,89 +16,109 @@ interface FloorPopupProps {
|
||||
|
||||
function FloorPopup({ title, complexName, data, onSelect }: FloorPopupProps) {
|
||||
const { setPopup } = usePopupStore();
|
||||
const [amentiesCount, setAmentiesCount] = useState<AmentiesCount | null>(
|
||||
null
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (Number.isNaN(+title.split(" ").at(-1)!)) {
|
||||
setAmentiesCount(getAmentiesCount(complexName, title));
|
||||
} else {
|
||||
setAmentiesCount(null);
|
||||
}
|
||||
|
||||
return () => setAmentiesCount(null);
|
||||
}, [complexName, title]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(amentiesCount);
|
||||
}, [amentiesCount]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col 2xl:gap-y-[0.556vw] gap-y-2">
|
||||
<div className="flex 2xl:gap-[0.556vw] gap-2">
|
||||
<p className="font-medium text-h5">
|
||||
{Number.isNaN(+title.split(" ").at(-1)!)
|
||||
? title
|
||||
: `${title.split(" ").at(-1)} floor`}
|
||||
{amentiesCount ? title : `${title.split(" ").at(-1)} floor`}
|
||||
</p>
|
||||
{complexName === "marasi-drive" &&
|
||||
!Number.isNaN(+title.split(" ").at(-1)!) && (
|
||||
<p className="text-[#0D1922]/40 text-s">
|
||||
{title.split(" ")[0]} Wing
|
||||
{complexName === "marasi-drive" && !amentiesCount && (
|
||||
<p className="text-[#0D1922]/40 text-s">{title.split(" ")[0]} Wing</p>
|
||||
)}
|
||||
</div>
|
||||
{amentiesCount !== null && (
|
||||
<>
|
||||
<div className="flex 2xl:gap-[0.278vw] gap-1">
|
||||
<p className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#F3F3F2] 2xl:rounded-[0.278vw] rounded text-caption-s text-[#0D1922]/70">
|
||||
{amentiesCount
|
||||
? `${amentiesCount?.total} Amenties`
|
||||
: `${
|
||||
complexName === "marasi-drive"
|
||||
? data[
|
||||
title.split(" ")[0] === "East"
|
||||
? "East"
|
||||
: title.split(" ")[0] === "West"
|
||||
? "West"
|
||||
: "others"
|
||||
].totalUnits
|
||||
: data.others.totalUnits
|
||||
} apartments`}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex 2xl:gap-[0.278vw] gap-1">
|
||||
<p className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#F3F3F2] 2xl:rounded-[0.278vw] rounded text-caption-s text-[#0D1922]/70">
|
||||
{title && Number.isNaN(+title!.split(" ").at(-1)!)
|
||||
? "16 Amen ties"
|
||||
: `${
|
||||
complexName === "marasi-drive"
|
||||
? data[
|
||||
title.split(" ")[0] === "East"
|
||||
? "East"
|
||||
: title.split(" ")[0] === "West"
|
||||
? "West"
|
||||
: "others"
|
||||
].totalUnits
|
||||
: data.others.totalUnits
|
||||
} apartments`}
|
||||
</p>
|
||||
{!Number.isNaN(+title.split(" ").at(-1)!) && (
|
||||
<div className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#30B216]/8 2xl:rounded-[0.278vw] rounded flex 2xl:gap-[0.278vw] gap-1">
|
||||
<span className="2xl:size-[0.833vw] size-3 text-[#30B216]">
|
||||
<HumanIcon />
|
||||
</span>
|
||||
<p className="text-caption-s text-[#30B216]">Virtual Tour</p>
|
||||
{!amentiesCount && (
|
||||
<div className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#30B216]/8 2xl:rounded-[0.278vw] rounded flex 2xl:gap-[0.278vw] gap-1">
|
||||
<span className="2xl:size-[0.833vw] size-3 text-[#30B216]">
|
||||
<HumanIcon />
|
||||
</span>
|
||||
<p className="text-caption-s text-[#30B216]">Virtual Tour</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<hr className="border-[#E2E2DC] 2xl:h-[0.069vw] h-px" />
|
||||
<div className="2xl:space-y-[0.556vw] space-y-2">
|
||||
{!Number.isNaN(+title.split(" ").at(-1)!) ? (
|
||||
Object.entries(
|
||||
data[
|
||||
title.split(" ")[0] === "East"
|
||||
? "East"
|
||||
: title.split(" ")[0] === "West"
|
||||
? "West"
|
||||
: "others"
|
||||
].types
|
||||
).map(([unitType, count]) => (
|
||||
<div className="flex 2xl:gap-[0.556vw] gap-2" key={unitType}>
|
||||
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
|
||||
{count}
|
||||
</p>
|
||||
<p className="text-caption-m text-[#0D1922]/70">
|
||||
{formattedUnitTypes.get(unitType)}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<>
|
||||
<div className="flex 2xl:gap-[0.556vw] gap-2">
|
||||
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
|
||||
8
|
||||
</p>
|
||||
<p className="text-caption-m text-[#0D1922]/70">
|
||||
Indoor Amenties
|
||||
</p >
|
||||
</div>
|
||||
<div className="flex 2xl:gap-[0.556vw] gap-2">
|
||||
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
|
||||
8
|
||||
</p>
|
||||
<p className="text-caption-m text-[#0D1922]/70">
|
||||
Outdoor Amenties
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<hr className="border-[#E2E2DC] 2xl:h-[0.069vw] h-px" />
|
||||
<div className="2xl:space-y-[0.556vw] space-y-2">
|
||||
{!amentiesCount ? (
|
||||
Object.entries(
|
||||
data[
|
||||
title.split(" ")[0] === "East"
|
||||
? "East"
|
||||
: title.split(" ")[0] === "West"
|
||||
? "West"
|
||||
: "others"
|
||||
].types
|
||||
).map(([unitType, count]) => (
|
||||
<div className="flex 2xl:gap-[0.556vw] gap-2" key={unitType}>
|
||||
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
|
||||
{count}
|
||||
</p>
|
||||
<p className="text-caption-m text-[#0D1922]/70">
|
||||
{formattedUnitTypes.get(unitType)}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<>
|
||||
{amentiesCount?.indoor && (
|
||||
<div className="flex 2xl:gap-[0.556vw] gap-2">
|
||||
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
|
||||
{amentiesCount.indoor}
|
||||
</p>
|
||||
<p className="text-caption-m text-[#0D1922]/70">
|
||||
Indoor Amenties
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{amentiesCount?.outdoor && (
|
||||
<div className="flex 2xl:gap-[0.556vw] gap-2">
|
||||
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
|
||||
{amentiesCount.outdoor}
|
||||
</p>
|
||||
<p className="text-caption-m text-[#0D1922]/70">
|
||||
Outdoor Amenties
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
variant="cta"
|
||||
size="small"
|
||||
|
||||
@@ -73,7 +73,7 @@ function UnitCard({ unit }: { unit: Unit }) {
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="2xl:rounded-[0.556vw] rounded-xl 2xl:p-[0.556vw] p-2 bg-[#F3F3F2] overflow-hidden mx-auto">
|
||||
<div className="2xl:rounded-[0.556vw] rounded-xl 2xl:p-[0.556vw] p-2 overflow-hidden mx-auto">
|
||||
<img
|
||||
src={`/images/unit-types/${complexSlug}/${getUnitTypeSlug(
|
||||
complexSlug,
|
||||
@@ -91,14 +91,14 @@ function UnitCard({ unit }: { unit: Unit }) {
|
||||
maximumFractionDigits: 2,
|
||||
})} Sqft`}
|
||||
</p>
|
||||
{(
|
||||
{
|
||||
<p className="text-[#00BED7] text-h4 font-medium">
|
||||
{`AED ${Intl.NumberFormat("ar-AE", {
|
||||
currency: "AED",
|
||||
minimumFractionDigits: 0,
|
||||
}).format(unit.salesPrice)}`}
|
||||
</p>
|
||||
)}
|
||||
}
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
|
||||
@@ -21,7 +21,7 @@ function UnitTypeCard({ project, type }: { project: Project; type: UnitType }) {
|
||||
<p className="text-caption-m text-[#0D1922]/70">{type.floors}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="2xl:p-[1.111vw] 2xl:rounded-[0.556vw] bg-[#F3F3F2]">
|
||||
<div className="2xl:p-[1.111vw] 2xl:rounded-[0.556vw]">
|
||||
<img
|
||||
src={`/images/unit-types/${project.slug}/${type.slug}.jpg`}
|
||||
alt=""
|
||||
|
||||
@@ -13,12 +13,14 @@ function Select({
|
||||
className = "",
|
||||
label = "",
|
||||
defaultOption = "",
|
||||
maxOptionsCount,
|
||||
}: {
|
||||
options: string[];
|
||||
onSelect: (option: string) => void;
|
||||
defaultOption: string;
|
||||
className?: string;
|
||||
label?: string;
|
||||
maxOptionsCount?: number;
|
||||
}) {
|
||||
const [isShow, setIsShow] = useState(false);
|
||||
const [selectedOption, setSelectedOption] = useState(defaultOption);
|
||||
@@ -32,18 +34,39 @@ function Select({
|
||||
useEffect(() => onSelect(selectedOption), [selectedOption]);
|
||||
|
||||
function handleScroll() {
|
||||
if (dropDownRef.current)
|
||||
dropDownRef.current.style.maxHeight = `calc(100vh - ${
|
||||
dropDownRef.current?.getBoundingClientRect().y
|
||||
}px - 0.278vw)`;
|
||||
if (!dropDownRef.current) return;
|
||||
dropDownRef.current.style.maxHeight = `calc(100vh - ${
|
||||
dropDownRef.current?.getBoundingClientRect().y
|
||||
}px - 0.278vw)`;
|
||||
}
|
||||
|
||||
function dropdownRefCallback(el: HTMLDivElement) {
|
||||
if (!el) return;
|
||||
|
||||
dropDownRef.current = el;
|
||||
|
||||
if (!maxOptionsCount) return;
|
||||
|
||||
const optionHeight = el.clientHeight / options.length;
|
||||
|
||||
el.style.maxHeight = `${optionHeight * maxOptionsCount}px`;
|
||||
|
||||
const scrollOffset =
|
||||
(options.findIndex((option) => option === selectedOption) -
|
||||
Math.floor(maxOptionsCount / 2)) *
|
||||
optionHeight;
|
||||
|
||||
el.scrollTo({ top: scrollOffset });
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (maxOptionsCount) return;
|
||||
|
||||
handleScroll();
|
||||
document.addEventListener("scroll", handleScroll);
|
||||
|
||||
return () => document.removeEventListener("scroll", handleScroll);
|
||||
}, [isShow]);
|
||||
}, [isShow, maxOptionsCount]);
|
||||
|
||||
return (
|
||||
<div ref={ref} className={clsx("relative", className)}>
|
||||
@@ -74,7 +97,7 @@ function Select({
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
ref={dropDownRef}
|
||||
ref={dropdownRefCallback}
|
||||
className="absolute 2xl:mt-[0.278vw] 2xl:pt-[0.278vw] mt-1 p-1 2xl:space-y-[0.139vw] space-y-0.5 shadow-[0px_2px_8px_rgba(0,0,0,0.15)] overflow-auto rounded-xl bg-white w-full z-1"
|
||||
>
|
||||
{options.map((option, index) => (
|
||||
|
||||
@@ -45,9 +45,7 @@ function FloorsPage() {
|
||||
});
|
||||
|
||||
const { data: unitsOnFloor } = useQuery({
|
||||
enabled:
|
||||
!!selectedFloor &&
|
||||
!SPECIAL_FLOORS.includes(selectedFloor),
|
||||
enabled: !!selectedFloor && !SPECIAL_FLOORS.includes(selectedFloor),
|
||||
queryKey: ["units-on-floor", complexName, selectedFloor],
|
||||
queryFn: () =>
|
||||
api
|
||||
@@ -110,6 +108,7 @@ function FloorsPage() {
|
||||
defaultOption={selectedFloor?.toString() || ""}
|
||||
onSelect={setSelectedFloor}
|
||||
className="2xl:w-[8.333vw] md:max-xl:w-[120px] w-full"
|
||||
maxOptionsCount={7}
|
||||
/>
|
||||
<div className="bg-[#E2E2DC] w-px 2xl:h-[1.667vw] h-1.5"></div>
|
||||
<div className="flex items-center 2xl:gap-[1.667vw] gap-2 max-md:hidden">
|
||||
@@ -156,12 +155,11 @@ function FloorsPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="2xl:p-[4.444vw] p-4 bg-[#F3F3F2] 2xl:rounded-[0.833vw] rounded-lg relative 2xl:space-y-[2.222vw] space-y-8"
|
||||
className="2xl:py-[1.667vw] 2xl:px-[1.111vw] max:2xl:p-4 bg-[#F3F3F2] 2xl:rounded-[0.833vw] rounded-lg relative 2xl:space-y-[2.222vw] space-y-8"
|
||||
onMouseMove={(e) =>
|
||||
!isMobile && setPosition({ x: e.clientX, y: e.clientY })
|
||||
}
|
||||
>
|
||||
|
||||
{selectedFloor && unitsOnFloor && (
|
||||
<>
|
||||
{+selectedFloor >= 7 && +selectedFloor < 39 && (
|
||||
@@ -236,6 +234,7 @@ function FloorsPage() {
|
||||
defaultOption={selectedFloor?.toString() || ""}
|
||||
onSelect={setSelectedFloor}
|
||||
className="2xl:w-[8.333vw] md:max-2xl:w-[120px] w-full"
|
||||
maxOptionsCount={7}
|
||||
/>
|
||||
<div className="bg-[#E2E2DC] w-px 2xl:h-[1.667vw] h-1.5"></div>
|
||||
<div className="flex items-center 2xl:gap-[1.667vw] gap-2 max-md:hidden">
|
||||
|
||||
@@ -14,6 +14,7 @@ import { projects } from "../data/projects";
|
||||
import { useEffect, useState } from "react";
|
||||
import UnitTypeImageWithMarkers from "../components/UnitTypeImageWithMarkers";
|
||||
import { getUnitTypeVariantMarasiDrive } from "../utils/getUnitTypeVariantMarasiDrive";
|
||||
import { formattedUnitTypes } from "../data/formattedUnitTypes";
|
||||
// import { useEffect } from "react";
|
||||
// import PlayIcon from "../components/icons/PlayIcon";
|
||||
// import { useRef } from "react";
|
||||
@@ -81,24 +82,29 @@ function UnitPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="2xl:p-[2.222vw] md:max-2xl:p-6 p-4 max-2xl:pb-0 bg-white flex 2xl:gap-[2.222vw] md:max-2xl:gap-8 gap-6 max-2xl:flex-col">
|
||||
<div className="relative 2xl:w-full flex flex-col items-center justify-center bg-[#F3F3F2] 2xl:rounded-[1.111vw] rounded-xl 2xl:p-[2.222vw] p-6 2xl:gap-[1.111vw] gap-4">
|
||||
<UnitTypeImageWithMarkers
|
||||
complexName={params.complexName!}
|
||||
unitType={getUnitTypeSlug(params.complexName!, unit.unitType)}
|
||||
floor={selectedFloor}
|
||||
legend={
|
||||
projects
|
||||
.find((project) => project.slug === params.complexName)
|
||||
?.types.find(
|
||||
(type) =>
|
||||
type.slug ===
|
||||
getUnitTypeSlug(params.complexName!, unit.unitType)
|
||||
)?.legend || []
|
||||
}
|
||||
/>
|
||||
<html>
|
||||
<head>
|
||||
<title>{formattedUnitTypes.get(unit.unitType)}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div className="2xl:p-[2.222vw] md:max-2xl:p-6 p-4 max-2xl:pb-0 bg-white flex 2xl:gap-[2.222vw] md:max-2xl:gap-8 gap-6 max-2xl:flex-col">
|
||||
<div className="relative 2xl:w-full flex flex-col items-center justify-center bg-[#F3F3F2] 2xl:rounded-[1.111vw] rounded-xl 2xl:p-[2.222vw] p-6 2xl:gap-[1.111vw] gap-4">
|
||||
<UnitTypeImageWithMarkers
|
||||
complexName={params.complexName!}
|
||||
unitType={getUnitTypeSlug(params.complexName!, unit.unitType)}
|
||||
floor={selectedFloor}
|
||||
legend={
|
||||
projects
|
||||
.find((project) => project.slug === params.complexName)
|
||||
?.types.find(
|
||||
(type) =>
|
||||
type.slug ===
|
||||
getUnitTypeSlug(params.complexName!, unit.unitType)
|
||||
)?.legend || []
|
||||
}
|
||||
/>
|
||||
|
||||
{/* <img
|
||||
{/* <img
|
||||
src={`/images/unit-types/${params.complexName}/${getUnitTypeSlug(
|
||||
params.complexName!,
|
||||
unit.unitType
|
||||
@@ -114,66 +120,68 @@ function UnitPage() {
|
||||
alt=""
|
||||
className="2xl:w-[40.625vw] 2xl:h-[37.778vw] object-cover 2xl:hidden block"
|
||||
/> */}
|
||||
{getUnitTypeSlug(params.complexName!, unit.unitType).includes(
|
||||
"loft"
|
||||
) && (
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant={selectedFloor === "lower" ? "cta" : "secondary"}
|
||||
onClick={() => setSelectedFloor("lower")}
|
||||
>
|
||||
Lower
|
||||
</Button>
|
||||
<Button
|
||||
variant={selectedFloor === "upper" ? "cta" : "secondary"}
|
||||
onClick={() => setSelectedFloor("upper")}
|
||||
>
|
||||
Upper
|
||||
</Button>
|
||||
{getUnitTypeSlug(params.complexName!, unit.unitType).includes(
|
||||
"loft"
|
||||
) && (
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant={selectedFloor === "lower" ? "cta" : "secondary"}
|
||||
onClick={() => setSelectedFloor("lower")}
|
||||
>
|
||||
Lower
|
||||
</Button>
|
||||
<Button
|
||||
variant={selectedFloor === "upper" ? "cta" : "secondary"}
|
||||
onClick={() => setSelectedFloor("upper")}
|
||||
>
|
||||
Upper
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col justify-between md:max-2xl:gap-6 gap-4 2xl:w-[21.944vw] flex-shrink-0">
|
||||
<div className="2xl:space-y-[1.667vw] space-y-6">
|
||||
<div className="flex justify-between items-start">
|
||||
<div className="2xl:space-y-[1.111vw] space-y-4">
|
||||
<h3 className="text-h3 font-medium">{unit.unitType}</h3>
|
||||
<div className="2xl:space-y-[0.556vw] space-y-2">
|
||||
<p className="text-s text-[#00BED7]">{unit.project}</p>
|
||||
<div className="flex items-center 2xl:gap-[0.556vw]">
|
||||
{unit.wing && (
|
||||
<>
|
||||
<p className="text-s opacity-70">{unit.wing}</p>
|
||||
<div className="flex flex-col justify-between md:max-2xl:gap-6 gap-4 2xl:w-[21.944vw] flex-shrink-0">
|
||||
<div className="2xl:space-y-[1.667vw] space-y-6">
|
||||
<div className="flex justify-between items-start">
|
||||
<div className="2xl:space-y-[1.111vw] space-y-4">
|
||||
<h3 className="text-h3 font-medium">
|
||||
{formattedUnitTypes.get(unit.unitType)}
|
||||
</h3>
|
||||
<div className="2xl:space-y-[0.556vw] space-y-2">
|
||||
<p className="text-s text-[#00BED7]">{unit.project}</p>
|
||||
<div className="flex items-center 2xl:gap-[0.556vw]">
|
||||
{unit.wing && (
|
||||
<>
|
||||
<p className="text-s opacity-70">{unit.wing}</p>
|
||||
<div className="2xl:w-[0.278vw] 2xl:h-[0.278vw] w-1 h-1 rounded-full bg-[#E2E2DC]" />
|
||||
</>
|
||||
)}
|
||||
<p className="text-s opacity-70">Floor {unit.floor}</p>
|
||||
<div className="2xl:w-[0.278vw] 2xl:h-[0.278vw] w-1 h-1 rounded-full bg-[#E2E2DC]" />
|
||||
</>
|
||||
)}
|
||||
<p className="text-s opacity-70">Floor {unit.floor}</p>
|
||||
<div className="2xl:w-[0.278vw] 2xl:h-[0.278vw] w-1 h-1 rounded-full bg-[#E2E2DC]" />
|
||||
<p className="text-s opacity-70">{unit.unitNo}</p>
|
||||
<p className="text-s opacity-70">{unit.unitNo}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="tertiary" onlyIcon onClick={handleFavorite}>
|
||||
<span className="2xl:size-[1.389vw] size-5">
|
||||
{favoriteUnits.some(
|
||||
(favoriteUnit) => favoriteUnit.id === unit.id
|
||||
) ? (
|
||||
<FilledHeartIcon />
|
||||
) : (
|
||||
<HeartIcon />
|
||||
)}
|
||||
</span>
|
||||
</Button>
|
||||
<Button variant="tertiary" onlyIcon onClick={handleShare}>
|
||||
<span className="2xl:size-[1.389vw] size-5">
|
||||
<ShareIcon />
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Button variant="tertiary" onlyIcon onClick={handleFavorite}>
|
||||
<span className="2xl:size-[1.389vw] size-5">
|
||||
{favoriteUnits.some(
|
||||
(favoriteUnit) => favoriteUnit.id === unit.id
|
||||
) ? (
|
||||
<FilledHeartIcon />
|
||||
) : (
|
||||
<HeartIcon />
|
||||
)}
|
||||
</span>
|
||||
</Button>
|
||||
<Button variant="tertiary" onlyIcon onClick={handleShare}>
|
||||
<span className="2xl:size-[1.389vw] size-5">
|
||||
<ShareIcon />
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="w-full border-[#E2E2DC] 2xl:h-[0.069vw] h-px" />
|
||||
{/* <div
|
||||
<hr className="w-full border-[#E2E2DC] 2xl:h-[0.069vw] h-px" />
|
||||
{/* <div
|
||||
className="2xl:p-[1.111vw] p-4 2xl:rounded-[0.883vw] rounded-xl flex items-center justify-between 2xl:gap-[0.556vw] gap-2 2xl:ring-[0.069vw] ring ring-[#E2E2DC] cursor-pointer"
|
||||
onClick={() => videoButtonRef && videoButtonRef.current?.click()}
|
||||
>
|
||||
@@ -187,62 +195,64 @@ function UnitPage() {
|
||||
</div>
|
||||
</Button>
|
||||
</div> */}
|
||||
<div className="flex flex-col 2xl:gap-y-[0.556vw]">
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Total Area</p>
|
||||
<p className="text-s">{unit.squareFt.toFixed(2)} Sqft</p>
|
||||
<div className="flex flex-col 2xl:gap-y-[0.556vw]">
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Total Area</p>
|
||||
<p className="text-s">{unit.squareFt.toFixed(2)} Sqft</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Suite Area</p>
|
||||
<p className="text-s">{unit.suitsArea.toFixed(2)} Sqft</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Balcony Area</p>
|
||||
<p className="text-s">{unit.balconyArea.toFixed(2)} Sqft</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Status</p>
|
||||
<p className="text-s">
|
||||
{unit.state.charAt(0).toUpperCase() +
|
||||
unit.state.slice(1).replace(/_/g, " ")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Parking Space</p>
|
||||
<p className="text-s">{unit.noOfParkingSpace}</p>
|
||||
</div>
|
||||
</div>
|
||||
{!unit.project.includes("Marasi Drive") && (
|
||||
<p className="text-h4 font-medium text-[#00BED7]">{`AED ${Intl.NumberFormat(
|
||||
"ar-AE",
|
||||
{
|
||||
currency: "AED",
|
||||
minimumFractionDigits: 0,
|
||||
}
|
||||
).format(unit.salesPrice)}`}</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Suite Area</p>
|
||||
<p className="text-s">{unit.suitsArea.toFixed(2)} Sqft</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Balcony Area</p>
|
||||
<p className="text-s">{unit.balconyArea.toFixed(2)} Sqft</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Status</p>
|
||||
<p className="text-s">
|
||||
{unit.state.charAt(0).toUpperCase() +
|
||||
unit.state.slice(1).replace(/_/g, " ")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<p className="text-s opacity-70">Parking Space</p>
|
||||
<p className="text-s">{unit.noOfParkingSpace}</p>
|
||||
<div className="flex 2xl:flex-col 2xl:gap-[0.556vw] gap-2 2xl:bottom-[2.222vw] bottom-0 bg-white md:max-2xl:-mx-[3.125vw] md:max-2xl:p-[3.125vw] max-md:-mx-4 max-md:p-4 max-2xl:rounded-t-2xl max-2xl:shadow-[0_-4px_20px_0_rgba(0,0,0,0.05)]">
|
||||
<Button
|
||||
disabled={!unitTypeVariantMarasiDrive}
|
||||
variant="cta"
|
||||
size="large"
|
||||
// className="!bg-[#F3F3F2] !text-[#0D1922]"
|
||||
onClick={() => {
|
||||
window.open(
|
||||
`/virtual-tour/${params.complexName}/${unitTypeVariantMarasiDrive}`,
|
||||
"_blank"
|
||||
);
|
||||
}}
|
||||
>
|
||||
Virtual tour
|
||||
</Button>
|
||||
<Button disabled variant="cta" size="large">
|
||||
Book
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{!unit.project.includes("Marasi Drive") && (
|
||||
<p className="text-h4 font-medium text-[#00BED7]">{`AED ${Intl.NumberFormat(
|
||||
"ar-AE",
|
||||
{
|
||||
currency: "AED",
|
||||
minimumFractionDigits: 0,
|
||||
}
|
||||
).format(unit.salesPrice)}`}</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex 2xl:flex-col 2xl:gap-[0.556vw] gap-2 2xl:bottom-[2.222vw] bottom-0 bg-white md:max-2xl:-mx-[3.125vw] md:max-2xl:p-[3.125vw] max-md:-mx-4 max-md:p-4 max-2xl:rounded-t-2xl max-2xl:shadow-[0_-4px_20px_0_rgba(0,0,0,0.05)]">
|
||||
<Button
|
||||
disabled={!unitTypeVariantMarasiDrive}
|
||||
variant="cta"
|
||||
size="large"
|
||||
// className="!bg-[#F3F3F2] !text-[#0D1922]"
|
||||
onClick={() => {
|
||||
window.open(
|
||||
`/virtual-tour/${params.complexName}/${unitTypeVariantMarasiDrive}`,
|
||||
"_blank"
|
||||
);
|
||||
}}
|
||||
>
|
||||
Virtual tour
|
||||
</Button>
|
||||
<Button disabled variant="cta" size="large">
|
||||
Book
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
export interface AmentiesCount {
|
||||
total: number;
|
||||
indoor?: number;
|
||||
outdoor?: number;
|
||||
}
|
||||
|
||||
export default function getAmentiesCount(
|
||||
complexName: string,
|
||||
floorTitle: string
|
||||
):AmentiesCount | null {
|
||||
const dict = new Map<string, AmentiesCount>([
|
||||
["marasi-drive Rooftop", { total: 10 }],
|
||||
["marasi-drive Sky Garden", { total: 15, indoor: 3, outdoor: 12 }],
|
||||
["marasi-drive Podium Level", { total: 27, indoor: 13, outdoor: 14 }],
|
||||
["marasi-drive Ground Level", { total: 7 }],
|
||||
["dubai-marina Rooftop", { total: 14 }],
|
||||
["dubai-marina Podium Level", { total: 21, indoor: 8, outdoor: 13 }],
|
||||
["dubai-marina Ground Level", { total: 14 }],
|
||||
]);
|
||||
|
||||
return dict.get(`${complexName} ${floorTitle}`) || null;
|
||||
}
|
||||