ERP-node/frontend/app/(pop)/pop/test-v4/page.tsx

151 lines
4.8 KiB
TypeScript

"use client";
import { useState, useCallback } from "react";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import {
PopLayoutDataV4,
createEmptyPopLayoutV4,
addComponentToV4Layout,
removeComponentFromV4Layout,
updateComponentInV4Layout,
updateContainerV4,
findContainerV4,
PopComponentType,
PopComponentDefinitionV4,
PopContainerV4,
} from "@/components/pop/designer/types/pop-layout";
import { PopCanvasV4 } from "@/components/pop/designer/PopCanvasV4";
import { PopPanel } from "@/components/pop/designer/panels/PopPanel";
import { ComponentEditorPanelV4 } from "@/components/pop/designer/panels/ComponentEditorPanelV4";
// ========================================
// v4 테스트 페이지
//
// 목적: v4 렌더러, 캔버스, 속성 패널 테스트
// 경로: /pop/test-v4
// ========================================
export default function TestV4Page() {
// 레이아웃 상태
const [layout, setLayout] = useState<PopLayoutDataV4>(() => {
// 초기 테스트 데이터
const initial = createEmptyPopLayoutV4();
return initial;
});
// 선택 상태
const [selectedComponentId, setSelectedComponentId] = useState<string | null>(null);
const [selectedContainerId, setSelectedContainerId] = useState<string | null>(null);
// 컴포넌트 ID 카운터
const [idCounter, setIdCounter] = useState(1);
// 선택된 컴포넌트/컨테이너 가져오기
const selectedComponent = selectedComponentId
? layout.components[selectedComponentId]
: null;
const selectedContainer = selectedContainerId
? findContainerV4(layout.root, selectedContainerId)
: null;
// 컴포넌트 드롭
const handleDropComponent = useCallback(
(type: PopComponentType, containerId: string) => {
const componentId = `comp_${idCounter}`;
setIdCounter((prev) => prev + 1);
setLayout((prev) =>
addComponentToV4Layout(prev, componentId, type, containerId, `${type} ${idCounter}`)
);
setSelectedComponentId(componentId);
setSelectedContainerId(null);
},
[idCounter]
);
// 컴포넌트 삭제
const handleDeleteComponent = useCallback((componentId: string) => {
setLayout((prev) => removeComponentFromV4Layout(prev, componentId));
setSelectedComponentId(null);
}, []);
// 컴포넌트 업데이트
const handleUpdateComponent = useCallback(
(componentId: string, updates: Partial<PopComponentDefinitionV4>) => {
setLayout((prev) => updateComponentInV4Layout(prev, componentId, updates));
},
[]
);
// 컨테이너 업데이트
const handleUpdateContainer = useCallback(
(containerId: string, updates: Partial<PopContainerV4>) => {
setLayout((prev) => ({
...prev,
root: updateContainerV4(prev.root, containerId, updates),
}));
},
[]
);
// 선택
const handleSelectComponent = useCallback((id: string | null) => {
setSelectedComponentId(id);
if (id) setSelectedContainerId(null);
}, []);
const handleSelectContainer = useCallback((id: string | null) => {
setSelectedContainerId(id);
if (id) setSelectedComponentId(null);
}, []);
return (
<DndProvider backend={HTML5Backend}>
<div className="flex h-screen w-screen overflow-hidden bg-gray-100">
{/* 왼쪽: 컴포넌트 팔레트 */}
<div className="w-64 shrink-0 border-r bg-white">
<div className="border-b px-4 py-3">
<h2 className="text-sm font-semibold">v4 </h2>
<p className="text-xs text-muted-foreground"> </p>
</div>
<PopPanel />
</div>
{/* 중앙: 캔버스 */}
<div className="flex-1 overflow-hidden">
<PopCanvasV4
layout={layout}
selectedComponentId={selectedComponentId}
selectedContainerId={selectedContainerId}
onSelectComponent={handleSelectComponent}
onSelectContainer={handleSelectContainer}
onDropComponent={handleDropComponent}
onUpdateComponent={handleUpdateComponent}
onUpdateContainer={handleUpdateContainer}
onDeleteComponent={handleDeleteComponent}
/>
</div>
{/* 오른쪽: 속성 패널 */}
<div className="w-72 shrink-0 border-l bg-white">
<ComponentEditorPanelV4
component={selectedComponent}
container={selectedContainer}
onUpdateComponent={
selectedComponentId
? (updates) => handleUpdateComponent(selectedComponentId, updates)
: undefined
}
onUpdateContainer={
selectedContainerId
? (updates) => handleUpdateContainer(selectedContainerId, updates)
: undefined
}
/>
</div>
</div>
</DndProvider>
);
}