import React, { useEffect, useMemo, useRef, useState } from "react"; import { DraggableWidget } from "./draggableWidget"; import { useWidgetStore } from "../../store/store"; type Side = "top" | "bottom" | "left" | "right"; interface PanelProps { selectedZone: { zoneName: string; // Add zoneName property activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; widgets: { id: string; type: string; title: string; panel: Side; data: any; }[]; }; setSelectedZone: React.Dispatch< React.SetStateAction<{ zoneName: string; // Ensure zoneName is included in the state type activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; widgets: { id: string; type: string; title: string; panel: Side; data: any; }[]; }> >; } const generateUniqueId = () => `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const Panel: React.FC = ({ selectedZone, setSelectedZone }) => { const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({}); const [panelDimensions, setPanelDimensions] = useState<{ [side in Side]?: { width: number; height: number }; }>({}); const getPanelStyle = useMemo( () => (side: Side) => { const currentIndex = selectedZone.panelOrder.indexOf(side); const previousPanels = selectedZone.panelOrder.slice(0, currentIndex); const leftActive = previousPanels.includes("left"); const rightActive = previousPanels.includes("right"); const topActive = previousPanels.includes("top"); const bottomActive = previousPanels.includes("bottom"); switch (side) { case "top": case "bottom": return { width: `calc(100% - ${ (leftActive ? 204 : 0) + (rightActive ? 204 : 0) }px)`, left: leftActive ? "204px" : "0", right: rightActive ? "204px" : "0", [side]: "0", height: "200px", }; case "left": case "right": return { height: `calc(100% - ${ (topActive ? 204 : 0) + (bottomActive ? 204 : 0) }px)`, top: topActive ? "204px" : "0", bottom: bottomActive ? "204px" : "0", [side]: "0", width: "200px", }; default: return {}; } }, [selectedZone.panelOrder] ); const handleDrop = (e: React.DragEvent, panel: Side) => { e.preventDefault(); const { draggedAsset } = useWidgetStore.getState(); if (draggedAsset) { if (selectedZone.lockedPanels.includes(panel)) return; const currentWidgetsInPanel = selectedZone.widgets.filter( (w) => w.panel === panel ).length; const dimensions = panelDimensions[panel]; const CHART_WIDTH = 200; // Width of each chart for top/bottom panels const CHART_HEIGHT = 200; // Height of each chart for left/right panels let maxCharts = 0; if (dimensions) { if (panel === "top" || panel === "bottom") { maxCharts = Math.floor(dimensions.width / CHART_WIDTH); // Use width for top/bottom } else { maxCharts = Math.floor(dimensions.height / CHART_HEIGHT); // Use height for left/right } } else { maxCharts = panel === "top" || panel === "bottom" ? 5 : 3; // Default values } if (currentWidgetsInPanel >= maxCharts) { return; } const updatedZone = { ...selectedZone, widgets: [ ...selectedZone.widgets, { ...draggedAsset, id: generateUniqueId(), panel, }, ], }; // Update the selectedZone state setSelectedZone(updatedZone); } }; useEffect(() => { const observers: ResizeObserver[] = []; const currentPanelRefs = panelRefs.current; selectedZone.activeSides.forEach((side) => { const element = currentPanelRefs[side]; if (element) { const observer = new ResizeObserver((entries) => { for (const entry of entries) { const { width, height } = entry.contentRect; setPanelDimensions((prev) => ({ ...prev, [side]: { width, height }, })); } }); observer.observe(element); observers.push(observer); } }); return () => { observers.forEach((observer) => observer.disconnect()); }; }, [selectedZone.activeSides]); return ( <> {selectedZone.activeSides.map((side) => (
handleDrop(e, side)} onDragOver={(e) => e.preventDefault()} ref={(el) => { if (el) { panelRefs.current[side] = el; } else { delete panelRefs.current[side]; } }} >
{selectedZone.widgets .filter((w) => w.panel === side) .map((widget) => ( ))}
))} ); }; export default Panel;