249 lines
8.8 KiB
TypeScript
249 lines
8.8 KiB
TypeScript
/* eslint-disable react-hooks/exhaustive-deps */
|
|
import { useRef, useState } from "react";
|
|
import FloorPath from "../components/FloorPath";
|
|
import floorPaths from "../data/floorPaths.json";
|
|
import ArrowLeftIcon from "../components/icons/ArrowLeftIcon";
|
|
import Button3 from "../components/Button3";
|
|
import InfoIcon from "../components/icons/InfoIcon";
|
|
// import Header from "../components/Header";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { isMobile } from "react-device-detect";
|
|
|
|
import FloorPopup from "../components/FloorPopup";
|
|
import FloorSidebarContainer from "../components/FloorSidebarContainer";
|
|
import FloorPlan from "../components/FloorPlan";
|
|
import FloorPlanSkyGarden from "../components/FloorPlanSkyGarden";
|
|
import FloorLabels from "../components/FloorLabels";
|
|
import SelectWingMobile from "../components/SelectWingMobile";
|
|
import FloorSelectionMobilePage from "./FloorSelectionMobilePage";
|
|
import IPath from "../types/IPath";
|
|
import FloorPlanRooftop from "../components/FloorPlanRooftop";
|
|
import FloorPlanPodiumLevel from "../components/FloorPlanPodiumLevel";
|
|
import FloorPlanGroundLevel from "../components/FloorPlanGroundLevel";
|
|
|
|
function ComplexWingPage() {
|
|
const ref = useRef<HTMLImageElement>(null);
|
|
const [imageWidth, setImageWidth] = useState(0);
|
|
const [imageHeight, setImageHeight] = useState(0);
|
|
const [mousePos, setMousePos] = useState<[number, number]>([0, 0]);
|
|
const navigate = useNavigate();
|
|
const [hoveredFloorPath, setHoveredFloorPath] = useState<SVGPathElement | null>(null);
|
|
// const [selectedFloorPath, setSelectedFloorPath] =
|
|
// useState<SVGPathElement | null>(null);
|
|
const [sidebarComponent, setSidebarComponent] = useState<{
|
|
element: JSX.Element;
|
|
name: "Floor" | "Rooftop" | "Sky Garden" | "Podium Level" | "Ground Level";
|
|
desc?: string;
|
|
} | null>(null);
|
|
const [selectedWing, setSelectedWing] = useState<"east" | "west" | null>(null);
|
|
|
|
// function handleResize() {
|
|
// if (window.innerHeight > window.innerWidth) {
|
|
// setScaled(true);
|
|
// } else {
|
|
// setScaled(false);
|
|
// }
|
|
// }
|
|
|
|
function handleMouseEnter(e: React.MouseEvent<SVGPathElement>) {
|
|
setHoveredFloorPath(e.currentTarget);
|
|
}
|
|
|
|
function handleMouseMove(e: React.MouseEvent<HTMLDivElement>) {
|
|
const x = e.clientX - e.currentTarget.getBoundingClientRect().left;
|
|
const y = e.clientY - e.currentTarget.getBoundingClientRect().top;
|
|
|
|
setMousePos([x, y]);
|
|
}
|
|
|
|
function handleMouseLeave() {
|
|
setHoveredFloorPath(null);
|
|
}
|
|
|
|
function handleClick(path: IPath) {
|
|
console.log("path", path);
|
|
|
|
if (path["data-name"].includes("floor")) {
|
|
const wing = path["data-name"].split(" ")[0].toLowerCase() as "east" | "west";
|
|
const floor = path["data-name"].split(" ")[1];
|
|
|
|
setSidebarComponent({
|
|
element: <FloorPlan wing={wing} floor={floor} />,
|
|
name: "Floor",
|
|
});
|
|
} else if (path["data-name"] === "Sky Garden") {
|
|
setSidebarComponent({
|
|
element: <FloorPlanSkyGarden />,
|
|
name: "Sky Garden",
|
|
desc: "22-23 floor",
|
|
});
|
|
} else if (path["data-name"] === "Rooftop") {
|
|
setSidebarComponent({
|
|
element: <FloorPlanRooftop />,
|
|
name: "Rooftop",
|
|
desc: "32 floor",
|
|
});
|
|
} else if (path["data-name"] === "Podium Level") {
|
|
setSidebarComponent({
|
|
element: <FloorPlanPodiumLevel />,
|
|
name: "Podium Level",
|
|
desc: "4 floor",
|
|
});
|
|
} else if (path["data-name"] === "Ground Level") {
|
|
setSidebarComponent({
|
|
element: <FloorPlanGroundLevel />,
|
|
name: "Ground Level",
|
|
});
|
|
}
|
|
}
|
|
|
|
function handleLoadedData() {
|
|
setImageWidth(ref.current!.naturalWidth);
|
|
setImageHeight(ref.current!.naturalHeight);
|
|
}
|
|
|
|
// useEffect(() => {
|
|
// handleResize();
|
|
|
|
// window.addEventListener("resize", handleResize);
|
|
|
|
// return () => {
|
|
// window.removeEventListener("resize", handleResize);
|
|
// };
|
|
// }, []);
|
|
|
|
return (
|
|
<>
|
|
{!isMobile ? (
|
|
<div className="relative overflow-hidden select-none h-dvh" onMouseMove={handleMouseMove}>
|
|
{/* <Header /> */}
|
|
|
|
<FloorPopup visible={!!hoveredFloorPath} mousePos={[mousePos[0], mousePos[1]]} path={hoveredFloorPath} />
|
|
|
|
<div className="absolute top-0 left-0 z-10 w-full">
|
|
<div className="p-3 mt-14">
|
|
<div className="grid justify-between w-full grid-cols-3 sm:gap-2">
|
|
<div className="flex items-start gap-2">
|
|
<Button3
|
|
size="small"
|
|
icon={<ArrowLeftIcon />}
|
|
onlyIcon
|
|
onClick={() => (isMobile ? navigate("/") : navigate("/masterplan/1"))}
|
|
/>
|
|
<Button3
|
|
variant="secondary"
|
|
icon={<InfoIcon className="w-5 h-5" />}
|
|
className="max-sm:hidden"
|
|
onClick={() => navigate("/about-projects")}
|
|
>
|
|
About Projects
|
|
</Button3>
|
|
</div>
|
|
<div
|
|
className={`font-semibold text-center text-white drop-shadow transition-opacity ${
|
|
sidebarComponent ? "opacity-0" : "opacity-100"
|
|
}`}
|
|
>
|
|
<p className="text-base lg:text-xl">ROVE Home Marasi Drive</p>
|
|
<p className="text-xs">Select a {isMobile ? "wing" : "floor"}</p>
|
|
</div>
|
|
<div className="flex items-start justify-end">
|
|
<Button3
|
|
variant="secondary"
|
|
icon={<InfoIcon className="w-5 h-5" />}
|
|
onlyIcon
|
|
className="sm:hidden"
|
|
onClick={() => navigate("/about-projects")}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`h-dvh transition-all duration-300 ${sidebarComponent ? "-translate-x-1/4" : ""}`}>
|
|
<img
|
|
ref={ref}
|
|
src="/images/sequenceWing.jpg"
|
|
alt=""
|
|
className="object-cover w-full h-full"
|
|
onLoad={() => handleLoadedData()}
|
|
/>
|
|
|
|
{!isMobile ? (
|
|
<svg
|
|
viewBox={`0 0 ${imageWidth} ${imageHeight}`}
|
|
preserveAspectRatio="xMidYMid slice"
|
|
className="absolute top-0 left-0 w-full h-full"
|
|
>
|
|
{floorPaths.map((floorPath, index) => (
|
|
<FloorPath
|
|
key={index}
|
|
{...floorPath}
|
|
selected={false}
|
|
onMouseEnter={handleMouseEnter}
|
|
onMouseLeave={handleMouseLeave}
|
|
onClick={() => handleClick(floorPath)}
|
|
/>
|
|
))}
|
|
|
|
<FloorLabels />
|
|
</svg>
|
|
) : (
|
|
<></>
|
|
)}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="relative overflow-hidden select-none">
|
|
{!selectedWing ? (
|
|
<div className="">
|
|
<div className="fixed top-0 left-0 z-10 flex items-start justify-between w-full p-3 mt-14">
|
|
<Button3 icon={<ArrowLeftIcon />} onlyIcon onClick={() => navigate("/masterplan/1")} />
|
|
<div className="font-semibold text-center text-white">
|
|
<p className="text-base capitalize">ROVE Home Marasi Drive</p>
|
|
<p className="text-xs">Select a wing</p>
|
|
</div>
|
|
<Button3
|
|
variant="secondary"
|
|
icon={<InfoIcon className="w-5 h-5" />}
|
|
onlyIcon
|
|
onClick={() => navigate("/about-projects")}
|
|
/>
|
|
</div>
|
|
|
|
<div className="scale-150 h-dvh">
|
|
<img
|
|
ref={ref}
|
|
src="/images/sequenceWing.jpg"
|
|
alt=""
|
|
className="object-cover w-full h-full"
|
|
onLoad={() => handleLoadedData()}
|
|
/>
|
|
<svg
|
|
viewBox={`0 0 ${imageWidth} ${imageHeight}`}
|
|
preserveAspectRatio="xMidYMid slice"
|
|
className="absolute top-0 left-0 w-full h-full"
|
|
>
|
|
<SelectWingMobile onClick={(wing) => setSelectedWing(wing)} />
|
|
|
|
<FloorLabels />
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<FloorSelectionMobilePage
|
|
wing={selectedWing}
|
|
onUnselectWing={() => setSelectedWing(null)}
|
|
onSelectPath={(path) => (path ? handleClick(path) : console.log(path))}
|
|
/>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
<FloorSidebarContainer sidebarComponent={sidebarComponent} onClose={() => setSidebarComponent(null)} />
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default ComplexWingPage;
|