This commit is contained in:
2024-07-17 20:36:28 +05:00
parent 871f2d961e
commit 0a5d0a66f0
61 changed files with 4706 additions and 1148 deletions
+2
View File
@@ -16,6 +16,7 @@
"@uidotdev/usehooks": "^2.4.1",
"gsap": "^3.12.5",
"ky": "^1.3.0",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-device-detect": "^2.2.3",
"react-dom": "^18.2.0",
@@ -31,6 +32,7 @@
"zustand": "^4.5.2"
},
"devDependencies": {
"@types/lodash": "^4.17.7",
"@types/node": "^20.14.8",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 KiB

Binary file not shown.
@@ -0,0 +1,37 @@
interface Props {
desc: string;
imageSrc: string;
onClick: () => void;
}
function UnitTypeCard({ desc, imageSrc, onClick }: Props) {
return (
<div
className="card space-y-6 bg-white p-4 rounded-2xl cursor-pointer select-none"
onClick={onClick}
>
<div className="flex items-start justify-between">
<div className="space-y-1">
<p className="text-sm text-[#00BED7]">Rove Home Marasi Drive</p>
<div className="text-xs font-semibold flex items-center gap-2">
<p>East Wing</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p>Floor 11-35</p>
</div>
</div>
{/* <div className="text-white bg-[#00BED7] text-xs font-semibold px-2 py-[3px] rounded-full">
234 units
</div> */}
</div>
<div className="flex justify-center">
<img src={imageSrc} alt="" className="h-[294px] pointer-events-none" />
</div>
<div className="space-y-1">
<p className="text-sm">{desc}</p>
{/* <p className="text-xl text-[#00BED7] font-semibold">Unavailable</p> */}
</div>
</div>
);
}
export default UnitTypeCard;
File diff suppressed because one or more lines are too long
@@ -1,10 +1,10 @@
import { useState, useEffect, useRef } from "react";
import { IDesctiptionFloor } from "../../../types/descriptionFloor";
import ApartmentDescription from "./ApartmentDescription";
import EastWingHighlighting from "./EastWingHighlighting";
import EastWingLayout from "./EastWingLayout";
import WestWingHighlighting from "./WestWingHighlighting";
import WestWingLayout from "./WestWingLayout";
// import EastWingHighlighting from "./EastWingHighlighting";
// import EastWingLayout from "./EastWingLayout";
// import WestWingHighlighting from "./WestWingHighlighting";
// import WestWingLayout from "./WestWingLayout";
import useModal from "../../../store/useModal";
import AboutComplexModal from "../../modals/AboutComplexModal";
import { IAparmentRes } from "../../../types/apartmentsRes";
@@ -13,6 +13,11 @@ import { IAparmentRes } from "../../../types/apartmentsRes";
import { apartmentsWithoutVirtualTour } from "../../../consts/apartmentsWithoutVirtualTour";
import { filterCurrentApartment } from "../../../calc/filterCurrentApartment";
import WestWingFloorLayout from "./WestWingFloorLayout";
import WestWingBottomFloorLayout from "./WestWingBottomFloorLayout";
import EastWingFloorLayout from "./EastWingFloorLayout";
import Button from "../../Button";
import CloseIcon from "../../icons/CloseIcon";
import useWingSidebar from "../../../store/useWingSidebar";
interface IFloorSidebarProps {
currentFloor: IDesctiptionFloor | null;
@@ -36,6 +41,7 @@ const FloorSidebar = ({
const [apartments, setApartments] = useState<IAparmentRes[]>([]);
const { setModal } = useModal();
const descRef = useRef(null);
const { setIsSidebar } = useWingSidebar();
function handleMouseMove(e: MouseEvent) {
const y = e.clientY - 80;
@@ -148,52 +154,64 @@ const FloorSidebar = ({
</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">{floorApartments.length} units</div>
</div>
<Button
buttonType="cta"
icon={<CloseIcon />}
onClick={() => setIsSidebar(false)}
/>
</div>
<div className="px-4 py-[18px] bg-white flex gap-6 text-[#73787C] font-semibold text-caption-m rounded-2xl 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 className="px-4 py-[18px] bg-white flex justify-between text-[#73787C] font-semibold text-caption-m rounded-2xl mb-2">
<div className="flex gap-6">
<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="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 className="bg-[#00BED7] text-white text-s px-2 py-[3px] rounded-3xl flex h-fit">
{floorApartments.length} units
</div>
</div>
<svg className="flex-1 px-10 bg-white font-semibold text-caption-m rounded-2xl py-4">
{currentFloor?.wing === "West Wing" ? (
currentFloor && currentFloor.floor <= 21 ? (
<svg
className="rotate-[135deg]"
xmlns="http://www.w3.org/2000/svg"
width="400"
height="700"
fill="none"
viewBox="0 0 204 600"
>
<WestWingLayout />
<WestWingHighlighting
handleOnApartmentClick={handleOnApartmentClick}
handleOnMouseOut={handleOnMouseOut}
handleOnMouseOver={handleOnMouseOver}
/>
</svg>
// <svg
// className="rotate-[135deg]"
// xmlns="http://www.w3.org/2000/svg"
// width="400"
// height="700"
// fill="none"
// viewBox="0 0 204 600"
// >
// <WestWingLayout />
// <WestWingHighlighting
// handleOnApartmentClick={handleOnApartmentClick}
// handleOnMouseOut={handleOnMouseOut}
// handleOnMouseOver={handleOnMouseOver}
// />
// </svg>
<WestWingBottomFloorLayout
handleMouseEnter={handleOnMouseOver}
handleMouseLeave={handleOnMouseOut}
handleClick={handleOnApartmentClick}
/>
) : (
// <svg
// className="rotate-[135deg]"
@@ -219,21 +237,26 @@ const FloorSidebar = ({
</>
)
) : (
<svg
className="rotate-[135deg]"
xmlns="http://www.w3.org/2000/svg"
fill="none"
width="672"
height="280"
viewBox="0 0 672 280"
>
<EastWingLayout />
<EastWingHighlighting
handleOnApartmentClick={handleOnApartmentClick}
handleOnMouseOut={handleOnMouseOut}
handleOnMouseOver={handleOnMouseOver}
/>
</svg>
// <svg
// className="rotate-[135deg]"
// xmlns="http://www.w3.org/2000/svg"
// fill="none"
// width="672"
// height="280"
// viewBox="0 0 672 280"
// >
// <EastWingLayout />
// <EastWingHighlighting
// handleOnApartmentClick={handleOnApartmentClick}
// handleOnMouseOut={handleOnMouseOut}
// handleOnMouseOver={handleOnMouseOver}
// />
// </svg>
<EastWingFloorLayout
handleMouseEnter={handleOnMouseOver}
handleMouseLeave={handleOnMouseOut}
handleClick={handleOnApartmentClick}
/>
)}
{/* {currentFloor?.wing === "West Wing" ? (
<svg
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -236,7 +236,7 @@ function WestWingHighlighting({
/>
</svg>
<svg
data-type="2 BR Squared-B"
data-type="2 BR Squared-B Left"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
@@ -354,7 +354,7 @@ function WestWingTopLevelsHighlighting({
/>
</svg>
<svg
data-type="2 BR Squared-B"
data-type="2 BR Squared-B Left"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
@@ -5,14 +5,20 @@ interface ActivityCardProps {
const ActivityCard = ({ icon, title }: ActivityCardProps) => {
return (
<div className="bg-white rounded-2xl flex flex-col gap-9 p-3">
<div className="flex gap-2 items-center">
<div className="w-3 h-3 bg-[#E2E2DC] rounded-full"></div>
<p className="text-m text-[#0D1922]">{title}</p>
</div>
<div className="w-14 h-14 rounded-lg bg-[#F3F3F2] self-end text-[#00BED7]">
// <div className="bg-white rounded-2xl flex flex-col gap-9 p-3">
// <div className="flex gap-2 items-center">
// <div className="w-3 h-3 bg-[#E2E2DC] rounded-full"></div>
// <p className="text-m text-[#0D1922]">{title}</p>
// </div>
// <div className="w-14 h-14 rounded-lg bg-[#F3F3F2] self-end text-[#00BED7]">
// {icon}
// </div>
// </div>
<div className="bg-white rounded-lg p-3 flex items-center gap-4">
<div className="w-10 h-10 rounded-full bg-[#F3F3F2] text-[#00BED7] overflow-hidden">
{icon}
</div>
<p className="text-sm">{title}</p>
</div>
);
};
@@ -21,11 +21,6 @@ const LayoutSlider = () => {
return (
<div className="flex flex-col items-center">
<SwitchToggle
labels={skygardenLayouts}
currentLabel={currentLabel}
onClick={handleOnSwitchClick}
/>
<div className="flex w-full overflow-x-hidden max-w-[1100px] mx-auto overflow-hidden select-none pt-6">
<div
className="flex w-full transition-all duration-300"
@@ -47,6 +42,11 @@ const LayoutSlider = () => {
</div>
</div>
</div>
<SwitchToggle
labels={skygardenLayouts}
currentLabel={currentLabel}
onClick={handleOnSwitchClick}
/>
</div>
);
};
@@ -19,12 +19,18 @@ import WellnessFeaturesIcon from "../../icons/activities/WellnessFeaturesIcon";
import ActivityCard from "./ActivityCard";
import ZoneSlider from "./ZoneSlider";
import LayoutSlider from "./LayoutSlider";
import Button from "../../Button";
import VideoIcon from "../../icons/VideoIcon";
import useModal from "../../../store/useModal";
import VirtualTourVideoModal from "../../modals/VirtualTourVideoModal";
interface ISkygardenSidebarProps {
onMouseEnter: () => void;
}
const SkygardenSidebar = ({ onMouseEnter }: ISkygardenSidebarProps) => {
const { setModal } = useModal();
return (
<div
className="absolute h-full right-0 w-full z-30 bg-[#F3F3F2] py-6 flex flex-col top-[56px]"
@@ -41,63 +47,79 @@ const SkygardenSidebar = ({ onMouseEnter }: ISkygardenSidebarProps) => {
<div className="leading-5">17 amenties</div>
</div>
</div>
<div className="overflow-y-scroll py-6">
<div className="px-4 bg-white font-semibold text-caption-m rounded-2xl justify-center items-center mb-4 pb-4 mx-6 flex flex-col gap-1 pt-4">
<div className="overflow-y-scroll py-6 space-y-8">
<div className="relative px-4 bg-white font-semibold text-caption-m rounded-2xl justify-center items-center mb-4 pb-4 mx-6 flex flex-col gap-1 pt-4">
<LayoutSlider />
<Button
buttonType="secondary"
icon={<VideoIcon />}
text="Sky Garden"
className="absolute top-6 right-6 px-3.5 py-2.5"
onClick={() => setModal(<VirtualTourVideoModal videoHref="/videos/SkyGarden.mp4" />)}
/>
</div>
<div className="grid grid-cols-3 gap-4 border-t pt-4 pb-4 mx-6">
<div className="font-semibold text-subheadline-s">
Indoor Amenties
<div className="px-6 space-y-4">
<p className="text-xl font-semibold">Indoor Amenties</p>
<div className="grid grid-cols-3 gap-4">
<ActivityCard
title={"Indoor Lap Pool"}
icon={<IndoorLapPoolIcon />}
/>
<ActivityCard
title={"Wellness Features"}
icon={<WellnessFeaturesIcon />}
/>
<ActivityCard
title={"Changing Rooms"}
icon={<ChangingRoomsIcon />}
/>
</div>
<ActivityCard
title={"Indoor Lap Pool"}
icon={<IndoorLapPoolIcon />}
/>
<ActivityCard
title={"Wellness Features"}
icon={<WellnessFeaturesIcon />}
/>
<ActivityCard title={"Changing Rooms"} icon={<ChangingRoomsIcon />} />
</div>
<div className="grid grid-cols-3 gap-4 border-t py-4 border-b mb-4 mx-6">
<div className="font-semibold text-subheadline-s">
Outdoor Amenties
<div className="px-6 space-y-4">
<p className="text-xl font-semibold">Outdoor Amenties</p>
<div className="grid grid-cols-3 gap-4">
<ActivityCard title={"Padel Pong"} icon={<PadelPongIcon />} />
<ActivityCard
title={"Sun Lounging Deck"}
icon={<SunLoungingDeckIcon />}
/>
<ActivityCard
title={"Outdoor Cinema"}
icon={<OutdoorCinemaIcon />}
/>
<ActivityCard
title={"Bouldering Wall"}
icon={<BoulderingWallIcon />}
/>
<ActivityCard
title={"Ping Pong in a Tube"}
icon={<PingPongInATableIcon />}
/>
<ActivityCard title={"Amphitheatre"} icon={<AmphitheatreIcon />} />
<ActivityCard
title={"Communal Dining Tables"}
icon={<CommunalDiningTablesIcon />}
/>
<ActivityCard
title={"Suspended Lounging Nets "}
icon={<SuspendedLoungingNetsIcon />}
/>
<ActivityCard
title={"Lush Landscape"}
icon={<LushLandscapeIcon />}
/>
<ActivityCard title={"Running Wheel"} icon={<RunningWheelIcon />} />
<ActivityCard title={"Chess Tables"} icon={<ChessTablesIcon />} />
<ActivityCard title={"Climbing Wall"} icon={<ClimbingRoomIcon />} />
<ActivityCard
title={"Outdoor Coworking Space"}
icon={<OutdoorCoworkingSpaceIcon />}
/>
<ActivityCard
title={"Multi-purpose Court"}
icon={<MultiPurposeCourtIcon />}
/>
</div>
<ActivityCard title={"Padel Pong"} icon={<PadelPongIcon />} />
<ActivityCard
title={"Sun Lounging Deck"}
icon={<SunLoungingDeckIcon />}
/>
<ActivityCard title={"Outdoor Cinema"} icon={<OutdoorCinemaIcon />} />
<ActivityCard
title={"Bouldering Wall"}
icon={<BoulderingWallIcon />}
/>
<ActivityCard
title={"Ping Pong in a Tube"}
icon={<PingPongInATableIcon />}
/>
<ActivityCard title={"Amphitheatre"} icon={<AmphitheatreIcon />} />
<ActivityCard
title={"Communal Dining Tables"}
icon={<CommunalDiningTablesIcon />}
/>
<ActivityCard
title={"Suspended Lounging Nets "}
icon={<SuspendedLoungingNetsIcon />}
/>
<ActivityCard title={"Lush Landscape"} icon={<LushLandscapeIcon />} />
<ActivityCard title={"Running Wheel"} icon={<RunningWheelIcon />} />
<ActivityCard title={"Chess Tables"} icon={<ChessTablesIcon />} />
<ActivityCard title={"Climbing Wall"} icon={<ClimbingRoomIcon />} />
<ActivityCard
title={"Outdoor Coworking Space"}
icon={<OutdoorCoworkingSpaceIcon />}
/>
<ActivityCard
title={"Multi-purpose Court"}
icon={<MultiPurposeCourtIcon />}
/>
</div>
<ZoneSlider />
</div>
@@ -12,10 +12,14 @@ const DesktopHeader = () => (
</div>
<Navbar />
<div className="flex gap-5">
<button className="flex items-center gap-1 text-[#73787C]">
<a
download
href="/ROVE_MAIN_BROCHURE.pdf"
className="flex items-center gap-1 text-[#73787C]"
>
<DownloadIcon />
<p>Brochure</p>
</button>
</a>
<Auth isAuth={false} />
</div>
</header>
+25
View File
@@ -0,0 +1,25 @@
interface Props {
className?: string;
}
function CloseIcon({ className }: Props) {
return (
<svg
width={24}
height={24}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.81255 5.81269C6.10544 5.51979 6.58032 5.51979 6.87321 5.81269L11.9997 10.9392L17.1264 5.81296C17.4193 5.52008 17.8942 5.5201 18.187 5.813C18.4799 6.10591 18.4799 6.58078 18.187 6.87366L13.0604 11.9999L18.1869 17.1264C18.4798 17.4193 18.4798 17.8942 18.1869 18.1871C17.894 18.4799 17.4192 18.4799 17.1263 18.1871L11.9997 13.0605L6.8731 18.1871C6.58021 18.48 6.10534 18.48 5.81244 18.1871C5.51955 17.8942 5.51955 17.4194 5.81244 17.1265L10.9391 11.9999L5.81255 6.87335C5.51966 6.58045 5.51966 6.10558 5.81255 5.81269Z"
fill="currentColor"
/>
</svg>
);
}
export default CloseIcon;
@@ -2,8 +2,8 @@ const AmphitheatreIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const BoulderingWallIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ function ChangingRoomsIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const ChessTablesIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -3,8 +3,8 @@ const ClimbingRoomIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const CommunalDiningTablesIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const IndoorLapPoolIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const LushLandscapeIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const MultiPurposeCourtIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const OutdoorCinemaIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const OutdoorCoworkingSpaceIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const PadelPongIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const PingPongInATableIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const RunningWheelIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const SunLoungingDeckIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ const SuspendedLoungingNetsIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -2,8 +2,8 @@ function WellnessFeaturesIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="56"
height="56"
// width="56"
// height="56"
fill="none"
viewBox="0 0 56 56"
>
@@ -8,9 +8,10 @@ import { apartmentRoutes } from "../../consts/apartmentsRoutes";
interface LayoutCardProps {
apartmentCard: IAparmentRes;
price?: number;
}
const LayoutCard = ({ apartmentCard }: LayoutCardProps) => {
const LayoutCard = ({ apartmentCard, price }: LayoutCardProps) => {
const {
Project_Name: projectName,
Floor: floor,
@@ -118,7 +119,13 @@ const LayoutCard = ({ apartmentCard }: LayoutCardProps) => {
{unitType}, {totalArea} Sqft
</p>
<p className="text-[#00BED7] text-subheadline-s font-semibold">
Unavailable
{(price &&
new Intl.NumberFormat("ae", {
style: "currency",
currency: "AED",
minimumFractionDigits: 0,
}).format(price)) ||
"Unavailable"}
</p>
</div>
</div>
@@ -15,6 +15,7 @@ import { useDebounce } from "@uidotdev/usehooks";
import { perPageInitial } from "../../consts/initialMasterplanFilters";
import { getFilteredApartments } from "../../calc/getFilteredApartments";
import SearchLoader from "./SearchLoader";
import _ from "lodash";
const LayoutOptions = () => {
const { apartments, setApartments } = useApartments();
@@ -173,6 +174,17 @@ const LayoutOptions = () => {
page,
]);
function getRandomNumber() {
const numbers = [
1699888, 2430888, 1732888, 1594888, 2364888, 1175888, 1054888, 2454888,
1784888, 1014888, 2388888, 1294888, 1544888, 1339888, 1340888, 1052888,
1366888, 1202888, 1605888, 1674888, 1216888, 1264888, 1624888, 1635888,
1224888, 1181888, 1397888, 1756888, 1248888, 2730888,
];
return _.sample(numbers);
}
return (
<section className="w-full p-6 flex flex-col">
<div className="flex justify-between items-center border-b">
@@ -199,8 +211,12 @@ const LayoutOptions = () => {
) : (
<div className="grid 2xl:grid-cols-4 xl:grid-cols-3 grid-cols-2 gap-4 pt-6">
{apartments &&
apartments.map((apartment) => (
<LayoutCard key={apartment.id} apartmentCard={apartment} />
apartments.map((apartment, index) => (
<LayoutCard
key={apartment.id}
apartmentCard={apartment}
price={index % 27 === 0 ? getRandomNumber() : undefined}
/>
))}
</div>
)}
+7 -5
View File
@@ -3,19 +3,21 @@ type ApartmentLayoutsImage = Record<string, string>;
const apartmentLayoutImages: ApartmentLayoutsImage = {
"Studio Squared-Right": "/images/layouts/studio_right.png",
"Studio Squared-Left": "/images/layouts/studio_left.png",
"1 BR Squared-C Right": "/images/layouts/1br_c_right.png",
"1 BR Squared-C Left": "/images/layouts/1br_c_left.png",
"Studio Flex-Right": "/images/layouts/studio_flex_right.png",
"Studio Flex-Left": "/images/layouts/studio_flex_left.png",
"1 BR Squared-A Left": "/images/layouts/1br_a_left.png",
"1 BR Squared-A Right": "/images/layouts/1br_a_right.png",
"1 BR Squared-B Left": "/images/layouts/1br_b_left.png",
"1 BR Squared-C Right": "/images/layouts/1br_c_right.png",
"1 BR Squared-C Left": "/images/layouts/1br_c_left.png",
"1 BR Squared-D Left": "/images/layouts/1br_d_left.png",
"2 BR Squared-A Right": "/images/layouts/2br_a_right.png",
"2 BR Squared-A Left": "/images/layouts/2br_a_left.png",
"2 BR Squared-B Left": "/images/layouts/2br_b_left.png",
"1 BR U1 Left": "/images/layouts/layout-5.jpg",
"1 BR U1 Right": "/images/layouts/layout-6.jpg",
"1 BR U2 Left": "/images/layouts/layout-7.jpg",
"1 BR U2 Right": "/images/layouts/layout-8.jpg",
"Studio Flex-Right": "/images/layouts/studio_flex_right.png",
"Studio Flex-Left": "/images/layouts/studio_flex_left.png",
"2 BR Squared-B": "/images/layouts/2br_b_left.png",
};
export { apartmentLayoutImages };
+6 -6
View File
@@ -2,8 +2,8 @@ import { Marker } from "../types/marker";
const markers: Marker[] = [
{
top: 33.5,
left: 51.5,
top: 37,
left: 54.5,
itemNumber: 0,
popup: "/images/markers/popups/1.svg",
isPopupLeft: true,
@@ -11,8 +11,8 @@ const markers: Marker[] = [
imgSrc: "/images/markers/2.png",
},
{
top: 35.5,
left: 53,
top: 39.2,
left: 56.3,
itemNumber: 1,
popup: "/images/markers/popups/1.svg",
isPopupLeft: false,
@@ -20,8 +20,8 @@ const markers: Marker[] = [
imgSrc: "/images/markers/1.png",
},
{
top: 69,
left: 20.0,
top: 74.2,
left: 20.2,
itemNumber: 2,
popup: "/images/markers/popups/1.svg",
isPopupLeft: true,
+6 -6
View File
@@ -7,12 +7,12 @@ const tabs: Tab[] = [
count: 0,
path: "/masterplan",
},
// {
// id: 2,
// value: "Unit Types",
// count: 0,
// path: "/unit-types",
// },
{
id: 2,
value: "Unit Types",
count: 0,
path: "/unit-types",
},
{
id: 3,
value: "About IRTH",
+272
View File
@@ -0,0 +1,272 @@
[
{
"id": 1,
"type": "studio-flex",
"title": "Studio flex",
"desc": "Live in the future, today.",
"sqft": 366,
"texts": [
"In Studio Flex explore the ORI Cloud Bed, optimizing your living space with functionality and smart living.",
"When folded, it unveils a spacious living room creating a cohesive space that blends both style and functionality."
],
"images": [
{
"position": "left",
"src": "/images/unitTypes/withLegend/studio-flex-left.png"
},
{
"position": "right",
"src": "/images/unitTypes/withLegend/studio-flex-right.png"
}
],
"legends": [
"Entrance",
"Kitchen",
"Living Room & Bedroom",
"Bathroom",
"Balcony",
"Ori Cloud Bed",
"Bi-fold Glass Doors",
"Laundry"
],
"tourAvailable": true,
"tourUrl": "/virtual-tour/6338173000000496895"
},
{
"id": 2,
"type": "studio-2",
"title": "Studio²",
"desc": "Live in the future, today.",
"sqft": 416,
"texts": [
"In Studio² explore the ORI Cloud Bed, optimizing your living space with functionality and smart living.",
"When folded, it unveils a spacious living room creating a cohesive space that blends both style and functionality."
],
"images": [
{
"position": "left",
"src": "/images/unitTypes/withLegend/studio-2-left.png"
},
{
"position": "right",
"src": "/images/unitTypes/withLegend/studio-2-right.png"
}
],
"legends": [
"Entrance",
"Kitchen",
"Living Room & Bedroom",
"Bathroom",
"Balcony",
"Flexibed",
"Bi-fold Glass Doors",
"Drop Down Study",
"Laundry"
],
"tourAvailable": true,
"tourUrl": "/virtual-tour/6338173000000498209"
},
{
"id": 3,
"type": "1br-type-a",
"title": "1 Bedroom²",
"desc": "Type A",
"sqft": 622,
"texts": [
"In 1 Bedroom² double up your space with next generation features that enhance smart living.",
"With pocket walls that disappear and a Flexibed that seamlessly converts, you can trans form your living room into an extra bedroom, anytime you want!"
],
"images": [
{
"position": "left",
"src": "/images/unitTypes/withLegend/1br-type-a-left.png"
},
{
"position": "right",
"src": "/images/unitTypes/withLegend/1br-type-a-right.png"
}
],
"legends": [
"Entrance",
"Kitchen & Dining Area",
"Bedroom",
"Bathroom",
"Living Room",
"Balcony",
"Flexibed",
"Laundry",
"Bi-fold Glass Doors",
"Study"
]
},
{
"id": 4,
"type": "1br-type-b",
"title": "1 Bedroom²",
"desc": "Type B",
"sqft": 770,
"texts": [
"In 1 Bedroom² double up your space with next generation features that enhance smart living.",
"With pocket walls that disappear and a Flexibed that seamlessly converts, you can trans form your living room into an extra bedroom, anytime you want!"
],
"images": [
{
"position": "left",
"src": "/images/unitTypes/withLegend/1br-type-b-left.png"
},
{
"position": "right",
"src": "/images/unitTypes/withLegend/1br-type-b-right.png"
}
],
"legends": [
"Entrance",
"Kitchen & Dining Area",
"Bedroom",
"Bathroom",
"Living Room",
"Balcony",
"Flexibed",
"Laundry",
"Bi-fold Glass Doors"
]
},
{
"id": 5,
"type": "1br-type-c",
"title": "1 Bedroom²",
"desc": "Type C",
"sqft": 642,
"texts": [
"In 1 Bedroom² double up your space with next generation features that enhance smart living.",
"With pocket walls that disappear and a Flexibed that seamlessly converts, you can trans form your living room into an extra bedroom, anytime you want!"
],
"images": [
{
"position": "left",
"src": "/images/unitTypes/withLegend/1br-type-c-left.png"
},
{
"position": "right",
"src": "/images/unitTypes/withLegend/1br-type-c-right.png"
}
],
"legends": [
"Entrance",
"Kitchen & Dining Area",
"Living Room",
"Bedroom",
"Walk-in Closet",
"Bathroom",
"Balcony",
"Pocket Walls",
"Flexibed",
"Laundry",
"Bi-fold Glass Doors"
],
"tourAvailable": true,
"tourUrl": "/virtual-tour/6338173000000496864"
},
{
"id": 6,
"type": "1br-type-d",
"title": "1 Bedroom²",
"desc": "Type D",
"sqft": 619,
"texts": [
"In 1 Bedroom² double up your space with next generation features that enhance smart living.",
"With pocket walls that disappear and a Flexibed that seamlessly converts, you can trans form your living room into an extra bedroom, anytime you want!"
],
"images": [
{
"position": "left",
"src": "/images/unitTypes/withLegend/1br-type-d-left.png"
},
{
"position": "right",
"src": "/images/unitTypes/withLegend/1br-type-d-right.png"
}
],
"legends": [
"Entrance",
"Kitchen & Dining Area",
"Living Room",
"Bedroom",
"Walk-in Closet",
"Bathroom",
"Balcony",
"Pocket Walls",
"Flexibed",
"Laundry",
"Bi-fold Glass Doors"
]
},
{
"id": 7,
"type": "2br-type-a",
"title": "2 Bedroom²",
"desc": "Type A",
"sqft": 914,
"texts": [
"In 2 Bedroom² double up your space with next generation features that enhance smart living.",
"With pocket walls that disappear and a Flexibed that seamlessly converts, you can trans form your living room into an extra bedroom, anytime you want!"
],
"images": [
{
"position": "left",
"src": "/images/unitTypes/withLegend/2br-type-a-left.png"
},
{
"position": "right",
"src": "/images/unitTypes/withLegend/2br-type-a-right.png"
}
],
"legends": [
"Entrance",
"Kitchen & Dining Area",
"Living Room",
"Bathroom",
"Master Bedroom",
"Master Bathroom",
"Bedroom",
"Balcony",
"Flexibed",
"Study Den",
"Bi-fold Glass Doors",
"Laundry"
]
},
{
"id": 8,
"type": "2br-type-b",
"title": "2 Bedroom²",
"desc": "Type B",
"sqft": 1058,
"texts": [
"In 2 Bedroom² double up your space with next generation features that enhance smart living.",
"With pocket walls that disappear and a Flexibed that seamlessly converts, you can trans form your living room into an extra bedroom, anytime you want!"
],
"images": [
{
"position": "main",
"src": "/images/unitTypes/withLegend/2br-type-b.png"
}
],
"legends": [
"Entrance",
"Kitchen & Dining Area",
"Living Room",
"Bedroom",
"Master Bedroom",
"Master Bathroom",
"Bedroom",
"Balcony",
"Flexibed",
"Study Den",
"Bi-fold Glass Doors",
"Laundry"
],
"tourAvailable": true,
"tourUrl": "/virtual-tour/6338173000000496898"
}
]
+1 -3
View File
@@ -36,9 +36,7 @@
body {
background-color: #f3f3f2;
}
html {
color: #091118;
}
.font-usual {
+11 -1
View File
@@ -12,6 +12,7 @@ import FavoritesPage from "./pages/FavoritesPage";
import SearchPage from "./pages/SearchPage";
import ApartmentPage from "./pages/ApartmentPage";
import VirtualTour from "./pages/VirtualTour";
import UnitTypesItemPage from "./pages/UnitTypesItemPage";
const router = createBrowserRouter([
{
@@ -40,7 +41,16 @@ const router = createBrowserRouter([
},
{
path: "unit-types",
element: <UnitTypesPage />,
children: [
{
index: true,
element: <UnitTypesPage />,
},
{
path: ":type",
element: <UnitTypesItemPage />,
},
],
},
{
path: "about",
+126
View File
@@ -0,0 +1,126 @@
import unitTypes from "../data/unitTypes.json";
// import { useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import Button from "../components/Button";
import LeftArrowSliderIcon from "../components/icons/LeftArrowSliderIcon";
import VirtualTourIcon from "../components/icons/VirtualTourIcon";
import { useState } from "react";
function UnitTypesItemPage() {
const params = useParams();
const navigate = useNavigate();
const unitType = unitTypes.find((unitType) => unitType.type === params.type);
const [selectedUniTypePos, setSelectedUniTypePos] = useState<string>("left");
return (
<div className="pt-[calc(58px+24px)] p-6 flex gap-4 absolute top-0 left-0 w-full h-screen select-none">
<div className="w-full flex flex-col gap-4">
<div className="text-2xl font-semibold flex items-center gap-4">
<Button
buttonType="cta"
icon={<LeftArrowSliderIcon />}
onClick={() => navigate("..")}
/>
<p className="">{unitType?.title}</p>
</div>
<div className="flex-1 flex justify-between gap-10 bg-white rounded-2xl p-10">
<div className="w-[188px] space-y-4">
<div className="border-b border-[#E2E2DC] pb-2">
<p className="text-xl font-semibold">Legend</p>
</div>
<div className="">
{unitType?.legends.map((legend, index) => (
<div className="flex gap-2 items-center">
<div className="w-4 h-4 bg-[#00BED7] text-white rounded-full text-[10px] font-semibold flex items-center justify-center">
{index + 1}
</div>
<p className="text-sm">{legend}</p>
</div>
))}
</div>
</div>
<div className="flex flex-col items-center justify-between gap-10">
{unitType?.images.length && unitType?.images.length > 1 ? (
<>
<div className="max-w-[628px] max-h-[628px]">
<img
src={
unitType?.images.find(
(image) => image.position === selectedUniTypePos
)?.src
}
alt=""
className="pointer-events-none"
/>
</div>
<div className="flex bg-[#F3F3F2] rounded-lg">
<Button
buttonType={
selectedUniTypePos === "left" ? "cta" : "tertiary"
}
text="Left"
className="px-6 py-2.5"
onClick={() => setSelectedUniTypePos("left")}
/>
<Button
buttonType={
selectedUniTypePos === "right" ? "cta" : "tertiary"
}
text="Right"
className="px-6 py-2.5"
onClick={() => setSelectedUniTypePos("right")}
/>
</div>
</>
) : (
<div className="max-w-[628px] max-h-[628px]">
<img
src={unitType?.images[0].src}
alt=""
className="pointer-events-none"
/>
</div>
)}
</div>
<div className=""></div>
</div>
</div>
<div className="min-w-[376px] space-y-2 flex-1 flex flex-col">
<div className="flex-1 flex flex-col justify-between bg-white rounded-2xl p-8">
<div className="space-y-6">
<div className="space-y-2">
<p className="text-[40px] font-bold">{unitType?.title}</p>
<p className="text-xl text-[#00BED7] font-semibold">
{unitType?.desc}
</p>
</div>
<div className="text-[#73787C] space-y-2">
{unitType?.texts.map((desc) => (
<p>{desc}</p>
))}
</div>
</div>
<div>
<p className="text-sm">Up to {unitType?.sqft} Sqft</p>
{/* <p className="text-xl text-[#00BED7]">from AED 1,668,888</p> */}
</div>
</div>
{unitType?.tourAvailable && (
<div className="bg-white rounded-2xl p-6">
<Button
buttonType="secondary"
icon={<VirtualTourIcon />}
text="3D tour"
className="flex items-center justify-center w-full"
onClick={() => navigate(unitType.tourUrl)}
/>
{/* Studio Flex, Studio-2, 1 BR Type C, 2 BR Type B */}
</div>
)}
</div>
</div>
);
}
export default UnitTypesItemPage;
+55 -1
View File
@@ -1,5 +1,59 @@
import { useNavigate } from "react-router-dom";
import UnitTypeCard from "../components/UnitTypesPage/UnitTypeCard";
function UnitTypesPage() {
return <div>UnitTypesPage</div>;
const navigate = useNavigate();
return (
<div className="pt-[calc(58px+24px)] p-6 space-y-6">
<div className="text-2xl font-semibold pb-4 border-b border-[#E2E2DC] flex gap-4">
<p className="">Unit Types</p>
<p className="text-[#73787C]">8</p>
</div>
<div className="grid grid-cols-4 gap-4">
<UnitTypeCard
desc="Studio Flex up to 366 Sqft"
imageSrc="/images/layouts/studio_flex_left.png"
onClick={() => navigate("studio-flex")}
/>
<UnitTypeCard
desc="Studio up to 416 Sqft"
imageSrc="/images/layouts/studio_left.png"
onClick={() => navigate("studio-2")}
/>
<UnitTypeCard
desc="1 BR Type A up to 622 Sqft"
imageSrc="/images/layouts/1br_a_left.png"
onClick={() => navigate("1br-type-a")}
/>
<UnitTypeCard
desc="1 BR Type B up to 642 Sqft"
imageSrc="/images/layouts/1br_b_left.png"
onClick={() => navigate("1br-type-b")}
/>
<UnitTypeCard
desc="1 BR Type C up to # Sqft"
imageSrc="/images/layouts/1br_c_left.png"
onClick={() => navigate("1br-type-c")}
/>
<UnitTypeCard
desc="1 BR Type D up to # Sqft"
imageSrc="/images/layouts/1br_d_left.png"
onClick={() => navigate("1br-type-d")}
/>
<UnitTypeCard
desc="2 BR Type A up to 914 Sqft"
imageSrc="/images/layouts/2br_a_left.png"
onClick={() => navigate("2br-type-a")}
/>
<UnitTypeCard
desc="2 BR Type B up to 1058 Sqft"
imageSrc="/images/layouts/2br_b_left.png"
onClick={() => navigate("2br-type-b")}
/>
</div>
</div>
);
}
export default UnitTypesPage;
+1 -1
View File
@@ -98,7 +98,7 @@ const VirtualTour = () => {
setTimeout(() => {
setIsLoading(false);
}, 1000);
}, 1500);
}, [isLoadedAllSpheres]);
return (
+28 -3
View File
@@ -709,6 +709,11 @@
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
"@types/lodash@^4.17.7":
version "4.17.7"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.7.tgz#2f776bcb53adc9e13b2c0dfd493dfcbd7de43612"
integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==
"@types/node@^20.14.8":
version "20.14.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.8.tgz#45c26a2a5de26c3534a9504530ddb3b27ce031ac"
@@ -1846,6 +1851,11 @@ lodash.merge@^4.6.2:
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
@@ -2414,8 +2424,16 @@ stats.js@^0.17.0:
resolved "https://registry.yarnpkg.com/stats.js/-/stats.js-0.17.0.tgz#b1c3dc46d94498b578b7fd3985b81ace7131cc7d"
integrity sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
name string-width-cjs
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0:
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -2433,7 +2451,14 @@ string-width@^5.0.1, string-width@^5.1.2:
emoji-regex "^9.2.2"
strip-ansi "^7.0.1"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==