263 lines
7.4 KiB
TypeScript
263 lines
7.4 KiB
TypeScript
import React, { useEffect, useRef, useState, useCallback } from "react";
|
|
import { useWidgetStore, Widget } from "../../store/useWidgetStore";
|
|
|
|
import {
|
|
useDroppedObjectsStore,
|
|
useFloatingWidget,
|
|
} from "../../store/useDroppedObjectsStore";
|
|
import { getSelect2dZoneData } from "../../services/realTimeVisulization/zoneData/getSelect2dZoneData";
|
|
import { getFloatingZoneData } from "../../services/realTimeVisulization/zoneData/getFloatingData";
|
|
import { get3dWidgetZoneData } from "../../services/realTimeVisulization/zoneData/get3dWidgetData";
|
|
import {
|
|
MoveArrowLeft,
|
|
MoveArrowRight,
|
|
} from "../../components/icons/SimulationIcons";
|
|
import { InfoIcon } from "../../components/icons/ExportCommonIcons";
|
|
|
|
// Define the type for `Side`
|
|
type Side = "top" | "bottom" | "left" | "right";
|
|
|
|
interface HiddenPanels {
|
|
[zoneId: string]: Side[];
|
|
}
|
|
|
|
interface DisplayZoneProps {
|
|
zonesData: {
|
|
[key: string]: {
|
|
activeSides: Side[];
|
|
panelOrder: Side[];
|
|
lockedPanels: Side[];
|
|
points: [];
|
|
widgets: Widget[];
|
|
zoneId: string;
|
|
zoneViewPortTarget: number[];
|
|
zoneViewPortPosition: number[];
|
|
};
|
|
};
|
|
selectedZone: {
|
|
zoneName: string;
|
|
activeSides: Side[];
|
|
panelOrder: Side[];
|
|
lockedPanels: Side[];
|
|
zoneId: string;
|
|
points: [];
|
|
zoneViewPortTarget: number[];
|
|
zoneViewPortPosition: number[];
|
|
widgets: {
|
|
id: string;
|
|
type: string;
|
|
title: string;
|
|
panel: Side;
|
|
data: any;
|
|
}[];
|
|
};
|
|
setSelectedZone: React.Dispatch<
|
|
React.SetStateAction<{
|
|
zoneName: string;
|
|
activeSides: Side[];
|
|
panelOrder: Side[];
|
|
lockedPanels: Side[];
|
|
points: [];
|
|
zoneId: string;
|
|
zoneViewPortTarget: number[];
|
|
zoneViewPortPosition: number[];
|
|
widgets: {
|
|
id: string;
|
|
type: string;
|
|
title: string;
|
|
panel: Side;
|
|
data: any;
|
|
}[];
|
|
}>
|
|
>;
|
|
hiddenPanels: HiddenPanels; // Updated prop type
|
|
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
|
|
}
|
|
|
|
const DisplayZone: React.FC<DisplayZoneProps> = ({
|
|
zonesData,
|
|
selectedZone,
|
|
setSelectedZone,
|
|
hiddenPanels,
|
|
}) => {
|
|
// Ref for the container element
|
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
const scrollContainerRef = useRef<HTMLDivElement | null>(null);
|
|
|
|
// State to track overflow visibility
|
|
const [showLeftArrow, setShowLeftArrow] = useState(false);
|
|
const [showRightArrow, setShowRightArrow] = useState(false);
|
|
const { floatingWidget, setFloatingWidget } = useFloatingWidget();
|
|
|
|
const { setSelectedChartId } = useWidgetStore();
|
|
|
|
// Function to calculate overflow state
|
|
const updateOverflowState = useCallback(() => {
|
|
const container = scrollContainerRef.current;
|
|
if (container) {
|
|
const isOverflowing = container.scrollWidth > container.clientWidth;
|
|
const canScrollLeft = container.scrollLeft > 0;
|
|
|
|
const canScrollRight =
|
|
container.scrollLeft + container.clientWidth + 1 <
|
|
container.scrollWidth;
|
|
setShowLeftArrow(isOverflowing && canScrollLeft);
|
|
setShowRightArrow(isOverflowing && canScrollRight);
|
|
|
|
// console.log('canScrollRight: ', canScrollRight);
|
|
// console.log('isOverflowing: ', isOverflowing);
|
|
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const container = scrollContainerRef.current;
|
|
if (!container) return;
|
|
|
|
// Initial calculation after the DOM has been rendered
|
|
const observer = new ResizeObserver(updateOverflowState);
|
|
observer.observe(container);
|
|
|
|
// Update on scroll
|
|
const handleScroll = () => updateOverflowState();
|
|
container.addEventListener("scroll", handleScroll);
|
|
|
|
// Add mouse wheel listener for horizontal scrolling
|
|
const handleWheel = (event: WheelEvent) => {
|
|
if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
|
|
event.preventDefault();
|
|
container.scrollBy({
|
|
left: event.deltaY * 2,
|
|
behavior: "smooth",
|
|
});
|
|
}
|
|
};
|
|
|
|
container.addEventListener("wheel", handleWheel, { passive: false });
|
|
|
|
// Initial check
|
|
updateOverflowState();
|
|
|
|
return () => {
|
|
observer.disconnect();
|
|
container.removeEventListener("scroll", handleScroll);
|
|
container.removeEventListener("wheel", handleWheel);
|
|
};
|
|
}, [updateOverflowState]);
|
|
|
|
// Handle scrolling with navigation arrows
|
|
const handleScrollLeft = () => {
|
|
const container = scrollContainerRef.current;
|
|
if (container) {
|
|
container.scrollBy({
|
|
left: -200,
|
|
behavior: "smooth",
|
|
});
|
|
}
|
|
};
|
|
|
|
const handleScrollRight = () => {
|
|
const container = scrollContainerRef.current;
|
|
if (container) {
|
|
container.scrollBy({
|
|
left: 200,
|
|
behavior: "smooth",
|
|
});
|
|
}
|
|
};
|
|
|
|
async function handleSelect2dZoneData(zoneId: string, zoneName: string) {
|
|
try {
|
|
if (selectedZone?.zoneId === zoneId) {
|
|
return;
|
|
}
|
|
// setSelectedChartId(null);
|
|
const email = localStorage.getItem("email") || "";
|
|
const organization = email?.split("@")[1]?.split(".")[0];
|
|
let response = await getSelect2dZoneData(zoneId, organization);
|
|
console.log("response: ", response);
|
|
let res = await getFloatingZoneData(zoneId, organization);
|
|
console.log("res: ", res);
|
|
|
|
setFloatingWidget(res);
|
|
// Set the selected zone in the store
|
|
useDroppedObjectsStore.getState().setZone(zoneName, zoneId);
|
|
if (Array.isArray(res)) {
|
|
res.forEach((val) => {
|
|
useDroppedObjectsStore.getState().addObject(zoneName, val);
|
|
});
|
|
}
|
|
|
|
setSelectedZone({
|
|
zoneName,
|
|
activeSides: response.activeSides || [],
|
|
panelOrder: response.panelOrder || [],
|
|
lockedPanels: response.lockedPanels || [],
|
|
widgets: response.widgets || [],
|
|
points: response.points || [],
|
|
zoneId: zoneId,
|
|
zoneViewPortTarget: response.viewPortCenter || {},
|
|
zoneViewPortPosition: response.viewPortposition || {},
|
|
});
|
|
} catch (error) {}
|
|
}
|
|
|
|
return (
|
|
<div
|
|
ref={containerRef}
|
|
className={`zone-wrapper ${
|
|
selectedZone?.activeSides?.includes("bottom") &&
|
|
!hiddenPanels[selectedZone.zoneId]?.includes("bottom")
|
|
? "bottom"
|
|
: ""
|
|
}`}
|
|
>
|
|
{/* Left Arrow */}
|
|
{showLeftArrow && (
|
|
<button className="arrow left-arrow" onClick={handleScrollLeft}>
|
|
<MoveArrowLeft />
|
|
</button>
|
|
)}
|
|
|
|
{/* Scrollable Zones Container */}
|
|
<div
|
|
ref={scrollContainerRef}
|
|
className="zones-wrapper"
|
|
style={{ overflowX: "auto", whiteSpace: "nowrap" }}
|
|
>
|
|
{Object.keys(zonesData).length !== 0 ? (
|
|
<>
|
|
{Object.keys(zonesData).map((zoneName, index) => (
|
|
<div
|
|
key={index}
|
|
className={`zone ${
|
|
selectedZone.zoneName === zoneName ? "active" : ""
|
|
}`}
|
|
onClick={() =>
|
|
handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)
|
|
}
|
|
>
|
|
{zoneName}
|
|
</div>
|
|
))}
|
|
</>
|
|
) : (
|
|
<div className="no-zone">
|
|
<InfoIcon />
|
|
No zones? Create one!
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Right Arrow */}
|
|
{showRightArrow && (
|
|
<button className="arrow right-arrow" onClick={handleScrollRight}>
|
|
<MoveArrowRight />
|
|
</button>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DisplayZone;
|