Skip to content

Commit c907406

Browse files
committed
refactor: 토픽 편집 사이드 바 컴포넌트 리팩토링
1 parent 8a38a20 commit c907406

2 files changed

Lines changed: 67 additions & 82 deletions

File tree

apps/web/src/components/topic/custom-node.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export default function CustomNode(props: CustomNodeProps) {
5858
};
5959
const updatePosition = async () => {
6060
if (isTopic) {
61+
// TODO: ec2 살아나면 주석 풀기
6162
// await updateTopicPosition(body);
6263
} else {
6364
await updateContentPosition({

apps/web/src/components/topic/edit-topic-sidebar/index.tsx

Lines changed: 66 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useEffect, useState } from "react";
44
import { useRouter } from "next/navigation";
55

6+
import Sidebar from "@/components/sidebar";
67
import { Button } from "@/components/ui/button";
78
import { Input } from "@/components/ui/input";
89
import { TOPIC } from "@/constants/topic";
@@ -12,8 +13,6 @@ import { useTopicStore } from "@/lib/zustand/topic-store";
1213
import { revalidatePath } from "@/utils/revalidate";
1314
import { errorToast, successToast } from "@/utils/toast";
1415
import { Dialog, DialogTrigger } from "@repo/ui/components/dialog";
15-
import { useOutsideClick } from "@repo/ui/hooks/use-outside-click";
16-
import { cn } from "@repo/ui/utils/cn";
1716
import CodeBlock from "@tiptap/extension-code-block";
1817
import Highlight from "@tiptap/extension-highlight";
1918
import Image from "@tiptap/extension-image";
@@ -38,16 +37,18 @@ export default function EditTopicSidebar() {
3837
const { setEditingTopic, setShowEditTopicSidebar, editingTopic, showEditTopicSidebar } =
3938
useTopicStore();
4039

40+
const buttonDisabled = isUpdatePending || isDeletePending;
41+
4142
const onClose = () => {
4243
setEditingTopic(null);
4344
setShowEditTopicSidebar(false);
4445
};
4546

46-
const [sidebarRef] = useOutsideClick<HTMLDivElement>(() => {
47+
const onClickOutside = () => {
4748
if (!isDeleteModalOpen) {
4849
onClose();
4950
}
50-
});
51+
};
5152

5253
const editor = useEditor({
5354
extensions: [
@@ -143,93 +144,76 @@ export default function EditTopicSidebar() {
143144
};
144145

145146
return (
146-
<div
147-
className={cn(
148-
"pointer-events-none fixed inset-0 z-50",
149-
showEditTopicSidebar && "pointer-events-auto bg-black/50"
150-
)}
151-
aria-label="토픽 편집 사이드바 닫기"
152-
>
153-
{/* 사이드바 */}
154-
<div
155-
ref={sidebarRef}
156-
className={cn(
157-
"fixed top-0 right-0 z-50 h-full w-full max-w-xl transform bg-white shadow-xl transition-all duration-300 ease-out",
158-
showEditTopicSidebar ? "translate-x-0" : "translate-x-full"
159-
)}
160-
>
161-
<div className="flex h-full flex-col">
162-
{/* 헤더 */}
163-
<div className="flex items-center justify-between border-b p-6">
164-
<h2 className="text-xl font-semibold">토픽 편집</h2>
165-
<Button variant="ghost" size="icon" onClick={onCloseSidebar} aria-label="사이드바 닫기">
166-
<X size={24} />
167-
</Button>
147+
<Sidebar isOpen={showEditTopicSidebar} onClose={onClickOutside}>
148+
<div className="flex h-full flex-col">
149+
{/* 헤더 */}
150+
<div className="flex items-center justify-between border-b p-6">
151+
<h2 className="text-xl font-semibold">토픽 편집</h2>
152+
<Button variant="ghost" size="icon" onClick={onCloseSidebar} aria-label="사이드바 닫기">
153+
<X size={24} />
154+
</Button>
155+
</div>
156+
157+
{/* 내용 */}
158+
<div className="flex-1 space-y-6 overflow-y-auto p-6">
159+
{/* 제목 입력 */}
160+
<div>
161+
<label className="mb-2 block text-base font-medium">제목</label>
162+
<Input
163+
value={title}
164+
onChange={(e) => setTitle(e.target.value)}
165+
placeholder="토픽 제목을 입력하세요"
166+
className="text-base"
167+
/>
168168
</div>
169169

170-
{/* 내용 */}
171-
<div className="flex-1 overflow-y-auto p-6">
172-
<div className="space-y-6">
173-
{/* 제목 입력 */}
174-
<div>
175-
<label className="mb-2 block text-base font-medium">제목</label>
176-
<Input
177-
value={title}
178-
onChange={(e) => setTitle(e.target.value)}
179-
placeholder="토픽 제목을 입력하세요"
180-
className="text-base"
181-
/>
182-
</div>
183-
184-
{/* 리치 텍스트 툴바 */}
185-
{editor && <EditTopicTooltipList editor={editor} />}
186-
187-
{/* 리치 텍스트 에디터 */}
188-
<div>
189-
<label className="mb-2 block text-base font-medium">내용</label>
190-
<div className="min-h-[400px] rounded-md border bg-white">
191-
<EditorContent editor={editor} />
192-
</div>
193-
</div>
194-
</div>
170+
{/* 리치 텍스트 툴바 */}
171+
{editor && <EditTopicTooltipList editor={editor} />}
172+
173+
{/* 리치 텍스트 에디터 */}
174+
<div className="">
175+
<label className="block text-base font-medium">내용</label>
176+
<EditorContent editor={editor} className="rounded-md border bg-white" />
195177
</div>
178+
</div>
196179

197-
{/* 액션 버튼 */}
198-
<div className="border-t p-6">
199-
<div className="flex gap-2">
180+
{/* 액션 버튼 */}
181+
<div className="border-t p-6">
182+
<div className="flex gap-2">
183+
<Button
184+
onClick={onSave}
185+
className="h-12 flex-1 text-base"
186+
disabled={buttonDisabled || !title.trim()}
187+
>
188+
{isUpdatePending ? (
189+
<Loader2 size={18} className="mr-2 animate-spin" />
190+
) : (
191+
<>
192+
<Save size={18} className="mr-2" />
193+
저장
194+
</>
195+
)}
196+
</Button>
197+
<Dialog>
200198
<Button
201-
onClick={onSave}
202-
className="h-12 flex-1 text-base"
203-
disabled={isUpdatePending || !title.trim()}
199+
className="h-12 bg-red-400 text-base hover:bg-red-500"
200+
asChild
201+
disabled={buttonDisabled}
204202
>
205-
{isUpdatePending ? (
206-
<Loader2 size={18} className="mr-2 animate-spin" />
207-
) : (
208-
<Save size={18} className="mr-2" />
209-
)}
210-
저장
203+
<DialogTrigger>
204+
<Trash2 size={18} className="mr-2" />
205+
삭제
206+
</DialogTrigger>
211207
</Button>
212-
<Dialog>
213-
<Button
214-
className="h-12 bg-red-400 text-base hover:bg-red-500"
215-
asChild
216-
disabled={isUpdatePending || isDeletePending}
217-
>
218-
<DialogTrigger>
219-
<Trash2 size={18} className="mr-2" />
220-
삭제
221-
</DialogTrigger>
222-
</Button>
223-
<RemoveDialogContent
224-
id={editingTopic?.id || null}
225-
setIsDeleteModalOpen={setIsDeleteModalOpen}
226-
onDelete={onDelete}
227-
/>
228-
</Dialog>
229-
</div>
208+
<RemoveDialogContent
209+
id={editingTopic?.id || null}
210+
setIsDeleteModalOpen={setIsDeleteModalOpen}
211+
onDelete={onDelete}
212+
/>
213+
</Dialog>
230214
</div>
231215
</div>
232216
</div>
233-
</div>
217+
</Sidebar>
234218
);
235219
}

0 commit comments

Comments
 (0)