feat(pop): POP 화면 카테고리 관리 시스템 구현 및 저장/로드 안정화
POP 전용 카테고리 트리 UI 구현 (계층적 폴더 구조) 카테고리 CRUD API 추가 (hierarchy_path LIKE 'POP/%' 필터) 화면 이동 기능 (기존 연결 삭제 후 새 연결 추가 방식) 카테고리/화면 순서 변경 기능 (display_order 교환) 이동 UI를 서브메뉴에서 검색 가능한 모달로 개선 POP 레이아웃 버전 통일 (pop-1.0) 및 로드 로직 수정 DB 스키마 호환성 수정 (writer 컬럼, is_active VARCHAR)
This commit is contained in:
@@ -78,18 +78,24 @@ function PopScreenViewPage() {
|
||||
setScreen(screenData);
|
||||
|
||||
// POP 레이아웃 로드 (screen_layouts_pop 테이블에서)
|
||||
// POP 레이아웃은 sections[] 구조 사용 (데스크톱의 components[]와 다름)
|
||||
try {
|
||||
const popLayout = await screenApi.getLayoutPop(screenId);
|
||||
|
||||
if (popLayout && popLayout.components && popLayout.components.length > 0) {
|
||||
// POP 레이아웃이 있으면 사용
|
||||
console.log("POP 레이아웃 로드:", popLayout.components?.length || 0, "개 컴포넌트");
|
||||
if (popLayout && popLayout.sections && popLayout.sections.length > 0) {
|
||||
// POP 레이아웃 (sections 구조) - 그대로 저장
|
||||
console.log("POP 레이아웃 로드:", popLayout.sections?.length || 0, "개 섹션");
|
||||
setLayout(popLayout as any); // sections 구조 그대로 사용
|
||||
} else if (popLayout && popLayout.components && popLayout.components.length > 0) {
|
||||
// 이전 형식 (components 구조) - 호환성 유지
|
||||
console.log("POP 레이아웃 로드 (이전 형식):", popLayout.components?.length || 0, "개 컴포넌트");
|
||||
setLayout(popLayout as LayoutData);
|
||||
} else {
|
||||
// POP 레이아웃이 비어있으면 빈 레이아웃
|
||||
console.log("POP 레이아웃 없음, 빈 화면 표시");
|
||||
setLayout({
|
||||
screenId,
|
||||
sections: [],
|
||||
components: [],
|
||||
gridSettings: {
|
||||
columns: 12,
|
||||
@@ -101,12 +107,13 @@ function PopScreenViewPage() {
|
||||
opacity: 0.5,
|
||||
snapToGrid: true,
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
}
|
||||
} catch (layoutError) {
|
||||
console.warn("POP 레이아웃 로드 실패:", layoutError);
|
||||
setLayout({
|
||||
screenId,
|
||||
sections: [],
|
||||
components: [],
|
||||
gridSettings: {
|
||||
columns: 12,
|
||||
@@ -118,7 +125,7 @@ function PopScreenViewPage() {
|
||||
opacity: 0.5,
|
||||
snapToGrid: true,
|
||||
},
|
||||
});
|
||||
} as any);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("POP 화면 로드 실패:", error);
|
||||
@@ -222,8 +229,58 @@ function PopScreenViewPage() {
|
||||
maxWidth: isPreviewMode ? currentDevice.width : "100%",
|
||||
}}
|
||||
>
|
||||
{/* 화면 컨텐츠 */}
|
||||
{layout && layout.components && layout.components.length > 0 ? (
|
||||
{/* POP 레이아웃: sections 구조 렌더링 */}
|
||||
{layout && (layout as any).sections && (layout as any).sections.length > 0 ? (
|
||||
<div className="w-full min-h-full p-2">
|
||||
{/* 그리드 레이아웃으로 섹션 배치 */}
|
||||
<div
|
||||
className="grid gap-1"
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(${(layout as any).canvasGrid?.columns || 24}, 1fr)`,
|
||||
}}
|
||||
>
|
||||
{(layout as any).sections.map((section: any) => (
|
||||
<div
|
||||
key={section.id}
|
||||
className="bg-gray-50 border border-gray-200 rounded-lg p-2"
|
||||
style={{
|
||||
gridColumn: `${section.grid?.col || 1} / span ${section.grid?.colSpan || 6}`,
|
||||
gridRow: `${section.grid?.row || 1} / span ${section.grid?.rowSpan || 4}`,
|
||||
minHeight: `${(section.grid?.rowSpan || 4) * 20}px`,
|
||||
}}
|
||||
>
|
||||
{/* 섹션 라벨 */}
|
||||
{section.label && (
|
||||
<div className="text-xs font-medium text-gray-500 mb-1">
|
||||
{section.label}
|
||||
</div>
|
||||
)}
|
||||
{/* 섹션 내 컴포넌트들 */}
|
||||
{section.components && section.components.length > 0 ? (
|
||||
<div className="space-y-1">
|
||||
{section.components.map((comp: any) => (
|
||||
<div
|
||||
key={comp.id}
|
||||
className="bg-white border border-gray-100 rounded p-2 text-sm"
|
||||
>
|
||||
{/* TODO: POP 전용 컴포넌트 렌더러 구현 필요 */}
|
||||
<span className="text-gray-600">
|
||||
{comp.label || comp.type || comp.id}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-xs text-gray-400 text-center py-2">
|
||||
빈 섹션
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : layout && layout.components && layout.components.length > 0 ? (
|
||||
// 이전 형식 (components 구조) - 호환성 유지
|
||||
<ScreenMultiLangProvider components={layout.components} companyCode={companyCode}>
|
||||
<div className="relative w-full min-h-full p-4">
|
||||
{layout.components
|
||||
|
||||
Reference in New Issue
Block a user