ERP-node/frontend/hooks/usePanelState.ts

173 lines
4.2 KiB
TypeScript

"use client";
import { useState, useCallback, useEffect } from "react";
export interface PanelState {
isOpen: boolean;
position: { x: number; y: number };
size: { width: number; height: number };
}
export interface PanelConfig {
id: string;
title: string;
defaultPosition: "left" | "right" | "top" | "bottom";
defaultWidth: number;
defaultHeight: number;
shortcutKey?: string;
}
export const usePanelState = (panels: PanelConfig[]) => {
const [panelStates, setPanelStates] = useState<Record<string, PanelState>>(() => {
const initialStates: Record<string, PanelState> = {};
panels.forEach((panel) => {
initialStates[panel.id] = {
isOpen: false,
position: { x: 0, y: 0 },
size: { width: panel.defaultWidth, height: panel.defaultHeight },
};
});
return initialStates;
});
// 패널 설정이 변경되었을 때 크기 업데이트
useEffect(() => {
setPanelStates((prev) => {
const newStates = { ...prev };
panels.forEach((panel) => {
if (newStates[panel.id]) {
// 기존 패널의 위치는 유지하고 크기만 업데이트
newStates[panel.id] = {
...newStates[panel.id],
size: { width: panel.defaultWidth, height: panel.defaultHeight },
};
} else {
// 새로운 패널이면 전체 초기화
newStates[panel.id] = {
isOpen: false,
position: { x: 0, y: 0 },
size: { width: panel.defaultWidth, height: panel.defaultHeight },
};
}
});
return newStates;
});
}, [panels]);
// 패널 토글
const togglePanel = useCallback((panelId: string) => {
setPanelStates((prev) => ({
...prev,
[panelId]: {
...prev[panelId],
isOpen: !prev[panelId]?.isOpen,
},
}));
}, []);
// 패널 열기
const openPanel = useCallback((panelId: string) => {
console.log("📂 패널 열기:", {
panelId,
timestamp: new Date().toISOString(),
});
setPanelStates((prev) => ({
...prev,
[panelId]: {
...prev[panelId],
isOpen: true,
},
}));
}, []);
// 패널 닫기
const closePanel = useCallback((panelId: string) => {
console.log("📁 패널 닫기:", {
panelId,
timestamp: new Date().toISOString(),
});
setPanelStates((prev) => ({
...prev,
[panelId]: {
...prev[panelId],
isOpen: false,
},
}));
}, []);
// 모든 패널 닫기
const closeAllPanels = useCallback(() => {
setPanelStates((prev) => {
const newStates = { ...prev };
Object.keys(newStates).forEach((panelId) => {
newStates[panelId] = {
...newStates[panelId],
isOpen: false,
};
});
return newStates;
});
}, []);
// 패널 위치 업데이트
const updatePanelPosition = useCallback((panelId: string, position: { x: number; y: number }) => {
setPanelStates((prev) => ({
...prev,
[panelId]: {
...prev[panelId],
position,
},
}));
}, []);
// 패널 크기 업데이트
const updatePanelSize = useCallback((panelId: string, size: { width: number; height: number }) => {
setPanelStates((prev) => ({
...prev,
[panelId]: {
...prev[panelId],
size,
},
}));
}, []);
// 키보드 단축키 처리
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
// Esc 키로 모든 패널 닫기
if (e.key === "Escape") {
closeAllPanels();
return;
}
// 단축키 처리
panels.forEach((panel) => {
if (panel.shortcutKey && e.key?.toLowerCase() === panel.shortcutKey?.toLowerCase()) {
// Ctrl/Cmd 키와 함께 사용
if (e.ctrlKey || e.metaKey) {
e.preventDefault();
togglePanel(panel.id);
}
}
});
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [panels, togglePanel, closeAllPanels]);
return {
panelStates,
togglePanel,
openPanel,
closePanel,
closeAllPanels,
updatePanelPosition,
updatePanelSize,
};
};