touch functionality

This commit is contained in:
2024-07-01 17:58:09 +05:00
parent 87d78f3f78
commit 497cb6aa44
24 changed files with 843 additions and 264 deletions
@@ -3,6 +3,7 @@ import { ISwitchLabel } from "../../types/switchLabel";
import SwitchToggle from "../SwitchToggle";
import { IAparmentRes } from "../../types/apartmentsRes";
import { apartmentRoutes } from "../../consts/apartmentsRoutes";
import { apartmentLayoutImages } from "../../consts/apartmentLayoutsImages";
const apartmentLayouts: ISwitchLabel[] = [
{ id: "1", label: "Layout" },
@@ -14,6 +15,8 @@ interface ApartmentLayoutProps {
}
const ApartmentLayout = ({ currentApartment }: ApartmentLayoutProps) => {
const apartmentLayoutImage =
apartmentLayoutImages[currentApartment.Unit_Type];
const [currentLabel, setCurrentLabel] = useState(apartmentLayouts[0]);
const handleOnSwitchClick = (label: ISwitchLabel) => {
setCurrentLabel(label);
@@ -27,7 +30,7 @@ const ApartmentLayout = ({ currentApartment }: ApartmentLayoutProps) => {
<div className="w-full xl:px-[304px] sm:px-24 h-full flex justify-center items-center">
<img
className="w-full h-full object-contain max-h-[628px]"
src={imageLayout ? imageLayout : "/images/layout-1.png"}
src={imageLayout ? imageLayout : apartmentLayoutImage}
alt=""
/>
</div>
@@ -37,6 +40,7 @@ const ApartmentLayout = ({ currentApartment }: ApartmentLayoutProps) => {
className="absolute right-10 bottom-10"
/>
<SwitchToggle
isDisabled
labels={apartmentLayouts}
currentLabel={currentLabel}
onClick={handleOnSwitchClick}
@@ -1,10 +1,10 @@
import { useNavigate } from "react-router-dom";
import { useEffect, useState } from "react";
import Button from "../Button";
import HeartIcon from "../icons/Heart";
import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon";
import { IAparmentRes } from "../../types/apartmentsRes";
import useFavorites from "../../store/useFavorites";
import { useEffect, useState } from "react";
interface ButtonPanelProps {
currentApartment: IAparmentRes;
@@ -17,7 +17,7 @@ const ButtonPanel = ({ currentApartment }: ButtonPanelProps) => {
const { setFavorites } = useFavorites();
const handleOnBackClick = () => {
navigate("../search");
navigate(-1);
};
const handleOnFavoriteClick = (
@@ -1,11 +1,11 @@
interface EastWingHighlightingProps {
handleOnMouseOut:
handleOnMouseOut?:
| (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnMouseOver: (
handleOnMouseOver?: (
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void;
handleOnApartmentClick: (
handleOnApartmentClick?: (
e: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void;
}
@@ -1,11 +1,11 @@
interface FloorEastWingHighlightingProps {
handleOnMouseOut:
handleOnMouseOut?:
| (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnMouseOver: (
handleOnMouseOver?: (
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void | (() => void);
handleOnApartmentClick: (
handleOnApartmentClick?: (
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void;
}
@@ -1,11 +1,11 @@
interface WestWingTopLevelsHighlightingProps {
handleOnMouseOut:
handleOnMouseOut?:
| (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnMouseOver:
handleOnMouseOver?:
| (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnApartmentClick: (
handleOnApartmentClick?: (
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void;
}
@@ -0,0 +1,110 @@
import { apartmentsWithoutVirtualTour } from "../../consts/apartmentsWithoutVirtualTour";
import { IAparmentRes } from "../../types/apartmentsRes";
import Button from "../Button";
import RightArrowSliderIcon from "../icons/RightArrowSliderIcon";
import VirtualTourIcon from "../icons/VirtualTourIcon";
import useModal from "../../store/useModal";
import { MobileModalWrapper } from "../modals/mobile/MobileModalWrapper";
import AboutComplexMobileModal from "../modals/mobile/AboutCompexMobileModal/AboutComplexMobileModal";
import { IDesctiptionFloor } from "../../types/descriptionFloor";
interface MobileApartmentDescriptionProps {
apartment: IAparmentRes | null;
apartments: IAparmentRes[];
apartmentDataType: string | null;
floor: IDesctiptionFloor | null;
}
const MobileApartmentDescription = ({
apartment,
apartmentDataType,
apartments,
floor,
}: MobileApartmentDescriptionProps) => {
const wing =
apartment && apartment.Unit_No.split("-")[0] === "E"
? "East Wing"
: "West Wing";
const isVirtualTourAvailiable =
apartment &&
!apartmentsWithoutVirtualTour.some(
(aprt) =>
aprt.type === apartment.Unit_Type || aprt.type === apartmentDataType
);
const { setModal } = useModal();
const handleOnExploreClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
event.preventDefault();
if (!apartment) return;
setModal(null);
const timeout = setTimeout(() => {
setModal(
<MobileModalWrapper isHeightScreen>
<AboutComplexMobileModal
currentApartment={apartment}
apartments={apartments}
floor={floor}
/>
</MobileModalWrapper>
);
clearTimeout(timeout);
}, 300);
};
return (
<>
{apartment && (
<div className="p-6 py-3">
<div
className={`bg-white rounded-2xl p-6 flex flex-col text-subheadline-s relative text-nowrap desc-shadow py-2 duration-300 ease-in-out transition-opacity min-w-[344px]`}
>
<h2 className="text-[#0D1922] font-semibold pt-6">
{apartment?.Unit_Type},{" "}
{apartment && Math.round(apartment?.Total_Area_Sqft)} Sqft
</h2>
<div className="flex gap-2 items-center text-caption-m font-semibold pt-1 border-b pb-4 justify-start">
<p className="text-[#0D1922B2]">{wing}</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-[#0D1922B2]">Floor {apartment.Floor}</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-[#0D1922B2]">{apartment.Unit_No}</p>
</div>
<div className="flex justify-between items-center pt-4 gap-14 pb-4">
<p className="font-semibold text-[#00BED7] text-subheadline-s">
Unvailiable
</p>
{/* <p className="font-semibold text-[#00BED7] text-subheadline-s">
AED 1,668,888
</p> */}
{isVirtualTourAvailiable && (
<div
className={`bg-[#30B21614] text-[#30B216] px-2 py-[6px] flex gap-1 items-center rounded-lg opacity-100`}
>
<VirtualTourIcon />
<p className="text-caption-m font-semibold text-[#30B216]">
3D-tour
</p>
</div>
)}
</div>
<div className="w-0 h-0 border-transparent border-t-[14px] border-x-[6px] border-b-0 absolute left-6 -bottom-[13px] border-t-white"></div>
<div className="w-full pb-6 ">
<Button
buttonType="cta"
className="justify-center w-full"
text="Explore"
icon={<RightArrowSliderIcon />}
iconPos="right"
onClick={handleOnExploreClick}
/>
</div>
</div>
</div>
)}
</>
);
};
export default MobileApartmentDescription;
@@ -3,8 +3,8 @@ import { MouseEvent } from "react";
import { IDesctiptionFloor } from "../../../types/descriptionFloor";
interface FloorsHighlightingProps {
handleOnFloorClick: () => void;
handleOnSkygardenClick: () => void;
handleOnFloorClick: (e: MouseEvent | any) => void;
handleOnSkygardenClick: (e: React.MouseEvent) => void;
handleOnWingWrapperMouseEnter: (e: React.MouseEvent<SVGSVGElement>) => void;
handleOnFloorMouseEnter:
| ((
@@ -7,9 +7,7 @@ import RightArrowSliderIcon from "../../icons/RightArrowSliderIcon";
interface MobileFloorDescriptionProps {
descriptionFloor: IDesctiptionFloor | null;
floorApartments: IAparmentRes[];
onClick: (
e: React.MouseEvent<Element, React.MouseEvent<Element, MouseEvent>>
) => void;
onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
}
const MobileFloorDescription = ({
@@ -0,0 +1,63 @@
import Button from "../../Button";
import CrossIcon from "../../icons/CrossIcon";
import RightArrowSliderIcon from "../../icons/RightArrowSliderIcon";
interface MobileSkygardenDescriptionProps {
onClick: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
}
const MobileSkygardenDescription = ({
onClick,
}: MobileSkygardenDescriptionProps) => {
return (
<>
<div
className={`bg-white rounded-2xl p-6 flex flex-col gap-4 w-[344px] absolute left-[414px] transition-opacity duration-300 desc-shadow h-[240px] pointer-events-auto`}
>
<div className="relative">
<div className="flex justify-between border-b pb-4">
<div className="flex flex-col">
<p
className={`text-[#0D1922] font-semibold text-[20px] duration-300 ease-in-out text-subheadline-s`}
>
Sky Garden
</p>
</div>
<Button buttonType="tertiary" icon={<CrossIcon />} />
</div>
<div className="flex flex-col gap-4 pt-4">
<div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="p-1 flex justify-center items-center">8</p>
</div>
<p className="text-s text-[#73787C] w-full">Indoor</p>
</div>
<p className="text-s text-[#0D1922] text-nowrap">3 amenties</p>
</div>
<div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="p-1 flex justify-center items-center">8</p>
</div>
<p className="text-s text-[#73787C] w-full">Studio</p>
</div>
<p className="text-s text-[#0D1922] text-nowrap">14 amenties</p>
</div>
<Button
buttonType="cta"
className="justify-center"
text="Explore"
icon={<RightArrowSliderIcon />}
iconPos="right"
onClick={onClick}
/>
</div>
<div className="w-0 h-0 border-t-0 border-r-[6px] border-b-[14px] border-l-[6px] border-transparent border-b-white absolute -top-[35px] left-[0px]"></div>
</div>
</div>
</>
);
};
export default MobileSkygardenDescription;
@@ -1,10 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { MouseEvent, useEffect, useState } from "react";
import FloorDescription from "../FloorDescription";
import { IDesctiptionFloor } from "../../../types/descriptionFloor";
import SkygardenDescription from "../SkygardenDescription";
import FloorSidebar from "../FloorSidebar/FloorSidebar";
import SkygardenSidebar from "../SkygardenSidebar/SkygardenSidebar";
import useWingSidebar from "../../../store/useWingSidebar";
import useModal from "../../../store/useModal";
import {
@@ -26,14 +23,15 @@ import { isMobile } from "react-device-detect";
import FloorsHighlighting from "./FloorsHighlighting";
import MobileFloorDescription from "./MobileFloorDescription";
import WingFloorModal from "../../modals/mobile/WingFloorModal";
import MobileSkygardenDescription from "./MobileSkygardenDescription";
import SkygardenModal from "../../modals/mobile/SkygardenModal";
const skyGardenFloor = 22;
// const skyGardenFloor = 22;
const SequenceWing = () => {
const [width, setWidth] = useState<number>(0);
const [top, setTop] = useState<number>(0);
const [left, setLeft] = useState<number>(0);
// const leftWingRef = useRef(null);
const { isSidebar, setIsSidebar } = useWingSidebar();
const [mousePos, setMousePos] = useState<[number, number]>([0, 0]);
const [currentHoveredFloor, setHoverCurrentFloor] =
@@ -42,7 +40,7 @@ const SequenceWing = () => {
const [currentFloor, setCurrentFloor] = useState<IDesctiptionFloor | null>(
null
);
const [isWrapperHovered, setIsWrapperHovered] = useState(false);
const [, setIsWrapperHovered] = useState(false);
const [isSkygardenSidebar, setIsSkygardenSidebar] = useState(false);
const [isFloorSidebar, setIsFloorSidebar] = useState(false);
const { setModal } = useModal();
@@ -50,12 +48,10 @@ const SequenceWing = () => {
const [currentHoveredApartments, setCurrentHoveredApartments] = useState<
IAparmentRes[]
>([]);
const [selectedApartments, setSelectedApartments] = useState<IAparmentRes[]>(
[]
);
const [isDescriptionFloorMobile, setIsDescriptionFloorMobile] =
useState(false);
const [isDescriptionSkygarden, setIsDescriptionSkygarden] = useState(false);
const {
apartmentTypeCheckboxes,
@@ -96,60 +92,17 @@ const SequenceWing = () => {
setIsWrapperHovered(false);
};
const handleOnFloorClick = (e: MouseEvent | any) => {
const isFloorClicked = Boolean(e.currentTarget.dataset.id);
if (isFloorClicked) {
// detect mouse pos
const screenWidth = window.innerWidth;
const screenHeight = window.innerHeight;
// >1072
if (screenWidth > laptopWidth) {
const _top = screenWidth / 2 - screenHeight / 2;
setMousePos([e.clientX - 384, e.clientY + Math.abs(_top) - 20]);
} else {
// 640-1072
if (screenWidth > mobileWidht) {
const _top = screenHeight / 4;
const _left = laptopWidth - screenWidth;
setMousePos([
e.clientX - 440 + _left,
e.clientY + Math.abs(_top) + 20,
]);
// <640
} else {
const _top = screenHeight / 2.5;
const _left = laptopWidth - screenWidth;
setMousePos([
e.clientX - 440 + _left,
e.clientY + Math.abs(_top) + 20,
]);
}
}
//detect currentFloor, current sidebar and apartment on floor
if (!currentHoveredFloor && !currentHoveredApartments) return;
setSelectedApartments(currentHoveredApartments);
setCurrentFloor(currentHoveredFloor);
if (!isMobile) {
setIsFloorSidebar(true);
setIsSkygardenSidebar(false);
setIsSidebar(true);
} else {
setIsDescriptionFloorMobile(true);
}
} else {
setIsDescriptionFloorMobile(false);
}
const handleOnFloorClick = () => {
setIsDescriptionSkygarden(false);
//detect currentFloor
if (!currentHoveredFloor && !currentHoveredApartments) return;
setCurrentFloor(currentHoveredFloor);
};
const handleOnSkygardenClick = () => {
if (!isMobile) {
setIsSkygardenSidebar(true);
setIsFloorSidebar(false);
setIsSidebar(true);
} else {
// setModal(<WingFloorModal />);
}
setCurrentFloor(null);
setIsDescriptionFloorMobile(false);
setIsDescriptionSkygarden(true);
};
function handleMouseMove(
@@ -195,7 +148,6 @@ const SequenceWing = () => {
//detect currentFloor, current sidebar and apartment on floor
if (!currentHoveredFloor && !currentHoveredApartments) return;
setSelectedApartments(currentHoveredApartments);
setCurrentFloor(currentHoveredFloor);
if (!isMobile) {
setIsFloorSidebar(true);
@@ -203,6 +155,7 @@ const SequenceWing = () => {
setIsSidebar(true);
} else {
setIsDescriptionFloorMobile(true);
setCurrentFloor(null);
}
}
}
@@ -233,11 +186,25 @@ const SequenceWing = () => {
}
}
const handleOnExploreClick = (
e: MouseEvent<Element, MouseEvent<Element, MouseEvent>>
const handleOnExploreFloorClick = (
e: MouseEvent<Element, MouseEvent<Element, MouseEvent>> | any
) => {
e.stopPropagation();
setModal(<WingFloorModal />);
if (!currentHoveredFloor) return;
setModal(
<WingFloorModal
currentFloor={currentHoveredFloor}
floorApartments={apartments}
/>
);
setIsDescriptionFloorMobile(false);
};
const handleOnExploreSkygardenClick = (
e: MouseEvent<Element, MouseEvent<Element, MouseEvent>> | any
) => {
e.stopPropagation();
setIsDescriptionSkygarden(false);
setModal(<SkygardenModal />);
setIsDescriptionFloorMobile(false);
};
@@ -313,33 +280,16 @@ const SequenceWing = () => {
sortList,
]);
// useEffect(() => {
// if (isLoading) {
// setModal(<LoaderModal />);
// } else {
// setModal(null);
// }
// }, [isLoading, setModal]);
useEffect(() => {
if (isLoading) {
setModal(<LoaderModal />);
} else {
setModal(null);
}
}, [isLoading, setModal]);
return (
<div className="absolute left-0 overflow-hidden h-screen w-screen select-none ">
<div
className=" absolute h-[calc(100vh-56px)] right-0 w-1/2 duration-300 transition-all "
style={{ right: `${isFloorSidebar ? "0" : "-50%"}` }}
>
<FloorSidebar
floorApartments={selectedApartments}
currentFloor={currentFloor}
onMouseEnter={handleOnWingWrapperMouseLeave}
/>
</div>
<div
className=" absolute h-[calc(100vh-56px)] right-0 w-1/2 duration-300 transition-all"
style={{ right: `${isSkygardenSidebar ? "0" : "-50%"}` }}
>
<SkygardenSidebar onMouseEnter={handleOnWingWrapperMouseLeave} />
</div>
<div
className="absolute left-0 transition-[left]"
style={{
@@ -351,60 +301,29 @@ const SequenceWing = () => {
}`,
}}
>
<div
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out lg:flex hidden ${
currentHoveredFloor?.floor === skyGardenFloor && isWrapperHovered
? "opacity-100"
: "opacity-0"
}`}
style={{
top: mousePos[1] - 25,
left: `${
isSkygardenSidebar || isFloorSidebar
? `calc(${mousePos[0]}px + 25%)`
: `${mousePos[0]}px`
}`,
}}
>
<SkygardenDescription />
</div>
<div
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out lg:flex hidden ${
currentHoveredFloor?.floor !== skyGardenFloor &&
currentHoveredFloor &&
isWrapperHovered
? "opacity-100"
: "opacity-0"
}`}
style={{
top: mousePos[1],
left: `${
isSkygardenSidebar || isFloorSidebar
? `calc(${mousePos[0]}px + 25%)`
: `${mousePos[0]}px`
}`,
}}
>
<FloorDescription
descriptionFloor={currentHoveredFloor}
floorApartments={currentHoveredApartments}
/>
</div>
{/* */}
<div
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out ${
isDescriptionFloorMobile ? "opacity-100" : "opacity-0"
isDescriptionSkygarden ? "" : "hidden"
}`}
style={{
top: `${mousePos[1]}px`,
left: `${mousePos[0]}px`,
}}
>
<MobileSkygardenDescription onClick={handleOnExploreSkygardenClick} />
</div>
<div
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out ${
isDescriptionFloorMobile ? "" : "hidden"
}`}
style={{
top: `${mousePos[1]}px`,
left: `${mousePos[0]}px`,
// top: `${mousePos[1] + 140}px`,
// left: `${mousePos[0] + 366}px`,
}}
>
<MobileFloorDescription
onClick={handleOnExploreClick}
onClick={handleOnExploreFloorClick}
descriptionFloor={currentHoveredFloor}
floorApartments={currentHoveredApartments}
/>
@@ -1,5 +1,5 @@
import { useState } from "react";
// import { useSwipeable } from "react-swipeable";
import { useSwipeable } from "react-swipeable";
import SkygardenIndoorLayout from "./SkygardenIndoorLayout";
import { ISwitchLabel } from "../../../types/switchLabel";
import SwitchToggle from "../../SwitchToggle";
@@ -14,13 +14,18 @@ const LayoutSlider = () => {
const [currentLabel, setCurrentLabel] = useState<ISwitchLabel>(
skygardenLayouts[0]
);
const handlers = useSwipeable({
onSwipedLeft: () => setCurrentLabel(skygardenLayouts[1]),
onSwipedRight: () => setCurrentLabel(skygardenLayouts[0]),
trackMouse: true,
});
const handleOnSwitchClick = (label: ISwitchLabel) => {
setCurrentLabel(label);
};
return (
<div className="flex flex-col items-center">
<div className="select-none flex flex-col items-center" {...handlers}>
<SwitchToggle
labels={skygardenLayouts}
currentLabel={currentLabel}
@@ -1,9 +1,7 @@
import { Outlet } from "react-router-dom";
import { isMobile } from "react-device-detect";
import { FullScreen, useFullScreenHandle } from "react-full-screen";
import { useEffect } from "react";
import useModal from "../../../store/useModal";
import DesktopHeader from "./DesktopHeader";
import MobileHeader from "./MobileHeader";
import useFullScreen from "../../../store/useFullScreen";
@@ -14,12 +12,12 @@ const Layout = () => {
useEffect(() => {
setOnFullscreen(onFullscreenHandle);
}, []);
}, [onFullscreenHandle, setOnFullscreen]);
return (
<>
<FullScreen handle={onFullscreenHandle}>
{isMobile ? <MobileHeader /> : <DesktopHeader />}
<MobileHeader />
{modal}
<Outlet />
</FullScreen>
@@ -18,7 +18,7 @@ const MobileHeader = () => {
isToggled
? "rounded-ee-lg rounded-es-lg shadow-[#00000026] shadow-md"
: ""
} text-white flex flex-col text-sm items-center transition-all duration-500 ease-in-out absolute top-0 left-0 z-[99999900] overflow-hidden font-usual ${
} text-white flex flex-col text-sm items-center transition-all duration-500 ease-in-out absolute top-0 left-0 z-[99999999] overflow-hidden font-usual ${
isToggled ? "max-h-[472px]" : "max-h-14"
}`}
>
@@ -1,8 +1,6 @@
import { useEffect, useState } from "react";
import { isMobile } from "react-device-detect";
import { useNavigate, useLocation } from "react-router-dom";
import { Tab } from "../../../types/tab";
import NavbarDesktop from "./NavbarDesktop";
import NavbarMobile from "./NavbarMobile";
import { tabs as _tabs } from "../../../consts/tabs";
import useFavorites from "../../../store/useFavorites";
@@ -50,15 +48,13 @@ const Navbar = () => {
return (
<>
{isMobile ? (
<NavbarMobile onTabClick={onTabClick} tabs={tabs} />
) : (
<NavbarDesktop
selectedTab={selectedTab}
{
<NavbarMobile
onTabClick={onTabClick}
tabs={tabs}
selectedTab={selectedTab}
/>
)}
}
</>
);
};
@@ -4,14 +4,20 @@ import NavbarTabMobile from "./NavbarTabMobile";
interface NavbarProps {
onTabClick: (tab: Tab) => void;
tabs: Tab[];
selectedTab: Tab | null;
}
const NavbarMobile = ({ onTabClick, tabs }: NavbarProps) => (
const NavbarMobile = ({ onTabClick, tabs, selectedTab }: NavbarProps) => (
<nav
className={`text-[#73787C] flex w-full flex-col bg-white rounded-lg px-4`}
>
{tabs.map((tab) => (
<NavbarTabMobile key={tab.id} tab={tab} onClick={onTabClick} />
<NavbarTabMobile
key={tab.id}
tab={tab}
onClick={onTabClick}
isSelected={selectedTab?.id === tab.id}
/>
))}
</nav>
);
@@ -4,15 +4,16 @@ import RightArrowIcon from "../../icons/RightArrowIcon";
interface NavbarTabProps {
tab: Tab;
onClick: (tab: Tab) => void;
isSelected: boolean;
}
const NavbarTabMobile = ({ tab, onClick }: NavbarTabProps) => {
return (
<button className="w-full border-b last:border-b-0 flex justify-between py-4 ">
<div
className=" text-[#0D1922] relative w-fit"
onClick={() => onClick(tab)}
>
<button
className="w-full border-b last:border-b-0 flex justify-between py-4 "
onClick={() => onClick(tab)}
>
<div className=" text-[#0D1922] relative w-fit">
<div className={` transition-all duration-300`}>{tab.value}</div>
{tab.count !== 0 && (
<div className="absolute top-0 -right-4 w-4 h-4 bg-[#00BED7] rounded-full text-white text-[10px] flex items-center justify-center">
@@ -44,13 +44,6 @@ const AboutComplexModal = ({
const handleOn3DTourClick = () => {
setModal(null);
// const virtualTour = apartmentRoutes.find(
// (route) => route.type === apartment.Unit_Type
// );
// const virtualRoute = virtualTour
// ? virtualTour.virtualTour
// : "apartments-studio-1";
if (!apartment) return;
navigate(`../virtual-tour/${apartment.id}`);
@@ -0,0 +1,41 @@
import { IAparmentRes } from "../../../../types/apartmentsRes";
import ApartmentLayout from "../../../apartmentPage/ApartmentLayout";
import ButtonPanel from "./ButtonPanel";
import { IDesctiptionFloor } from "../../../../types/descriptionFloor";
import ApartmentSidebar from "../../../ApartmentSidebar";
interface AboutComplexMobileModalProps {
currentApartment: IAparmentRes;
apartments: IAparmentRes[];
floor: IDesctiptionFloor | null;
}
const AboutComplexMobileModal = ({
currentApartment,
apartments,
floor,
}: AboutComplexMobileModalProps) => {
return (
<div className="absolute min-h-screen w-screen bg-[#F3F3F2] pt-20 px-6 pb-6">
<div className="flex flex-col lg:col-span-7 col-span-full ">
{currentApartment && (
<ButtonPanel
currentApartment={currentApartment}
apartments={apartments}
floor={floor}
/>
)}
{currentApartment && (
<ApartmentLayout currentApartment={currentApartment} />
)}
{currentApartment && (
<div className="lg:col-span-2 rounded-lg col-span-full pt-6">
<ApartmentSidebar currentApartment={currentApartment} />
</div>
)}
</div>
</div>
);
};
export default AboutComplexMobileModal;
@@ -0,0 +1,106 @@
import { useEffect, useState } from "react";
import useFavorites from "../../../../store/useFavorites";
import { IAparmentRes } from "../../../../types/apartmentsRes";
import Button from "../../../Button";
import HeartIcon from "../../../icons/Heart";
import LeftArrowSliderIcon from "../../../icons/LeftArrowSliderIcon";
import useModal from "../../../../store/useModal";
import WingFloorModal from "../WingFloorModal";
import { IDesctiptionFloor } from "../../../../types/descriptionFloor";
interface ButtonPanelProps {
currentApartment: IAparmentRes;
apartments: IAparmentRes[];
floor: IDesctiptionFloor | null;
}
const ButtonPanel = ({
currentApartment,
apartments,
floor,
}: ButtonPanelProps) => {
const unitNo = currentApartment.Unit_No.split("-")[1];
const [isFavorite, setIsFavorite] = useState(false);
const { setFavorites } = useFavorites();
const { setModal } = useModal();
const handleOnBackClick = () => {
setModal(null);
const timeout = setTimeout(() => {
setModal(
<WingFloorModal currentFloor={floor} floorApartments={apartments} />
);
clearTimeout(timeout);
}, 300);
};
const handleOnFavoriteClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.stopPropagation();
const favorites = localStorage.getItem("Favorites");
if (!favorites) {
setIsFavorite(true);
const updatedFavorites = JSON.stringify([currentApartment]);
localStorage.setItem("Favorites", updatedFavorites);
} else {
const _favorites = JSON.parse(favorites) as IAparmentRes[];
if (_favorites.some((apart) => apart.id === currentApartment.id)) {
setIsFavorite(false);
const updatedFavorites = [..._favorites].filter(
(apart) => apart.id !== currentApartment.id
);
const convertedFavorites = JSON.stringify(updatedFavorites);
setFavorites(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites);
} else {
setIsFavorite(true);
const updatedFavorites = [..._favorites, currentApartment];
setFavorites(updatedFavorites);
const convertedFavorites = JSON.stringify(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites);
}
}
};
useEffect(() => {
const favorites = localStorage.getItem("Favorites");
if (favorites) {
const _isFavorite = (JSON.parse(favorites) as IAparmentRes[]).some(
(apart) => apart.id === currentApartment.id
);
setIsFavorite(_isFavorite);
}
}, [currentApartment.id]);
return (
<div className="flex justify-between w-full gap-4 items-center pb-3">
<div className="flex gap-4 items-center ">
<Button
icon={<LeftArrowSliderIcon />}
buttonType="cta"
onClick={handleOnBackClick}
/>
<div className="flex flex-col">
<p className="text-[#73787C] text-caption-m font-semibold">
{unitNo}
</p>
<h2 className="text-subheadline-s font-semibold text-[#0D1922]">
{currentApartment.Unit_Type}
</h2>
</div>
</div>
<Button
buttonType="favorite"
icon={<HeartIcon isFilled={isFavorite} />}
isCircleRounded
onClick={handleOnFavoriteClick}
/>
</div>
);
};
export default ButtonPanel;
@@ -15,18 +15,27 @@ import {
initialViewCheckboxes,
} from "../../../consts/initialMasterplanFilters";
import { ICheckbox } from "../../../types/checkbox";
import useMasterplanFilters from "../../../store/useMasterplanFilters";
const MasterplanFiltersModal = () => {
const { setModal } = useModal();
const { setIsAnimate } = useContext(MobileModalWrapperContext);
const [apartmentTypeCheckboxes, setApartmentTypeCheckboxes] = useState<
ICheckbox[]
>(initialAparmentTypeCheckboxes);
const [viewCheckboxes, setViewCheckboxes] = useState<ICheckbox[]>(
const {
setApartmentTypeCheckboxes,
setViewCheckboxes,
setMultirangeSliders,
setSwitchers,
} = useMasterplanFilters();
const [localApartmentTypeCheckboxes, setLocalApartmentTypeCheckboxes] =
useState<ICheckbox[]>(initialAparmentTypeCheckboxes);
const [localViewCheckboxes, setLocalViewCheckboxes] = useState<ICheckbox[]>(
initialViewCheckboxes
);
const [switchers, setSwitchers] = useState(initialSwitchers);
const [multirangeSliders, setMultirangeSliders] = useState(initialSliders);
const [localSwitchers, setLocalSwitchers] = useState(initialSwitchers);
const [localMultirangeSliders, setLocalMultirangeSliders] =
useState(initialSliders);
const handlers = useSwipeable({
onSwipedDown: () => handleOnCrossClick(),
});
@@ -42,49 +51,49 @@ const MasterplanFiltersModal = () => {
};
const handleOnCheckboxApartmentTypeClick = (checkboxId: string) => {
const updatedCheckboxes = apartmentTypeCheckboxes.map((cbox) => {
const updatedCheckboxes = localApartmentTypeCheckboxes.map((cbox) => {
if (checkboxId !== cbox.id) return cbox;
const isSelected = !cbox.selected;
return { ...cbox, selected: isSelected };
});
setApartmentTypeCheckboxes(updatedCheckboxes);
setLocalApartmentTypeCheckboxes(updatedCheckboxes);
};
const handleOnSwitcherClick = (switcherId: string) => {
const updatedSwitchers = switchers.map((switcher) => {
const updatedSwitchers = localSwitchers.map((switcher) => {
if (switcherId !== switcher.id) return switcher;
const { isSwitched } = switcher;
return { ...switcher, isSwitched: !isSwitched };
});
setSwitchers(updatedSwitchers);
setLocalSwitchers(updatedSwitchers);
};
const handleOnSliderValueChange = (
sliderId: string,
e: [a: number, b: number]
) => {
const updatedSliders = multirangeSliders.map((slider) => {
const updatedSliders = localMultirangeSliders.map((slider) => {
if (sliderId !== slider.id) return slider;
return { ...slider, startValue: e[0], endValue: e[1] };
});
setMultirangeSliders(updatedSliders);
setLocalMultirangeSliders(updatedSliders);
};
const handleOnViewCheckboxClick = (checkboxId: string) => {
const updatedCheckboxes = viewCheckboxes.map((cbox) => {
const updatedCheckboxes = localViewCheckboxes.map((cbox) => {
if (checkboxId !== cbox.id) return cbox;
const isSelected = !cbox.selected;
return { ...cbox, selected: isSelected };
});
setViewCheckboxes(updatedCheckboxes);
setLocalViewCheckboxes(updatedCheckboxes);
};
const handleOnShowApartmentClick = () => {
@@ -92,16 +101,21 @@ const MasterplanFiltersModal = () => {
setIsAnimate(false);
const timeout = setTimeout(() => {
setModal(null);
setApartmentTypeCheckboxes(localApartmentTypeCheckboxes);
setViewCheckboxes(localViewCheckboxes);
setMultirangeSliders(localMultirangeSliders);
setSwitchers(localSwitchers);
clearTimeout(timeout);
}, 300);
}
};
const handleOnResetClick = () => {
setViewCheckboxes(initialViewCheckboxes);
setSwitchers(initialSwitchers);
setMultirangeSliders(initialSliders);
setApartmentTypeCheckboxes(initialAparmentTypeCheckboxes);
setLocalViewCheckboxes(initialViewCheckboxes);
setLocalSwitchers(initialSwitchers);
setLocalMultirangeSliders(initialSliders);
setLocalApartmentTypeCheckboxes(initialAparmentTypeCheckboxes);
};
return (
@@ -124,7 +138,7 @@ const MasterplanFiltersModal = () => {
<div className="flex flex-col w-full">
<p className="text-[#0D1922] text-s pb-4">Apartment type</p>
<div className="grid grid-cols-2 gap-2">
{apartmentTypeCheckboxes.map((checkbox) => (
{localApartmentTypeCheckboxes.map((checkbox) => (
<Checkbox
checkbox={checkbox}
key={checkbox.id}
@@ -134,7 +148,7 @@ const MasterplanFiltersModal = () => {
</div>
</div>
<div className="grid grid-cols-2 gap-6 border-b pb-12">
{multirangeSliders.map((slider) => (
{localMultirangeSliders.map((slider) => (
<div className="flex flex-col gap-3">
<div className="flex justify-between items-center">
<p className="text-[#0D1922] text-s ">{slider.title}</p>
@@ -147,7 +161,7 @@ const MasterplanFiltersModal = () => {
</div>
))}
<div className="flex flex-col gap-2 pt-6">
{switchers.map((switcher) => (
{localSwitchers.map((switcher) => (
<div key={switcher.id} className="flex justify-between w-full">
<p className="text-s text-[#73787C]">{switcher.title}</p>
<Switch switcher={switcher} onClick={handleOnSwitcherClick} />
@@ -158,7 +172,7 @@ const MasterplanFiltersModal = () => {
<div className="flex flex-col w-full">
<p className="text-[#0D1922] text-s pb-4">Views</p>
<div className="grid grid-cols-2 gap-2">
{viewCheckboxes.map((checkbox) => (
{localViewCheckboxes.map((checkbox) => (
<Checkbox
checkbox={checkbox}
key={checkbox.id}
@@ -19,9 +19,13 @@ export const MobileModalWrapperContext =
interface MobileModalWrapperProps {
children: React.ReactNode;
isHeightScreen?: boolean;
}
const MobileModalWrapper = ({ children }: MobileModalWrapperProps) => {
const MobileModalWrapper = ({
children,
isHeightScreen = false,
}: MobileModalWrapperProps) => {
const [isAnimate, setIsAnimate] = useState(false);
useEffect(() => {
@@ -30,8 +34,10 @@ const MobileModalWrapper = ({ children }: MobileModalWrapperProps) => {
return (
<div
className={`h-screen w-screen pt-20 absolute z-[99999999] top-0 transition-all duration-300 ease-in-out ${
isAnimate ? "backdrop-blur-sm bg-[#0D192266]" : "backdrop-blur-none"
className={`h-screen w-screen ${
isHeightScreen ? "" : "pt-20"
} absolute z-[99999998] top-0 transition-all duration-300 ease-in-out ${
isAnimate ? "" : "backdrop-blur-none"
}`}
>
<div
@@ -0,0 +1,148 @@
import { useState, useEffect } from "react";
import { useSwipeable } from "react-swipeable";
import useModal from "../../../store/useModal";
import MinusIcon from "../../icons/MinusIcon";
import LayoutSlider from "../../complexWingPage/SkygardenSidebar/LayoutSlider";
import ActivityCard from "../../complexWingPage/SkygardenSidebar/ActivityCard";
import AmphitheatreIcon from "../../icons/activities/AmphitheatreIcon";
import BoulderingWallIcon from "../../icons/activities/BoulderingWallIcon";
import ChangingRoomsIcon from "../../icons/activities/ChangingRoomsIcon";
import ChessTablesIcon from "../../icons/activities/ChessTablesIcon";
import ClimbingRoomIcon from "../../icons/activities/ClimbingRoomIcon";
import CommunalDiningTablesIcon from "../../icons/activities/CommunalDiningTablesIcon";
import IndoorLapPoolIcon from "../../icons/activities/IndoorLapPoolIcon";
import LushLandscapeIcon from "../../icons/activities/LushLandscapeIcon";
import MultiPurposeCourtIcon from "../../icons/activities/MultiPurposeCourtIcon";
import OutdoorCinemaIcon from "../../icons/activities/OutdoorCinemaIcon";
import OutdoorCoworkingSpaceIcon from "../../icons/activities/OutdoorCoworkingSpaceIcon";
import PadelPongIcon from "../../icons/activities/PadelPongIcon";
import PingPongInATableIcon from "../../icons/activities/PingPongInATableIcon";
import RunningWheelIcon from "../../icons/activities/RunningWheelIcon";
import SunLoungingDeckIcon from "../../icons/activities/SunLoungingDeckIcon";
import SuspendedLoungingNetsIcon from "../../icons/activities/SuspendedLoungingNetsIcon";
import WellnessFeaturesIcon from "../../icons/activities/WellnessFeaturesIcon";
import ZoneSlider from "../../complexWingPage/SkygardenSidebar/ZoneSlider";
const SkygardenModal = () => {
const { setModal } = useModal();
const [isAnimate, setIsAnimate] = useState(false);
const handleOnClose = () => {
if (setIsAnimate) {
setIsAnimate(false);
const timeout = setTimeout(() => {
setModal(null);
clearTimeout(timeout);
}, 300);
}
};
const handlers = useSwipeable({
onSwipedDown: () => handleOnClose(),
});
useEffect(() => {
setIsAnimate(true);
}, []);
return (
<div
className={`h-[calc(100vh-64px)] w-screen pt-[128px] absolute z-[99999999] top-0 duration-300 ease-in-out `}
>
<div
className={`flex flex-col text-white px-4 pb-6 transition-opacity duration-300 ease-in-out ${
isAnimate ? "opacity-100" : "opacity-0"
}`}
>
<p className="text-subheadline-s font-semibold">
Rove Home Marasi Drive
</p>
<p className="text-s">Skygarden</p>
</div>
<div
style={{ transform: `translateY(${isAnimate ? 0 : 100}%)` }}
className="bg-[#F3F3F2] h-fit p-6 pt-0 flex flex-col gap-6 transition-transform ease-in-out relative"
>
<div
className="w-[calc(100%-48px)] absolute flex justify-center py-3"
{...handlers}
>
<MinusIcon />
</div>
<div className="pt-6 flex justify-between items-center">
<div className="flex flex-col">
<h2 className="font-semibold text-[#0D1922] text-subheadline-m">
Skygarden
</h2>
<p className="text-s">22-23 floor</p>
</div>
<div className="py-[3px] px-2 text-white bg-[#00BED7] rounded-full text-caption-m">
17 amenties
</div>
</div>
<div className="h-fit w-full bg-white rounded-lg flex justify-center items-center">
<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">
<LayoutSlider />
</div>
</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>
<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>
<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>
</div>
<ZoneSlider />
</div>
);
};
export default SkygardenModal;
@@ -1,11 +1,73 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useSwipeable } from "react-swipeable";
import useModal from "../../../store/useModal";
import { useEffect, useState } from "react";
import MinusIcon from "../../icons/MinusIcon";
import { IAparmentRes } from "../../../types/apartmentsRes";
import { IDesctiptionFloor } from "../../../types/descriptionFloor";
import { apartmentsWithoutVirtualTour } from "../../../consts/apartmentsWithoutVirtualTour";
import EastWingHighlighting from "../../complexWingPage/FloorSidebar/EastWingHighlighting";
import EastWingLayout from "../../complexWingPage/FloorSidebar/EastWingLayout";
import WestWingHighlighting from "../../complexWingPage/FloorSidebar/WestWingHighlighting";
import WestWingLayout from "../../complexWingPage/FloorSidebar/WestWingLayout";
import WestWingTopLevelsHighlighting from "../../complexWingPage/FloorSidebar/WestWingTopLevelsHighlighting";
import WestWingTopLevelsLayout from "../../complexWingPage/FloorSidebar/WestWingTopLevelsLayout";
import { filterCurrentApartment } from "../../../calc/filterCurrentApartment";
import MobileApartmentDescription from "../../complexWingPage/MobileApartmentDescription";
const WingFloorModal = () => {
const getDefaultApartments = (currentFloor: IDesctiptionFloor | null) => {
if (!currentFloor) return [];
const defaultApartment: IAparmentRes[] = apartmentsWithoutVirtualTour.map(
(aprt, index) => {
const unitNo = `${currentFloor?.wing.slice(0, 1)}-${
currentFloor.floor
}0${index}`;
return {
id: unitNo,
Floor: currentFloor.floor,
Property_Status: "Available",
Unit_Type: aprt.type,
Project_Name: "Rove Home Marasi Drive",
Suite_Area_Sqft: 0,
Balcony_Area_Sqft: 0,
No_Of_Bedrooms: 1,
Unit_No: unitNo,
Total_Area_Sqft: 0,
No_of_Bathrooms: 0,
Property_Name: "-",
Unit_View: "-",
};
}
);
return defaultApartment;
};
interface WingFloorModalProps {
currentFloor: IDesctiptionFloor | null;
floorApartments: IAparmentRes[];
}
const WingFloorModal = ({
currentFloor,
floorApartments,
}: WingFloorModalProps) => {
const { setModal } = useModal();
const [isAnimate, setIsAnimate] = useState(false);
const [apartments, setApartments] = useState<IAparmentRes[]>([]);
const [currentApartmentType, setCurrentApartmentType] = useState<
string | null
>(null);
const [currentApartment, setCurrentApartment] = useState<IAparmentRes | null>(
null
);
const [isDescVisible, setIsDescVisible] = useState(false);
const [mousePos, setMousePos] = useState<number[]>([0, 0]);
const wing =
floorApartments.length > 0 &&
floorApartments[0].Unit_No.split("-")[0] === "E"
? "East Wing"
: "West Wing";
const handleOnClose = () => {
if (setIsAnimate) {
@@ -17,85 +79,194 @@ const WingFloorModal = () => {
}
};
function handleOnApartmentClick(
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) {
const apartmentType = event.currentTarget.dataset.type;
if (!apartmentType) {
return;
}
setCurrentApartmentType(apartmentType);
// const apartments = [
// ...getDefaultApartments(currentFloor),
// ...floorApartments,
// ];
// console.log("apartments", apartments);
const apartment = filterCurrentApartment(apartments, apartmentType);
if (!apartment) return;
setCurrentApartment(apartment);
setIsDescVisible(true);
}
const handlers = useSwipeable({
onSwipedDown: () => handleOnClose(),
});
function handleMouseClick(
event: React.MouseEvent<SVGSVGElement, MouseEvent> | any
) {
const isApartmentClicked = event.target.parentElement.dataset.type;
if (!isApartmentClicked) {
setIsDescVisible(false);
} else {
const scrollOffsetY = window.scrollY;
//detect mouse pos
const y = event.clientY - 65 + scrollOffsetY - 205;
const x = event.clientX - 50;
setMousePos([x, y]);
}
}
useEffect(() => {
if (!currentFloor) return;
const defaultApartment: IAparmentRes[] = getDefaultApartments(currentFloor);
setApartments([...defaultApartment, ...floorApartments]);
}, [currentFloor, currentFloor?.floor, currentFloor?.wing, floorApartments]);
useEffect(() => {
setIsAnimate(true);
}, []);
useEffect(() => {
window.addEventListener("mousemove", handleMouseClick);
return () => {
window.removeEventListener("mousemove", handleMouseClick);
};
}, []);
return (
<div
className={`h-[calc(100vh-64px)] w-screen pt-[128px] absolute z-[99999999] top-0 duration-300 ease-in-out `}
>
<>
<div
className={`flex flex-col text-white px-4 pb-6 transition-opacity duration-300 ease-in-out ${
isAnimate ? "opacity-100" : "opacity-0"
}`}
>
<p className="text-subheadline-s font-semibold">
Rove Home Marasi Drive
</p>
<p className="text-s">11 floor</p>
</div>
<div
style={{ transform: `translateY(${isAnimate ? 0 : 100}%)` }}
className="bg-[#F3F3F2] h-fit p-6 pt-0 flex flex-col gap-6 transition-transform ease-in-out relative"
className={`h-[calc(100vh-64px)] w-screen pt-[128px] absolute z-[99999997] top-0 duration-300 ease-in-out overflow-x-clip`}
>
{isDescVisible && (
<div
className="absolute z-[99999999] w-fit h-fit top-0 left-0"
style={{ top: `${mousePos[1]}px`, left: `${mousePos[0]}px` }}
>
<MobileApartmentDescription
apartment={currentApartment}
apartmentDataType={currentApartmentType}
apartments={apartments}
floor={currentFloor}
/>
</div>
)}
<div
className="w-[calc(100%-48px)] absolute flex justify-center py-3"
{...handlers}
className={`flex flex-col text-white px-4 pb-6 transition-opacity duration-300 ease-in-out ${
isAnimate ? "opacity-100" : "opacity-0"
}`}
>
<MinusIcon />
<p className="text-subheadline-s font-semibold">
Rove Home Marasi Drive
</p>
<p className="text-s">{currentFloor?.floor} floor</p>
</div>
<div className="pt-6 flex justify-between items-center">
<div className="flex flex-col">
<h2 className="font-semibold text-[#0D1922] text-subheadline-m">
11 floor
</h2>
<p className="text-s">East Wing</p>
<div
style={{ transform: `translateY(${isAnimate ? 0 : 100}%)` }}
className="bg-[#F3F3F2] h-fit p-6 pt-0 flex flex-col gap-6 transition-transform ease-in-out relative"
>
<div
className="w-[calc(100%-48px)] absolute flex justify-center py-3"
{...handlers}
>
<MinusIcon />
</div>
<div className="py-[3px] px-2 text-white bg-[#00BED7] rounded-full text-caption-m">
22 units
</div>
</div>
<div className="flex justify-between items-center py-2 px-4 rounded-lg bg-white">
<div>11 floor</div>
<div className="flex items-center justify-center gap-6">
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#A19E9E] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
1
</div>
<p className="text-caption-m font-semibold">Studio flex</p>
<div className="pt-6 flex justify-between items-center">
<div className="flex flex-col">
<h2 className="font-semibold text-[#0D1922] text-subheadline-m">
{currentFloor?.floor} floor
</h2>
<p className="text-s">{wing}</p>
</div>
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#8299AD] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
11
</div>
<p className="text-caption-m font-semibold">Studio</p>
</div>
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#BFC9D1] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
3
</div>
<p className="text-caption-m font-semibold">1 Bedroom</p>
</div>
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#878FA3] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
7
</div>
<p className="text-caption-m font-semibold">2 Bedroom</p>
<div className="py-[3px] px-2 text-white bg-[#00BED7] rounded-full text-caption-m">
{floorApartments.length} units
</div>
</div>
</div>
<div className="h-fit w-full bg-white rounded-lg flex justify-center items-center">
<div className="">
<img src="/images/floor-apartment-layout.png" alt="" />
<div className="flex justify-between items-center py-2 px-4 rounded-lg bg-white">
<div>{currentFloor?.floor} floor</div>
<div className="flex items-center justify-center gap-6">
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#A19E9E] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
1
</div>
<p className="text-caption-m font-semibold">Studio flex</p>
</div>
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#8299AD] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
11
</div>
<p className="text-caption-m font-semibold">Studio</p>
</div>
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#BFC9D1] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
3
</div>
<p className="text-caption-m font-semibold">1 Bedroom</p>
</div>
<div className="flex gap-2 text-[#0D1922B2] items-center">
<div className="w-5 h-5 flex items-center bg-[#878FA3] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
7
</div>
<p className="text-caption-m font-semibold">2 Bedroom</p>
</div>
</div>
</div>
<div className="px-10 bg-white flex gap-6 font-semibold text-caption-m rounded-2xl justify-center items-center flex-1 py-4 overflow-clip">
{currentFloor?.wing === "West Wing" ? (
currentFloor && currentFloor.floor <= 21 ? (
<svg
className="rotate-[135deg]"
xmlns="http://www.w3.org/2000/svg"
width="400"
height="500"
fill="none"
viewBox="0 0 204 600"
>
<WestWingLayout />
<WestWingHighlighting
handleOnApartmentClick={handleOnApartmentClick}
/>
</svg>
) : (
<svg
className="rotate-[135deg]"
xmlns="http://www.w3.org/2000/svg"
width="400"
height="700"
fill="none"
viewBox="0 0 204 600"
>
<WestWingTopLevelsLayout />
<WestWingTopLevelsHighlighting
handleOnApartmentClick={handleOnApartmentClick}
/>
</svg>
)
) : (
<svg
className="rotate-[135deg]"
xmlns="http://www.w3.org/2000/svg"
fill="none"
width="672"
height="700"
viewBox="0 0 672 280"
>
<EastWingLayout />
<EastWingHighlighting
handleOnApartmentClick={handleOnApartmentClick}
/>
</svg>
)}
</div>
</div>
</div>
</div>
</>
);
};
+1 -1
View File
@@ -1,2 +1,2 @@
PORT=4002
PORT=4003
REFRESH_TOKEN=1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b