2025-11-05 15:23:57 +09:00
|
|
|
"use client";
|
|
|
|
|
|
2025-11-06 11:40:59 +09:00
|
|
|
import React, { useState, useRef, useCallback } from "react";
|
2025-11-05 15:23:57 +09:00
|
|
|
import { CategoryColumnList } from "@/components/table-category/CategoryColumnList";
|
|
|
|
|
import { CategoryValueManager } from "@/components/table-category/CategoryValueManager";
|
2025-11-06 11:40:59 +09:00
|
|
|
import { GripVertical } from "lucide-react";
|
2025-11-05 15:23:57 +09:00
|
|
|
|
|
|
|
|
interface CategoryWidgetProps {
|
|
|
|
|
widgetId: string;
|
|
|
|
|
tableName: string; // 현재 화면의 테이블
|
2025-11-11 14:32:00 +09:00
|
|
|
menuObjid?: number; // 현재 메뉴 OBJID (메뉴 스코프)
|
2025-11-05 15:23:57 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 카테고리 관리 위젯 (좌우 분할)
|
|
|
|
|
* - 좌측: 현재 테이블의 카테고리 타입 컬럼 목록
|
2025-11-11 14:32:00 +09:00
|
|
|
* - 우측: 선택된 컬럼의 카테고리 값 관리 (메뉴 스코프)
|
2025-11-05 15:23:57 +09:00
|
|
|
*/
|
2025-11-11 14:32:00 +09:00
|
|
|
export function CategoryWidget({ widgetId, tableName, menuObjid }: CategoryWidgetProps) {
|
2025-11-05 15:23:57 +09:00
|
|
|
const [selectedColumn, setSelectedColumn] = useState<{
|
|
|
|
|
columnName: string;
|
|
|
|
|
columnLabel: string;
|
|
|
|
|
} | null>(null);
|
2025-11-06 11:40:59 +09:00
|
|
|
|
|
|
|
|
const [leftWidth, setLeftWidth] = useState(15); // 초기값 15%
|
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const isDraggingRef = useRef(false);
|
|
|
|
|
|
|
|
|
|
const handleMouseDown = useCallback(() => {
|
|
|
|
|
isDraggingRef.current = true;
|
|
|
|
|
document.body.style.cursor = "col-resize";
|
|
|
|
|
document.body.style.userSelect = "none";
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleMouseMove = useCallback((e: MouseEvent) => {
|
|
|
|
|
if (!isDraggingRef.current || !containerRef.current) return;
|
|
|
|
|
|
|
|
|
|
const containerRect = containerRef.current.getBoundingClientRect();
|
|
|
|
|
const newLeftWidth = ((e.clientX - containerRect.left) / containerRect.width) * 100;
|
|
|
|
|
|
|
|
|
|
// 최소 10%, 최대 40%로 제한
|
|
|
|
|
if (newLeftWidth >= 10 && newLeftWidth <= 40) {
|
|
|
|
|
setLeftWidth(newLeftWidth);
|
|
|
|
|
}
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleMouseUp = useCallback(() => {
|
|
|
|
|
isDraggingRef.current = false;
|
|
|
|
|
document.body.style.cursor = "";
|
|
|
|
|
document.body.style.userSelect = "";
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
|
document.addEventListener("mousemove", handleMouseMove);
|
|
|
|
|
document.addEventListener("mouseup", handleMouseUp);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
document.removeEventListener("mousemove", handleMouseMove);
|
|
|
|
|
document.removeEventListener("mouseup", handleMouseUp);
|
|
|
|
|
};
|
|
|
|
|
}, [handleMouseMove, handleMouseUp]);
|
2025-11-05 15:23:57 +09:00
|
|
|
|
|
|
|
|
return (
|
2025-11-06 11:40:59 +09:00
|
|
|
<div ref={containerRef} className="flex h-full min-h-[10px] gap-0">
|
|
|
|
|
{/* 좌측: 카테고리 컬럼 리스트 */}
|
|
|
|
|
<div style={{ width: `${leftWidth}%` }} className="pr-3">
|
2025-11-05 15:23:57 +09:00
|
|
|
<CategoryColumnList
|
|
|
|
|
tableName={tableName}
|
|
|
|
|
selectedColumn={selectedColumn?.columnName || null}
|
|
|
|
|
onColumnSelect={(columnName, columnLabel) =>
|
|
|
|
|
setSelectedColumn({ columnName, columnLabel })
|
|
|
|
|
}
|
2025-11-11 14:32:00 +09:00
|
|
|
menuObjid={menuObjid}
|
2025-11-05 15:23:57 +09:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-06 11:40:59 +09:00
|
|
|
{/* 리사이저 */}
|
|
|
|
|
<div
|
|
|
|
|
onMouseDown={handleMouseDown}
|
|
|
|
|
className="group relative flex w-3 cursor-col-resize items-center justify-center border-r hover:bg-accent/50 transition-colors"
|
|
|
|
|
>
|
|
|
|
|
<GripVertical className="h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* 우측: 카테고리 값 관리 */}
|
|
|
|
|
<div style={{ width: `${100 - leftWidth - 1}%` }} className="pl-3">
|
2025-11-05 15:23:57 +09:00
|
|
|
{selectedColumn ? (
|
|
|
|
|
<CategoryValueManager
|
|
|
|
|
tableName={tableName}
|
|
|
|
|
columnName={selectedColumn.columnName}
|
|
|
|
|
columnLabel={selectedColumn.columnLabel}
|
2025-11-11 14:32:00 +09:00
|
|
|
menuObjid={menuObjid}
|
2025-11-05 15:23:57 +09:00
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<div className="flex h-64 flex-col items-center justify-center rounded-lg border bg-card shadow-sm">
|
|
|
|
|
<div className="flex flex-col items-center gap-2 text-center">
|
|
|
|
|
<p className="text-sm text-muted-foreground">
|
|
|
|
|
좌측에서 관리할 카테고리 컬럼을 선택하세요
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|