Dwinzo_dev/app/src/components/ui/componets/DisplayZone.tsx

204 lines
6.0 KiB
TypeScript

import React, { useEffect, useRef, useState, useCallback } from "react";
import { Widget } from "../../../store/useWidgetStore";
import { MoveArrowLeft, MoveArrowRight } from "../../icons/SimulationIcons";
import { InfoIcon } from "../../icons/ExportCommonIcons";
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
interface DisplayZoneProps {
zonesData: {
[key: string]: {
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: Widget[];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
};
};
selectedZone: {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
zoneId: string;
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[];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
}>
>;
}
const DisplayZone: React.FC<DisplayZoneProps> = ({
zonesData,
selectedZone,
setSelectedZone,
}) => {
// Ref for the container element
const containerRef = useRef<HTMLDivElement | null>(null);
// State to track overflow visibility
const [showLeftArrow, setShowLeftArrow] = useState(false);
const [showRightArrow, setShowRightArrow] = useState(false);
// Function to calculate overflow state
const updateOverflowState = useCallback(() => {
const container = containerRef.current;
if (container) {
const isOverflowing = container.scrollWidth > container.clientWidth;
const canScrollLeft = container.scrollLeft > 0;
const canScrollRight =
container.scrollLeft + container.clientWidth < container.scrollWidth;
setShowLeftArrow(isOverflowing && canScrollLeft);
setShowRightArrow(isOverflowing && canScrollRight);
}
}, []);
useEffect(() => {
const container = containerRef.current;
if (container) {
// Initial calculation after the DOM has been rendered
const handleInitialRender = () => {
requestAnimationFrame(updateOverflowState);
};
handleInitialRender();
// Update on window resize or scroll
const handleResize = () => updateOverflowState();
const handleScroll = () => updateOverflowState();
// Add mouse wheel listener for horizontal scrolling
const handleWheel = (event: WheelEvent) => {
event.preventDefault(); // Prevent default vertical scrolling
if (container) {
container.scrollBy({
left: event.deltaY * 2, // Translate vertical scroll to horizontal scroll
behavior: "smooth",
});
}
};
container.addEventListener("scroll", handleScroll);
window.addEventListener("resize", handleResize);
container.addEventListener("wheel", handleWheel, { passive: false });
return () => {
container.removeEventListener("scroll", handleScroll);
window.removeEventListener("resize", handleResize);
container.removeEventListener("wheel", handleWheel);
};
}
}, [updateOverflowState]);
// Handle scrolling with navigation arrows
const handleScrollLeft = () => {
const container = containerRef.current;
if (container) {
container.scrollBy({
left: -200, // Scroll left by 200px
behavior: "smooth",
});
}
};
const handleScrollRight = () => {
const container = containerRef.current;
if (container) {
container.scrollBy({
left: 200, // Scroll right by 200px
behavior: "smooth",
});
}
};
return (
<div
className={`zone-wrapper ${
selectedZone?.activeSides?.includes("bottom") && "bottom"
}`}
>
{/* Left Arrow */}
{showLeftArrow && (
<button className="arrow left-arrow" onClick={handleScrollLeft}>
<MoveArrowLeft />
</button>
)}
{/* Zones Wrapper */}
{Object.keys(zonesData).length !== 0 ? (
<div ref={containerRef} className="zones-wrapper">
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${
selectedZone.zoneName === zoneName ? "active" : ""
}`}
onClick={() => {
useDroppedObjectsStore.getState().setZone(zoneName, zonesData[zoneName]?.zoneId);
setSelectedZone({
zoneName,
activeSides: zonesData[zoneName].activeSides || [],
panelOrder: zonesData[zoneName].panelOrder || [],
lockedPanels: zonesData[zoneName].lockedPanels || [],
widgets: zonesData[zoneName].widgets || [],
zoneId: zonesData[zoneName]?.zoneId || "",
zoneViewPortTarget:
zonesData[zoneName].zoneViewPortTarget || [],
zoneViewPortPosition:
zonesData[zoneName].zoneViewPortPosition || [],
});
}}
>
{zoneName}
</div>
))}
</div>
) : (
<div className="no-zone">
<InfoIcon />
No zones? Create one!
</div>
)}
{/* Right Arrow */}
{showRightArrow && (
<button className="arrow right-arrow" onClick={handleScrollRight}>
<MoveArrowRight />
</button>
)}
</div>
);
};
export default DisplayZone;