376 lines
13 KiB
TypeScript
376 lines
13 KiB
TypeScript
/* 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";
|
|
import TransparentSelector from "../../TransparentSelector";
|
|
import { IOption } from "../../../types/selectorOption";
|
|
|
|
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 [optionsFloors, setOptionsFloors] = useState<IOption[]>([]);
|
|
const wing =
|
|
floorApartments.length > 0 &&
|
|
floorApartments[0].Unit_No.split("-")[0] === "E"
|
|
? "East Wing"
|
|
: "West Wing";
|
|
|
|
const handleOnClose = () => {
|
|
if (setIsAnimate) {
|
|
setIsAnimate(false);
|
|
const timeout = setTimeout(() => {
|
|
setModal(null);
|
|
clearTimeout(timeout);
|
|
}, 300);
|
|
}
|
|
};
|
|
|
|
function handleOnApartmentClick(
|
|
event: React.MouseEvent<SVGSVGElement, MouseEvent>
|
|
) {
|
|
const apartmentType = event.currentTarget.dataset.type;
|
|
if (!apartmentType) {
|
|
return;
|
|
}
|
|
|
|
setCurrentApartmentType(apartmentType);
|
|
|
|
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 - 650;
|
|
const x = event.clientX - 140;
|
|
// const x = event.clientX - 50;
|
|
setMousePos([x, y]);
|
|
}
|
|
}
|
|
|
|
const handleOnFloorOptionClick = (floorId: string) => {
|
|
const updatedOptions = [...optionsFloors].map((floor) => {
|
|
return { ...floor, isSelected: floor.id === floorId };
|
|
});
|
|
setOptionsFloors(updatedOptions);
|
|
};
|
|
|
|
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);
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (!currentFloor) return;
|
|
const { floor: selectedFloor } = currentFloor;
|
|
|
|
if (selectedFloor === 11) {
|
|
const floors = Array.from({ length: 4 }).map((_, index) => {
|
|
const floor: IOption = {
|
|
isSelected: index + 11 === 11,
|
|
value: `${index + 11}`,
|
|
id: `${index + 11}`,
|
|
};
|
|
return floor;
|
|
});
|
|
setOptionsFloors(floors);
|
|
return;
|
|
}
|
|
|
|
if (selectedFloor === 31) {
|
|
const floors = Array.from({ length: 4 }).map((_, index) => {
|
|
const floor: IOption = {
|
|
isSelected: index + 28 === 31,
|
|
value: `${index + 28}`,
|
|
id: `${index + 28}`,
|
|
};
|
|
return floor;
|
|
});
|
|
setOptionsFloors(floors);
|
|
return;
|
|
}
|
|
|
|
const floors = Array.from({ length: 4 }).map((_, index) => {
|
|
const floorIndex = selectedFloor - 1 + index;
|
|
const floor: IOption = {
|
|
isSelected: floorIndex === selectedFloor,
|
|
value: `${index - 1 + selectedFloor}`,
|
|
id: `${index - 1 + selectedFloor}`,
|
|
};
|
|
return floor;
|
|
});
|
|
|
|
setOptionsFloors(floors);
|
|
}, [currentFloor]);
|
|
|
|
return (
|
|
<>
|
|
<div
|
|
className={`h-[calc(100vh-78.75px)] w-screen pt-[157.5px] 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={`flex flex-col text-white px-4 pb-6 transition-opacity duration-300 ease-in-out h-[405px] pt-[202.5px] ${
|
|
isAnimate ? "opacity-100" : "opacity-0"
|
|
}`}
|
|
>
|
|
<p className="text-subheadline-s font-semibold">
|
|
Rove Home Marasi Drive
|
|
</p>
|
|
<p className="text-s">{currentFloor?.floor} floor</p>
|
|
</div>
|
|
<div
|
|
style={{ transform: `translateY(${isAnimate ? 0 : 100}%)` }}
|
|
className="bg-[#F3F3F2] h-full p-6 pt-0 flex flex-col gap-6 transition-transform ease-in-out relative"
|
|
>
|
|
<div
|
|
className="w-[calc(100%-135px)] absolute flex justify-center py-3"
|
|
{...handlers}
|
|
>
|
|
<div className="zoom-280">
|
|
<MinusIcon />
|
|
</div>
|
|
</div>
|
|
<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="py-[8.44px] px-2 text-white bg-[#00BED7] rounded-full text-caption-m">
|
|
{floorApartments.length} units
|
|
</div>
|
|
</div>
|
|
<div className="flex justify-between items-center py-2 px-4 rounded-lg bg-white">
|
|
<TransparentSelector
|
|
options={optionsFloors}
|
|
onClick={handleOnFloorOptionClick}
|
|
/>
|
|
<div className="flex items-center justify-center gap-6">
|
|
<div className="flex gap-2 text-[#0D1922B2] items-center">
|
|
<div className="w-[48px] h-[48px] text-caption-m flex items-center bg-[#A19E9E] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
|
|
{
|
|
floorApartments.filter(
|
|
(aprt) => aprt.Unit_Type === "Studio Flex"
|
|
).length
|
|
}
|
|
</div>
|
|
<p className="text-caption-m font-semibold">Studio flex</p>
|
|
</div>
|
|
<div className="flex gap-2 text-[#0D1922B2] items-center">
|
|
<div className="w-[48px] h-[48px] text-caption-m flex items-center bg-[#8299AD] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
|
|
{
|
|
floorApartments.filter(
|
|
(aprt) => aprt.Unit_Type === "Studio Squared"
|
|
).length
|
|
}
|
|
</div>
|
|
<p className="text-caption-m font-semibold">Studio</p>
|
|
</div>
|
|
<div className="flex gap-2 text-[#0D1922B2] items-center">
|
|
<div className="w-[48px] h-[48px] text-caption-m flex items-center bg-[#BFC9D1] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
|
|
{
|
|
floorApartments.filter(
|
|
(aprt) => aprt.Unit_Type === "1 BR Squared"
|
|
).length
|
|
}
|
|
</div>
|
|
<p className="text-caption-m font-semibold">1 Bedroom</p>
|
|
</div>
|
|
<div className="flex gap-2 text-[#0D1922B2] items-center">
|
|
<div className="w-[48px] h-[48px] text-caption-m flex items-center bg-[#878FA3] text-white justify-center rounded-full pt-[1.5px] pb-[2.5px]">
|
|
{
|
|
floorApartments.filter(
|
|
(aprt) => aprt.Unit_Type === "2 BR Squared"
|
|
).length
|
|
}
|
|
</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 py-4 overflow-clip">
|
|
{currentFloor?.wing === "West Wing" ? (
|
|
currentFloor && currentFloor.floor <= 21 ? (
|
|
<svg
|
|
className="rotate-[135deg] zoom-280"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="400"
|
|
height="700"
|
|
fill="none"
|
|
viewBox="0 0 204 600"
|
|
>
|
|
<WestWingLayout />
|
|
<WestWingHighlighting
|
|
handleOnApartmentClick={handleOnApartmentClick}
|
|
/>
|
|
</svg>
|
|
) : (
|
|
<svg
|
|
className="rotate-[135deg] zoom-280"
|
|
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] zoom-280"
|
|
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>
|
|
</>
|
|
);
|
|
};
|
|
|
|
// const TransparentSelector = ({
|
|
// options,
|
|
// setOptions,
|
|
// }: TransparentSelectorProps) => {
|
|
// const [isOpened, setIsOpened] = useState(false);
|
|
// const handleOnClick = () => {
|
|
// setIsOpened((prev) => !prev);
|
|
// };
|
|
|
|
// return (
|
|
// <div className="relative">
|
|
// <div
|
|
// className="text-[#00BED7] text-[38.4px] flex gap-[19.2px] items-center justify-center cursor-pointer select-none"
|
|
// onClick={handleOnClick}
|
|
// >
|
|
// <p>11 floor</p>
|
|
// <div
|
|
// className={`zoom-280 ease-in-out duration-300 transition-transform ${
|
|
// isOpened ? "-rotate-180" : ""
|
|
// }`}
|
|
// >
|
|
// <ChevronDownIcon />
|
|
// </div>
|
|
// </div>
|
|
// {isOpened && (
|
|
// <div className="flex flex-col bg-black p-[19.2px] absolute -bottom-[49px]">
|
|
// {options.map}
|
|
// </div>
|
|
// )}
|
|
// </div>
|
|
// );
|
|
// };
|
|
|
|
export default WingFloorModal;
|