From 3672bbd9971710a50429c71ac63f419d9855c27d Mon Sep 17 00:00:00 2001 From: dohyeons Date: Mon, 13 Oct 2025 18:09:20 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BA=94=EB=B2=84=EC=8A=A4=20=ED=81=AC?= =?UTF-8?q?=EA=B8=B0=20=EC=A1=B0=EC=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/dashboard/DashboardCanvas.tsx | 47 ++++----------- .../admin/dashboard/DashboardDesigner.tsx | 58 ++++++------------- .../admin/dashboard/DashboardSidebar.tsx | 2 +- .../components/admin/dashboard/gridUtils.ts | 7 ++- 4 files changed, 37 insertions(+), 77 deletions(-) diff --git a/frontend/components/admin/dashboard/DashboardCanvas.tsx b/frontend/components/admin/dashboard/DashboardCanvas.tsx index dcdcaa8f..04975d0f 100644 --- a/frontend/components/admin/dashboard/DashboardCanvas.tsx +++ b/frontend/components/admin/dashboard/DashboardCanvas.tsx @@ -36,30 +36,6 @@ export const DashboardCanvas = forwardRef( ref, ) => { const [isDragOver, setIsDragOver] = useState(false); - const [cellSize, setCellSize] = useState(60); - - // 화면 크기에 따라 셀 크기 동적 계산 - useEffect(() => { - const updateCellSize = () => { - if (!ref || typeof ref === "function" || !ref.current) return; - - const container = ref.current.parentElement; - if (!container) return; - - // 컨테이너 너비에서 여백 제외 - const availableWidth = container.clientWidth - 32; // 좌우 패딩 - - // 12 컬럼 + 11개 gap을 고려한 셀 크기 계산 - const calculatedCellSize = Math.floor((availableWidth - 11 * GRID_CONFIG.GAP) / GRID_CONFIG.COLUMNS); - - setCellSize(calculatedCellSize); - }; - - updateCellSize(); - window.addEventListener("resize", updateCellSize); - - return () => window.removeEventListener("resize", updateCellSize); - }, [ref]); // 드래그 오버 처리 const handleDragOver = useCallback((e: React.DragEvent) => { @@ -93,16 +69,16 @@ export const DashboardCanvas = forwardRef( const rawX = e.clientX - rect.left + (ref.current?.scrollLeft || 0); const rawY = e.clientY - rect.top + (ref.current?.scrollTop || 0); - // 그리드에 스냅 (동적 셀 크기 사용) - const snappedX = snapToGrid(rawX, cellSize); - const snappedY = snapToGrid(rawY, cellSize); + // 그리드에 스냅 (고정 셀 크기 사용) + const snappedX = snapToGrid(rawX, GRID_CONFIG.CELL_SIZE); + const snappedY = snapToGrid(rawY, GRID_CONFIG.CELL_SIZE); onCreateElement(dragData.type, dragData.subtype, snappedX, snappedY); } catch (error) { // console.error('드롭 데이터 파싱 오류:', error); } }, - [ref, onCreateElement, cellSize], + [ref, onCreateElement], ); // 캔버스 클릭 시 선택 해제 @@ -115,19 +91,20 @@ export const DashboardCanvas = forwardRef( [onSelectElement], ); - // 그리드 크기 계산 (동적) - const cellWithGap = cellSize + GRID_CONFIG.GAP; + // 고정 그리드 크기 + const cellWithGap = GRID_CONFIG.CELL_SIZE + GRID_CONFIG.GAP; const gridSize = `${cellWithGap}px ${cellWithGap}px`; return (
( key={element.id} element={element} isSelected={selectedElement === element.id} - cellSize={cellSize} + cellSize={GRID_CONFIG.CELL_SIZE} onUpdate={onUpdateElement} onRemove={onRemoveElement} onSelect={onSelectElement} diff --git a/frontend/components/admin/dashboard/DashboardDesigner.tsx b/frontend/components/admin/dashboard/DashboardDesigner.tsx index 495dd17c..f23a12a2 100644 --- a/frontend/components/admin/dashboard/DashboardDesigner.tsx +++ b/frontend/components/admin/dashboard/DashboardDesigner.tsx @@ -23,32 +23,8 @@ export default function DashboardDesigner() { const [dashboardId, setDashboardId] = useState(null); const [dashboardTitle, setDashboardTitle] = useState(""); const [isLoading, setIsLoading] = useState(false); - const [cellSize, setCellSize] = useState(60); const canvasRef = useRef(null); - // 화면 크기에 따라 셀 크기 동적 계산 - useEffect(() => { - const updateCellSize = () => { - if (!canvasRef.current) return; - - const container = canvasRef.current.parentElement; - if (!container) return; - - // 컨테이너 너비에서 여백 제외 - const availableWidth = container.clientWidth - 32; - - // 12 컬럼 + 11개 gap을 고려한 셀 크기 계산 - const calculatedCellSize = Math.floor((availableWidth - 11 * GRID_CONFIG.GAP) / GRID_CONFIG.COLUMNS); - - setCellSize(calculatedCellSize); - }; - - updateCellSize(); - window.addEventListener("resize", updateCellSize); - - return () => window.removeEventListener("resize", updateCellSize); - }, []); - // URL 파라미터에서 대시보드 ID 읽기 및 데이터 로드 React.useEffect(() => { const params = new URLSearchParams(window.location.search); @@ -100,12 +76,12 @@ export default function DashboardDesigner() { } }; - // 새로운 요소 생성 (그리드 기반 기본 크기) + // 새로운 요소 생성 (고정 그리드 기반 기본 크기) const createElement = useCallback( (type: ElementType, subtype: ElementSubtype, x: number, y: number) => { // 기본 크기: 차트는 4x3 셀, 위젯은 2x2 셀 const defaultCells = type === "chart" ? { width: 4, height: 3 } : { width: 2, height: 2 }; - const cellWithGap = cellSize + GRID_CONFIG.GAP; + const cellWithGap = GRID_CONFIG.CELL_SIZE + GRID_CONFIG.GAP; const defaultWidth = defaultCells.width * cellWithGap - GRID_CONFIG.GAP; const defaultHeight = defaultCells.height * cellWithGap - GRID_CONFIG.GAP; @@ -124,7 +100,7 @@ export default function DashboardDesigner() { setElementCounter((prev) => prev + 1); setSelectedElement(newElement.id); }, - [elementCounter, cellSize], + [elementCounter], ); // 요소 업데이트 @@ -253,25 +229,29 @@ export default function DashboardDesigner() { return (
{/* 캔버스 영역 */} -
+
{/* 편집 중인 대시보드 표시 */} {dashboardTitle && ( -
+
📝 편집 중: {dashboardTitle}
)} - + + {/* 캔버스 중앙 정렬 컨테이너 */} +
+ +
{/* 사이드바 */} diff --git a/frontend/components/admin/dashboard/DashboardSidebar.tsx b/frontend/components/admin/dashboard/DashboardSidebar.tsx index a9eb2659..6ff1502c 100644 --- a/frontend/components/admin/dashboard/DashboardSidebar.tsx +++ b/frontend/components/admin/dashboard/DashboardSidebar.tsx @@ -17,7 +17,7 @@ export function DashboardSidebar() { }; return ( -
+
{/* 차트 섹션 */}

📊 차트 종류

diff --git a/frontend/components/admin/dashboard/gridUtils.ts b/frontend/components/admin/dashboard/gridUtils.ts index f17496da..f5ec9d7c 100644 --- a/frontend/components/admin/dashboard/gridUtils.ts +++ b/frontend/components/admin/dashboard/gridUtils.ts @@ -5,13 +5,16 @@ * - 스냅 기능 */ -// 그리드 설정 +// 그리드 설정 (고정 크기) export const GRID_CONFIG = { COLUMNS: 12, - CELL_SIZE: 60, // 60px 정사각형 셀 + CELL_SIZE: 132, // 고정 셀 크기 GAP: 8, // 셀 간격 SNAP_THRESHOLD: 15, // 스냅 임계값 (px) ELEMENT_PADDING: 4, // 요소 주위 여백 (px) + CANVAS_WIDTH: 1682, // 고정 캔버스 너비 (실제 측정값) + // 계산식: (132 + 8) × 12 - 8 = 1672px (그리드) + // 추가 여백 10px 포함 = 1682px } as const; /**