리스트/에디터 스타일 정리 및 버그 수정
CI / test (push) Failing after 7m55s
CI / pr_and_merge (push) Has been skipped

This commit is contained in:
2025-11-30 16:52:27 +09:00
parent 17bfac62ed
commit 0cf67b5619
45 changed files with 1606 additions and 530 deletions
+61 -14
View File
@@ -3,6 +3,7 @@
import type { CSSProperties, ReactNode } from "react";
import { Fragment, useEffect, useState } from "react";
import Link from "next/link";
import { FilePlus2, Trash2, Eye, Pencil, ListChecks, Undo2, Redo2 } from "lucide-react";
import {
DndContext,
PointerSensor,
@@ -132,6 +133,11 @@ export default function EditorPage() {
// 멀티 선택(MVP)을 위한 로컬 선택 상태: 단일 선택(selectedBlockId)과 병행 사용한다.
const [selectedBlockIds, setSelectedBlockIds] = useState<string[]>([]);
const historyLength = useEditorStore((state) => (state as any).history?.length ?? 0);
const futureLength = useEditorStore((state) => (state as any).future?.length ?? 0);
const canUndo = historyLength > 0;
const canRedo = futureLength > 0;
const [menuOpen, setMenuOpen] = useState(false);
const [activeModal, setActiveModal] = useState<"project" | "json" | null>(null);
@@ -738,31 +744,57 @@ export default function EditorPage() {
return (
<main className="h-screen flex flex-col overflow-hidden">
<header className="border-b border-slate-800 px-6 py-4 flex items-center justify-between relative z-20">
<div className="flex items-baseline gap-3">
<h1 className="text-xl font-semibold">Page Editor</h1>
<p className="text-xs text-slate-400"> MVP용 </p>
<header className="border-b border-slate-800 px-6 py-4 flex items-center justify-between relative z-20 bg-slate-950/80 backdrop-blur">
<div className="flex items-center gap-3">
<span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-slate-900 border border-sky-700 shadow-sm">
<Pencil className="w-4 h-4 text-sky-400" aria-hidden="true" />
</span>
<div className="flex flex-col">
<h1 className="text-xl font-semibold">Page Editor</h1>
<p className="text-xs text-slate-400"> MVP용 </p>
</div>
</div>
<div className="flex items-center gap-2 text-xs">
<Link
href="/projects"
className="inline-flex items-center rounded border border-slate-700 bg-slate-900 px-3 py-1 text-slate-100 hover:bg-slate-800"
className="inline-flex items-center gap-1 rounded border border-slate-700 bg-slate-900 px-3 py-1 text-slate-100 hover:bg-slate-800"
>
<ListChecks className="w-3 h-3" aria-hidden="true" />
<span> </span>
</Link>
<Link
href="/preview"
className="inline-flex items-center rounded border border-slate-700 bg-slate-900 px-3 py-1 text-slate-100 hover:bg-slate-800"
className="inline-flex items-center gap-1 rounded border border-slate-700 bg-slate-900 px-3 py-1 text-slate-100 hover:bg-slate-800"
>
<Eye className="w-3 h-3" aria-hidden="true" />
<span> </span>
</Link>
<button
type="button"
className="inline-flex items-center gap-1 rounded border border-slate-700 bg-slate-900 px-3 py-1 text-slate-100 hover:bg-slate-800 disabled:opacity-40 disabled:cursor-not-allowed"
onClick={undo}
disabled={!canUndo}
>
<Undo2 className="w-3 h-3" aria-hidden="true" />
<span> </span>
</button>
<button
type="button"
className="inline-flex items-center gap-1 rounded border border-slate-700 bg-slate-900 px-3 py-1 text-slate-100 hover:bg-slate-800 disabled:opacity-40 disabled:cursor-not-allowed"
onClick={redo}
disabled={!canRedo}
>
<Redo2 className="w-3 h-3" aria-hidden="true" />
<span> </span>
</button>
<div className="relative">
<button
type="button"
className="inline-flex items-center gap-1 rounded border border-slate-700 bg-slate-900 px-3 py-1 text-slate-100 hover:bg-slate-800"
onClick={() => setMenuOpen((prev) => !prev)}
>
<FilePlus2 className="w-3 h-3" aria-hidden="true" />
<span></span>
<span className="text-[9px]"></span>
</button>
{menuOpen && (
@@ -775,7 +807,10 @@ export default function EditorPage() {
setActiveModal("project");
}}
>
/
<span className="inline-flex items-center gap-2">
<FilePlus2 className="w-3 h-3" aria-hidden="true" />
<span> /</span>
</span>
</button>
<button
type="button"
@@ -785,7 +820,10 @@ export default function EditorPage() {
setActiveModal("json");
}}
>
JSON /
<span className="inline-flex items-center gap-2">
<FilePlus2 className="w-3 h-3" aria-hidden="true" />
<span>JSON /</span>
</span>
</button>
<button
type="button"
@@ -795,7 +833,10 @@ export default function EditorPage() {
void handleDeleteProject();
}}
>
<span className="inline-flex items-center gap-2">
<Trash2 className="w-3 h-3" aria-hidden="true" />
<span> </span>
</span>
</button>
<button
type="button"
@@ -805,7 +846,10 @@ export default function EditorPage() {
void handleExportZip();
}}
>
(ZIP)
<span className="inline-flex items-center gap-2">
<FilePlus2 className="w-3 h-3" aria-hidden="true" />
<span> (ZIP)</span>
</span>
</button>
<button
type="button"
@@ -817,7 +861,10 @@ export default function EditorPage() {
}
}}
>
<span className="inline-flex items-center gap-2">
<Trash2 className="w-3 h-3" aria-hidden="true" />
<span> </span>
</span>
</button>
</div>
)}