diff --git a/src/app/editor/page.tsx b/src/app/editor/page.tsx index 47f976f..e14fd44 100644 --- a/src/app/editor/page.tsx +++ b/src/app/editor/page.tsx @@ -1,6 +1,6 @@ "use client"; -import type { CSSProperties } from "react"; +import type { CSSProperties, ReactNode } from "react"; import { useState } from "react"; import { DndContext, @@ -9,6 +9,7 @@ import { useSensor, useSensors, DragEndEvent, + useDroppable, } from "@dnd-kit/core"; import { SortableContext, @@ -17,16 +18,26 @@ import { } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { useEditorStore } from "@/features/editor/state/editorStore"; -import type { Block } from "@/features/editor/state/editorStore"; +import type { + Block, + TextBlockProps, + ButtonBlockProps, + ImageBlockProps, + SectionBlockProps, +} from "@/features/editor/state/editorStore"; export default function EditorPage() { const blocks = useEditorStore((state) => state.blocks); const selectedBlockId = useEditorStore((state) => state.selectedBlockId); const addTextBlock = useEditorStore((state) => state.addTextBlock); + const addButtonBlock = useEditorStore((state) => state.addButtonBlock); + const addImageBlock = useEditorStore((state) => state.addImageBlock); + const addSectionBlock = useEditorStore((state) => state.addSectionBlock); const updateBlock = useEditorStore((state) => state.updateBlock); const selectBlock = useEditorStore((state) => state.selectBlock); const replaceBlocks = useEditorStore((state) => state.replaceBlocks); const reorderBlocks = useEditorStore((state) => state.reorderBlocks); + const moveBlock = useEditorStore((state) => state.moveBlock); const [editingBlockId, setEditingBlockId] = useState(null); const [editingText, setEditingText] = useState(""); @@ -147,9 +158,64 @@ export default function EditorPage() { const handleDragEnd = (event: DragEndEvent) => { const { active, over } = event; if (!over || active.id === over.id) return; - reorderBlocks(String(active.id), String(over.id)); + const activeId = String(active.id); + const overId = String(over.id); + + // 컬럼 droppable에 드롭한 경우: 해당 섹션/컬럼으로 이동만 수행한다. + if (overId.startsWith("column:")) { + const [, sectionId, columnId] = overId.split(":"); + moveBlock(activeId, sectionId || null, columnId || null); + return; + } + + const activeBlock = blocks.find((b) => b.id === activeId); + const overBlock = blocks.find((b) => b.id === overId); + + if (!activeBlock || !overBlock) { + reorderBlocks(activeId, overId); + return; + } + + const activeSectionId = activeBlock.sectionId ?? null; + const activeColumnId = activeBlock.columnId ?? null; + const overSectionId = overBlock.sectionId ?? null; + const overColumnId = overBlock.columnId ?? null; + + // 같은 섹션/컬럼 내에서는 순서만 변경한다. + if (activeSectionId === overSectionId && activeColumnId === overColumnId) { + reorderBlocks(activeId, overId); + return; + } + + // 다른 컬럼/섹션으로 이동: 위치를 변경한 뒤, 블록 기준 드롭이면 순서 재배치까지 진행한다. + moveBlock(activeId, overSectionId, overColumnId); + reorderBlocks(activeId, overId); }; + const rootBlocks = blocks.filter((block) => !block.sectionId); + + const renderBlocks = (targetBlocks: Block[]) => + targetBlocks.map((block) => { + const isSelected = block.id === selectedBlockId; + const isEditing = block.id === editingBlockId; + + return ( + + ); + }); + return (
@@ -166,6 +232,27 @@ export default function EditorPage() { > 텍스트 블록 추가 + + +

Text / Image / Button / Section 블록을 이 영역에서 추가할 수 있습니다.

@@ -188,24 +275,7 @@ export default function EditorPage() { items={blocks.map((b) => b.id)} strategy={verticalListSortingStrategy} > - {blocks.map((block) => { - const isSelected = block.id === selectedBlockId; - const isEditing = block.id === editingBlockId; - - return ( - - ); - })} + {renderBlocks(rootBlocks)} )} @@ -214,66 +284,238 @@ export default function EditorPage() {

속성 패널

{selectedBlockId ? (
-
-

선택한 텍스트 블록 내용

-