Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into lhj
; Conflicts: ; frontend/components/admin/CreateTableModal.tsx ; frontend/components/screen/CopyScreenModal.tsx ; frontend/components/screen/MenuAssignmentModal.tsx ; frontend/components/screen/ScreenList.tsx ; frontend/components/screen/widgets/FlowWidget.tsx ; frontend/lib/registry/components/table-list/TableListComponent.tsx
This commit is contained in:
104
frontend/components/screen/widgets/CategoryWidget.tsx
Normal file
104
frontend/components/screen/widgets/CategoryWidget.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useRef, useCallback } from "react";
|
||||
import { CategoryColumnList } from "@/components/table-category/CategoryColumnList";
|
||||
import { CategoryValueManager } from "@/components/table-category/CategoryValueManager";
|
||||
import { GripVertical } from "lucide-react";
|
||||
|
||||
interface CategoryWidgetProps {
|
||||
widgetId: string;
|
||||
tableName: string; // 현재 화면의 테이블
|
||||
}
|
||||
|
||||
/**
|
||||
* 카테고리 관리 위젯 (좌우 분할)
|
||||
* - 좌측: 현재 테이블의 카테고리 타입 컬럼 목록
|
||||
* - 우측: 선택된 컬럼의 카테고리 값 관리 (테이블 스코프)
|
||||
*/
|
||||
export function CategoryWidget({ widgetId, tableName }: CategoryWidgetProps) {
|
||||
const [selectedColumn, setSelectedColumn] = useState<{
|
||||
columnName: string;
|
||||
columnLabel: string;
|
||||
} | null>(null);
|
||||
|
||||
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]);
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="flex h-full min-h-[10px] gap-0">
|
||||
{/* 좌측: 카테고리 컬럼 리스트 */}
|
||||
<div style={{ width: `${leftWidth}%` }} className="pr-3">
|
||||
<CategoryColumnList
|
||||
tableName={tableName}
|
||||
selectedColumn={selectedColumn?.columnName || null}
|
||||
onColumnSelect={(columnName, columnLabel) =>
|
||||
setSelectedColumn({ columnName, columnLabel })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 리사이저 */}
|
||||
<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">
|
||||
{selectedColumn ? (
|
||||
<CategoryValueManager
|
||||
tableName={tableName}
|
||||
columnName={selectedColumn.columnName}
|
||||
columnLabel={selectedColumn.columnLabel}
|
||||
/>
|
||||
) : (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export const ButtonWidget: React.FC<WebTypeComponentProps> = ({
|
||||
type="button"
|
||||
onClick={handleClick}
|
||||
disabled={disabled || readonly}
|
||||
className={`rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors duration-200 hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-500 ${className || ""} `}
|
||||
className={`flex items-center justify-center rounded-md bg-blue-600 px-4 text-sm font-medium text-white transition-colors duration-200 hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-500 ${className || ""} `}
|
||||
style={{
|
||||
...style,
|
||||
width: "100%",
|
||||
|
||||
Reference in New Issue
Block a user