465 lines
14 KiB
TypeScript
465 lines
14 KiB
TypeScript
/* 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 {
|
|
laptopWidth,
|
|
mobileWidht,
|
|
descriptions,
|
|
} from "../../../consts/masterplan";
|
|
import { updateAccessToken } from "../../../api/updateAccessToken";
|
|
import { IAparmentRes } from "../../../types/apartmentsRes";
|
|
import useMasterplanFilters from "../../../store/useMasterplanFilters";
|
|
import { initialRoveHomeCheckboxes } from "../../../consts/initialMasterplanFilters";
|
|
import { pageInitial } from "../../../consts/initialMasterplanFilters";
|
|
import { useDebounce } from "@uidotdev/usehooks";
|
|
import { getFilteredApartments } from "../../../calc/getFilteredApartments";
|
|
import LoaderModal from "../../modals/LoaderModal";
|
|
import FloorNumbers from "./FloorNumbers";
|
|
import WingSignatures from "./WingSignatures";
|
|
import { isMobile } from "react-device-detect";
|
|
import FloorsHighlighting from "./FloorsHighlighting";
|
|
import MobileFloorDescription from "./MobileFloorDescription";
|
|
import WingFloorModal from "../../modals/mobile/WingFloorModal";
|
|
import MobileSkygardenDescription from "./MobileSkygardenDescription";
|
|
|
|
const skyGardenFloor = 22;
|
|
|
|
const SequenceWing = () => {
|
|
const [width, setWidth] = useState<number>(0);
|
|
const [top, setTop] = useState<number>(0);
|
|
const [left, setLeft] = useState<number>(0);
|
|
const { isSidebar, setIsSidebar } = useWingSidebar();
|
|
const [mousePos, setMousePos] = useState<[number, number]>([0, 0]);
|
|
const [currentHoveredFloor, setHoverCurrentFloor] =
|
|
useState<null | IDesctiptionFloor>(null);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [currentFloor, setCurrentFloor] = useState<IDesctiptionFloor | null>(
|
|
null
|
|
);
|
|
const [isWrapperHovered, setIsWrapperHovered] = useState(false);
|
|
const [isSkygardenSidebar, setIsSkygardenSidebar] = useState(false);
|
|
const [isFloorSidebar, setIsFloorSidebar] = useState(false);
|
|
const { setModal } = useModal();
|
|
const [apartments, setApartments] = useState<IAparmentRes[]>([]);
|
|
const [currentHoveredApartments, setCurrentHoveredApartments] = useState<
|
|
IAparmentRes[]
|
|
>([]);
|
|
const [selectedApartments, setSelectedApartments] = useState<IAparmentRes[]>(
|
|
[]
|
|
);
|
|
const [isLeft, setIsLeft] = useState(false);
|
|
|
|
const {
|
|
apartmentTypeCheckboxes,
|
|
switchers,
|
|
multirangeSliders,
|
|
viewCheckboxes,
|
|
sortList,
|
|
} = useMasterplanFilters();
|
|
const debouncedSliders = useDebounce(multirangeSliders, 300);
|
|
|
|
const handleOnFloorMouseEnter = (
|
|
e: React.MouseEvent<SVGPathElement, MouseEvent>
|
|
) => {
|
|
e.stopPropagation();
|
|
const id = e.currentTarget.dataset.id;
|
|
if (!id) return;
|
|
const _currentFloor = descriptions.find((desc) => desc.id === id);
|
|
if (!_currentFloor) return;
|
|
setHoverCurrentFloor(_currentFloor);
|
|
const _currentHoveredApartments = apartments.filter((apartment) => {
|
|
const wing =
|
|
apartment.Unit_No.split("-")[0] === "E" ? "East Wing" : "West Wing";
|
|
return (
|
|
apartment.Floor === _currentFloor.floor && wing === _currentFloor.wing
|
|
);
|
|
});
|
|
setIsWrapperHovered(true);
|
|
setCurrentHoveredApartments(_currentHoveredApartments);
|
|
};
|
|
|
|
const handleOnWingWrapperMouseEnter = (
|
|
e: React.MouseEvent<SVGSVGElement>
|
|
) => {
|
|
(e as unknown as Event).stopPropagation();
|
|
setIsWrapperHovered(true);
|
|
};
|
|
const handleOnWingWrapperMouseLeave = () => {
|
|
setIsWrapperHovered(false);
|
|
};
|
|
|
|
const handleOnFloorClick = () => {
|
|
if (!currentHoveredFloor && !currentHoveredApartments) return;
|
|
setCurrentFloor(currentHoveredFloor);
|
|
setSelectedApartments(currentHoveredApartments);
|
|
|
|
const screenWidth = window.innerWidth;
|
|
|
|
const isMobile = screenWidth <= mobileWidht;
|
|
if (isMobile) return;
|
|
// <640
|
|
setIsFloorSidebar(true);
|
|
setIsSkygardenSidebar(false);
|
|
setIsSidebar(true);
|
|
};
|
|
|
|
const handleOnSkygardenClick = () => {
|
|
if (!isMobile) {
|
|
setIsSkygardenSidebar(true);
|
|
setIsFloorSidebar(false);
|
|
setIsSidebar(true);
|
|
} else {
|
|
// setModal(<WingFloorModal />);
|
|
}
|
|
};
|
|
|
|
const handleMouseMove = (
|
|
e: MouseEvent<Element, MouseEvent<Element, MouseEvent>> | any
|
|
) => {
|
|
const screenWidth = window.innerWidth;
|
|
const _isLeft = e.clientX > screenWidth / 2;
|
|
setIsLeft(_isLeft);
|
|
// <640
|
|
if (screenWidth <= mobileWidht) return;
|
|
|
|
// const _top = screenHeight / 16;
|
|
if (screenWidth > laptopWidth) {
|
|
const x = _isLeft ? e.clientX - 795 : e.clientX - 384;
|
|
setMousePos([x, e.clientY + top - 25]);
|
|
} else {
|
|
// 640-1072
|
|
if (screenWidth > mobileWidht) {
|
|
const x = _isLeft ? e.clientX + left - 800 : e.clientX - 385 + left;
|
|
setMousePos([x, e.clientY + top - 25]);
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleOnMouseDown = (
|
|
e: MouseEvent<Element, MouseEvent<Element, MouseEvent>> | any
|
|
) => {
|
|
const isFloorClicked = Boolean(e.target.dataset.id);
|
|
if (!isFloorClicked) return;
|
|
const screenWidth = window.innerWidth;
|
|
const _isLeft = e.clientX > screenWidth / 2;
|
|
setIsLeft(_isLeft);
|
|
|
|
if (screenWidth > mobileWidht) return;
|
|
// <640
|
|
|
|
const x = _isLeft ? e.clientX - 724 + left : e.clientX - 444 + left;
|
|
|
|
setMousePos([x, e.clientY + Math.abs(top) + 20]);
|
|
};
|
|
|
|
// function handleOnMouseDown(e: MouseEvent | any) {
|
|
// 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]);
|
|
// // setMousePos([e.clientX - 444 + _left, e.clientY + Math.abs(_top) + 30]);
|
|
// // <640
|
|
// } else {
|
|
// const _top = screenHeight / 2.5;
|
|
// const _left = laptopWidth - screenWidth;
|
|
// setMousePos([e.clientX - 440 + _left, e.clientY + Math.abs(_top) + 20]);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
function handleResize() {
|
|
const screenWidth = window.innerWidth;
|
|
const screenHeight = window.innerHeight;
|
|
if (screenWidth > laptopWidth) {
|
|
setWidth(screenWidth);
|
|
setTop(screenWidth / 2 - screenHeight / 2);
|
|
setLeft(0);
|
|
} else {
|
|
if (screenWidth > mobileWidht) {
|
|
const _top = screenHeight / 16;
|
|
setTop(_top);
|
|
} else {
|
|
const _top = screenHeight / 5.5;
|
|
setTop(_top);
|
|
}
|
|
const _left = (laptopWidth - screenWidth) * 1.1;
|
|
const _width = screenWidth + _left * 1.9;
|
|
|
|
setWidth(_width);
|
|
setLeft(_left);
|
|
}
|
|
}
|
|
|
|
const handleOnExploreFloorClick = (
|
|
e: MouseEvent<Element, MouseEvent<Element, MouseEvent>> | any
|
|
) => {
|
|
e.stopPropagation();
|
|
// if (!currentHoveredFloor) return;
|
|
setModal(
|
|
<WingFloorModal
|
|
currentFloor={currentHoveredFloor}
|
|
floorApartments={currentHoveredApartments}
|
|
/>
|
|
);
|
|
};
|
|
|
|
const handleOnExploreSkygardenClick = (
|
|
e: MouseEvent<Element, MouseEvent<Element, MouseEvent>> | any
|
|
) => {
|
|
e.stopPropagation();
|
|
// if (!currentHoveredFloor) return;
|
|
setModal(
|
|
<WingFloorModal
|
|
currentFloor={currentHoveredFloor}
|
|
floorApartments={currentHoveredApartments}
|
|
/>
|
|
);
|
|
};
|
|
|
|
useEffect(() => {
|
|
handleResize();
|
|
window.addEventListener("resize", handleResize);
|
|
window.addEventListener("mousemove", handleMouseMove);
|
|
window.addEventListener("mousedown", handleOnMouseDown);
|
|
return () => {
|
|
window.removeEventListener("resize", handleResize);
|
|
window.removeEventListener("mousemove", handleMouseMove);
|
|
window.removeEventListener("mousedown", handleOnMouseDown);
|
|
};
|
|
}, [handleMouseMove]);
|
|
|
|
useEffect(() => {
|
|
if (!isSidebar) {
|
|
setIsFloorSidebar(false);
|
|
setIsSkygardenSidebar(false);
|
|
}
|
|
}, [isSidebar]);
|
|
|
|
useEffect(() => {
|
|
const localStorageToken = `${localStorage.getItem("ACCESS_TOKEN")}`;
|
|
const perPage = 1000;
|
|
const getApartments = (token: string) =>
|
|
getFilteredApartments(
|
|
token,
|
|
setApartments,
|
|
initialRoveHomeCheckboxes,
|
|
apartmentTypeCheckboxes,
|
|
debouncedSliders,
|
|
switchers,
|
|
viewCheckboxes,
|
|
sortList,
|
|
pageInitial,
|
|
perPage
|
|
);
|
|
|
|
setIsLoading(true);
|
|
|
|
getApartments(localStorageToken)
|
|
.then(() => {
|
|
setIsLoading(false);
|
|
})
|
|
.catch((error) => {
|
|
const errorStatus = error.response.status;
|
|
|
|
if (errorStatus === 401) {
|
|
updateAccessToken()
|
|
.then((token) => {
|
|
if (token) {
|
|
getApartments(token).then(() => {
|
|
setIsLoading(false);
|
|
});
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
setIsLoading(false);
|
|
console.error("error", error);
|
|
});
|
|
} else {
|
|
setIsLoading(false);
|
|
console.error("error", error);
|
|
}
|
|
});
|
|
}, [
|
|
setApartments,
|
|
apartmentTypeCheckboxes,
|
|
debouncedSliders,
|
|
switchers,
|
|
viewCheckboxes,
|
|
sortList,
|
|
]);
|
|
|
|
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 sm:block hidden"
|
|
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 sm:block hidden"
|
|
style={{ right: `${isSkygardenSidebar ? "0" : "-50%"}` }}
|
|
>
|
|
<SkygardenSidebar onMouseEnter={handleOnWingWrapperMouseLeave} />
|
|
</div>
|
|
|
|
<div
|
|
className="absolute left-0 transition-[left]"
|
|
style={{
|
|
width: `${width}px`,
|
|
height: `${width}px`,
|
|
top: `-${top}px`,
|
|
left: `${
|
|
isSkygardenSidebar || isFloorSidebar ? "-25%" : `-${left}px`
|
|
}`,
|
|
}}
|
|
>
|
|
<div
|
|
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out sm: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 isLeft={isLeft} />
|
|
</div>
|
|
|
|
<div
|
|
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out sm: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
|
|
isLeft={isLeft}
|
|
descriptionFloor={currentHoveredFloor}
|
|
floorApartments={currentHoveredApartments}
|
|
/>
|
|
</div>
|
|
<div
|
|
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out sm:hidden flex ${
|
|
currentHoveredFloor?.floor !== skyGardenFloor &&
|
|
currentHoveredFloor &&
|
|
isWrapperHovered
|
|
? "flex"
|
|
: "hidden"
|
|
}`}
|
|
style={{
|
|
top: mousePos[1],
|
|
left: `${mousePos[0]}px`,
|
|
}}
|
|
>
|
|
<MobileFloorDescription
|
|
isLeft={isLeft}
|
|
onClick={handleOnExploreFloorClick}
|
|
descriptionFloor={currentHoveredFloor}
|
|
floorApartments={currentHoveredApartments}
|
|
/>
|
|
</div>
|
|
|
|
<div
|
|
className={`absolute z-40 top-0 left-0 transition-opacity duration-300 ease-in-out sm:hidden flex ${
|
|
currentHoveredFloor?.floor === skyGardenFloor &&
|
|
currentHoveredFloor &&
|
|
isWrapperHovered
|
|
? "flex"
|
|
: "hidden"
|
|
}`}
|
|
style={{
|
|
top: mousePos[1],
|
|
left: `${mousePos[0]}px`,
|
|
}}
|
|
>
|
|
<MobileSkygardenDescription
|
|
onClick={handleOnExploreSkygardenClick}
|
|
isLeft={isLeft}
|
|
/>
|
|
</div>
|
|
|
|
<img
|
|
width={`${width}px`}
|
|
height={`${width}px`}
|
|
src="/images/sequenceWing.jpg"
|
|
className={`absolute z-10 duration-300 transition-opacity ease-in-out opacity-100 select-none`}
|
|
alt=""
|
|
/>
|
|
<svg
|
|
width="1920"
|
|
height="1920"
|
|
viewBox="0 0 1920 1920"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
className={`absolute top-0 left-0 duration-300 transition-opacity ease-in-out w-full h-full opacity-100 z-10 `}
|
|
onMouseOver={handleOnWingWrapperMouseLeave}
|
|
>
|
|
{/* Подписи Крылья */}
|
|
<WingSignatures />
|
|
|
|
{/* Цифры этажи */}
|
|
<FloorNumbers />
|
|
|
|
{/* Этажи */}
|
|
<FloorsHighlighting
|
|
handleOnFloorClick={handleOnFloorClick}
|
|
handleOnSkygardenClick={handleOnSkygardenClick}
|
|
handleOnWingWrapperMouseEnter={handleOnWingWrapperMouseEnter}
|
|
handleOnFloorMouseEnter={handleOnFloorMouseEnter}
|
|
handleOnWingWrapperMouseLeave={handleOnWingWrapperMouseLeave}
|
|
currentFloor={currentFloor}
|
|
isFloorSidebar={isFloorSidebar}
|
|
isSkygardenSidebar={isSkygardenSidebar}
|
|
/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SequenceWing;
|