diff --git a/frontend/components/report/designer/CanvasComponent.tsx b/frontend/components/report/designer/CanvasComponent.tsx index 5f9b0aef..5d9ac69a 100644 --- a/frontend/components/report/designer/CanvasComponent.tsx +++ b/frontend/components/report/designer/CanvasComponent.tsx @@ -47,6 +47,8 @@ export function CanvasComponent({ component }: CanvasComponentProps) { // 마우스 이동 핸들러 (전역) useEffect(() => { + if (!isDragging && !isResizing) return; + const handleMouseMove = (e: MouseEvent) => { if (isDragging) { const newX = Math.max(0, e.clientX - dragStart.x); @@ -66,15 +68,25 @@ export function CanvasComponent({ component }: CanvasComponentProps) { setIsResizing(false); }; - if (isDragging || isResizing) { - document.addEventListener("mousemove", handleMouseMove); - document.addEventListener("mouseup", handleMouseUp); - return () => { - document.removeEventListener("mousemove", handleMouseMove); - document.removeEventListener("mouseup", handleMouseUp); - }; - } - }, [isDragging, isResizing, dragStart, resizeStart, component.id, updateComponent]); + document.addEventListener("mousemove", handleMouseMove); + document.addEventListener("mouseup", handleMouseUp); + + return () => { + document.removeEventListener("mousemove", handleMouseMove); + document.removeEventListener("mouseup", handleMouseUp); + }; + }, [ + isDragging, + isResizing, + dragStart.x, + dragStart.y, + resizeStart.x, + resizeStart.y, + resizeStart.width, + resizeStart.height, + component.id, + updateComponent, + ]); // 표시할 값 결정 const getDisplayValue = (): string => { diff --git a/frontend/components/report/designer/QueryManager.tsx b/frontend/components/report/designer/QueryManager.tsx index d4b3e2a4..ced3f9ff 100644 --- a/frontend/components/report/designer/QueryManager.tsx +++ b/frontend/components/report/designer/QueryManager.tsx @@ -67,7 +67,6 @@ export function QueryManager() { setSelectedQueryId(null); setParameterValues({}); setParameterTypes({}); - setTestResult(null); } }; @@ -76,7 +75,6 @@ export function QueryManager() { setSelectedQueryId(queryId); setParameterValues({}); setParameterTypes({}); - setTestResult(null); }; // 파라미터 값이 모두 입력되었는지 확인 diff --git a/frontend/components/report/designer/ReportDesignerCanvas.tsx b/frontend/components/report/designer/ReportDesignerCanvas.tsx index 0cea297f..74f56892 100644 --- a/frontend/components/report/designer/ReportDesignerCanvas.tsx +++ b/frontend/components/report/designer/ReportDesignerCanvas.tsx @@ -38,9 +38,9 @@ export function ReportDesignerCanvas() { fontFamily: "Malgun Gothic", fontWeight: "normal", fontColor: "#000000", - backgroundColor: "#ffffff", - borderWidth: 1, - borderColor: "#666666", + backgroundColor: "transparent", + borderWidth: 0, + borderColor: "#cccccc", borderRadius: 5, textAlign: "left", padding: 10, diff --git a/frontend/components/report/designer/ReportDesignerToolbar.tsx b/frontend/components/report/designer/ReportDesignerToolbar.tsx index 1075b387..f2ca1b74 100644 --- a/frontend/components/report/designer/ReportDesignerToolbar.tsx +++ b/frontend/components/report/designer/ReportDesignerToolbar.tsx @@ -16,6 +16,11 @@ export function ReportDesignerToolbar() { await saveLayout(); }; + const handleSaveAndClose = async () => { + await saveLayout(); + router.push("/admin/report"); + }; + const handleReset = async () => { if (confirm("현재 변경사항을 모두 취소하고 마지막 저장 상태로 되돌리시겠습니까?")) { await loadLayout(); @@ -56,7 +61,7 @@ export function ReportDesignerToolbar() { 미리보기 - + diff --git a/frontend/contexts/ReportDesignerContext.tsx b/frontend/contexts/ReportDesignerContext.tsx index 50917d47..b8464bac 100644 --- a/frontend/contexts/ReportDesignerContext.tsx +++ b/frontend/contexts/ReportDesignerContext.tsx @@ -33,8 +33,8 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 40, fontSize: 24, fontColor: "#000000", - backgroundColor: "#ffffff", - borderColor: "#000000", + backgroundColor: "transparent", + borderColor: "#cccccc", borderWidth: 0, zIndex: 1, defaultValue: "발주서", @@ -48,9 +48,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 30, fontSize: 14, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, }, { @@ -62,9 +62,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 30, fontSize: 14, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, }, { @@ -76,9 +76,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 30, fontSize: 14, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, }, { @@ -90,9 +90,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 200, fontSize: 12, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, }, ], @@ -126,8 +126,8 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 40, fontSize: 24, fontColor: "#000000", - backgroundColor: "#ffffff", - borderColor: "#000000", + backgroundColor: "transparent", + borderColor: "#cccccc", borderWidth: 0, zIndex: 1, defaultValue: "청구서", @@ -141,9 +141,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 30, fontSize: 14, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, }, { @@ -155,9 +155,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 30, fontSize: 14, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, }, { @@ -169,9 +169,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 200, fontSize: 12, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, }, { @@ -220,8 +220,8 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 40, fontSize: 20, fontColor: "#000000", - backgroundColor: "#ffffff", - borderColor: "#000000", + backgroundColor: "transparent", + borderColor: "#cccccc", borderWidth: 0, zIndex: 1, defaultValue: "리포트 제목", @@ -235,9 +235,9 @@ function getTemplateLayout(templateId: string): TemplateLayout | null { height: 100, fontSize: 14, fontColor: "#000000", - backgroundColor: "#ffffff", + backgroundColor: "transparent", borderColor: "#cccccc", - borderWidth: 1, + borderWidth: 0, zIndex: 1, defaultValue: "내용을 입력하세요", }, @@ -381,6 +381,8 @@ export function ReportDesignerProvider({ reportId, children }: { reportId: strin // 레이아웃이 없으면 기본값 사용 console.log("레이아웃 없음, 기본값 사용"); } + + // 쿼리 조회는 이미 위에서 처리됨 (reportResponse.data.queries) } catch (error) { const errorMessage = error instanceof Error ? error.message : "리포트를 불러오는데 실패했습니다."; toast({ @@ -396,7 +398,8 @@ export function ReportDesignerProvider({ reportId, children }: { reportId: strin // 초기 로드 useEffect(() => { loadLayout(); - }, [loadLayout]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [reportId]); // 쿼리 결과 저장 const setQueryResult = useCallback((queryId: string, fields: string[], rows: Record[]) => {