Skip to content

Commit 7ea5473

Browse files
Yushin-Lclaude
andcommitted
Add edit button on post detail page for post author
- Show "수정" button in DynamicPostView when logged-in user is the author - Link to /write?edit=<id> to auto-select the draft in the editor - WritePage reads ?edit query param and auto-loads the matching draft Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 37f1b27 commit 7ea5473

2 files changed

Lines changed: 35 additions & 5 deletions

File tree

src/app/write/page.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use client";
22

3-
import { useEffect, useRef, useState } from "react";
3+
import { Suspense, useEffect, useRef, useState } from "react";
4+
import { useSearchParams } from "next/navigation";
45
import { useAuth } from "@/hooks/useAuth";
56
import ProtectedRoute from "@/components/auth/ProtectedRoute";
67
import NovelEditor from "@/components/editor/NovelEditor";
@@ -17,6 +18,8 @@ import type { PostDraft } from "@/lib/supabase/types";
1718

1819
function WritePage() {
1920
const { user } = useAuth();
21+
const searchParams = useSearchParams();
22+
const editId = searchParams.get("edit");
2023

2124
const [drafts, setDrafts] = useState<PostDraft[]>([]);
2225
const [currentDraft, setCurrentDraft] = useState<PostDraft | null>(null);
@@ -28,11 +31,23 @@ function WritePage() {
2831
const [message, setMessage] = useState("");
2932
const [mdMode, setMdMode] = useState(false);
3033
const editorRef = useRef<any>(null);
34+
const [editApplied, setEditApplied] = useState(false);
3135

3236
useEffect(() => {
3337
if (user) loadDrafts();
3438
}, [user]);
3539

40+
// ?edit=<id> 쿼리파라미터로 진입 시 해당 draft 자동 선택
41+
useEffect(() => {
42+
if (editId && drafts.length > 0 && !editApplied) {
43+
const target = drafts.find((d) => d.id === editId);
44+
if (target) {
45+
selectDraft(target);
46+
setEditApplied(true);
47+
}
48+
}
49+
}, [editId, drafts, editApplied]);
50+
3651
async function loadDrafts() {
3752
if (!user) return;
3853
try {
@@ -285,7 +300,9 @@ function WritePage() {
285300
export default function WritePageWrapper() {
286301
return (
287302
<ProtectedRoute requireApproved>
288-
<WritePage />
303+
<Suspense>
304+
<WritePage />
305+
</Suspense>
289306
</ProtectedRoute>
290307
);
291308
}

src/components/posts/DynamicPostView.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
"use client";
22

33
import { useEffect, useState } from "react";
4+
import Link from "next/link";
45
import { getPublishedPostBySlug } from "@/lib/drafts/published";
6+
import { useAuth } from "@/hooks/useAuth";
57
import MarkdownContent from "./MarkdownContent";
68
import TagBadge from "./TagBadge";
79
import LikeButton from "./LikeButton";
@@ -13,6 +15,7 @@ interface DynamicPostViewProps {
1315
}
1416

1517
export default function DynamicPostView({ slug }: DynamicPostViewProps) {
18+
const { user } = useAuth();
1619
const [post, setPost] = useState<PostDraft | null>(null);
1720
const [loading, setLoading] = useState(true);
1821
const [notFound, setNotFound] = useState(false);
@@ -49,9 +52,19 @@ export default function DynamicPostView({ slug }: DynamicPostViewProps) {
4952
return (
5053
<article className="mx-auto max-w-3xl">
5154
<header className="mb-8">
52-
<h1 className="text-3xl font-bold tracking-tight text-stone-900">
53-
{post.title}
54-
</h1>
55+
<div className="flex items-start justify-between gap-4">
56+
<h1 className="text-3xl font-bold tracking-tight text-stone-900">
57+
{post.title}
58+
</h1>
59+
{user && user.id === post.author_id && (
60+
<Link
61+
href={`/write?edit=${post.id}`}
62+
className="shrink-0 rounded-lg border border-stone-300 px-4 py-2 text-sm font-medium text-stone-600 transition-colors hover:bg-stone-50"
63+
>
64+
수정
65+
</Link>
66+
)}
67+
</div>
5568
<div className="mt-4 flex flex-wrap items-center gap-3">
5669
<span className="text-sm text-stone-500">
5770
{post.author_name ? `${post.author_name} · ` : ""}

0 commit comments

Comments
 (0)