diff --git a/app/admin/posts/page.tsx b/app/admin/posts/page.tsx index f96efbd..5b84e04 100644 --- a/app/admin/posts/page.tsx +++ b/app/admin/posts/page.tsx @@ -28,9 +28,9 @@ const AdminPostListPage = () => { setLoading(false); }; - const handleEdit = (postId: string) => { + const handleEdit = (slug: string) => { toast.success('글 수정 페이지로 이동합니다.'); - router.push(`/admin/write?postId=${postId}`); + router.push(`/admin/write?slug=${slug}`); }; const handleDeleteClick = (postId: string) => { @@ -68,7 +68,7 @@ const AdminPostListPage = () => { handleEdit(post._id)} + handleEdit={() => handleEdit(post.slug)} handleDelete={() => handleDeleteClick(post._id)} /> ))} diff --git a/app/admin/write/page.tsx b/app/admin/write/page.tsx index 8bbb55a..e5f09b6 100644 --- a/app/admin/write/page.tsx +++ b/app/admin/write/page.tsx @@ -1,35 +1,10 @@ -'use client'; import BlogForm from '@/app/entities/post/write/BlogForm'; -import axios from 'axios'; -import { PostBody } from '@/app/types/Post'; -import { useRouter, useSearchParams } from 'next/navigation'; -import useToast from '@/app/hooks/useToast'; const BlogWritePage = () => { - const router = useRouter(); - const params = useSearchParams(); - const postId = params.get('postId'); - const toast = useToast(); - - const postBlog = async (post: PostBody) => { - try { - const response = await axios.post('/api/posts', post); - const data = await response.data; - console.log('글 발행 결과', data); - if (response.status === 201) { - toast.success('글이 성공적으로 발행되었습니다.'); - router.push('/posts'); - } - } catch (e) { - toast.error('글 발행 중 오류 발생했습니다.'); - console.error('글 발행 중 오류 발생', e); - } - }; - return (

글 작성

- +
); }; diff --git a/app/api/posts/[slug]/route.ts b/app/api/posts/[slug]/route.ts index 7fcaf25..d9cc02f 100644 --- a/app/api/posts/[slug]/route.ts +++ b/app/api/posts/[slug]/route.ts @@ -2,6 +2,7 @@ import dbConnect from '@/app/lib/dbConnect'; import Post from '@/app/models/Post'; import { NextRequest } from 'next/server'; +import { getThumbnailInMarkdown } from '@/app/lib/utils/parse'; export async function GET( req: NextRequest, @@ -36,10 +37,14 @@ export async function PUT( await dbConnect(); const body = await req.json(); - const updatedPost = await Post.findByIdAndUpdate(params.slug, body, { - new: true, - runValidators: true, - }).lean(); + const updatedPost = await Post.findOneAndUpdate( + { slug: params.slug }, + { ...body, thumbnailImage: getThumbnailInMarkdown(body.content) }, + { + new: true, + runValidators: true, + } + ).lean(); if (!updatedPost) { return Response.json( diff --git a/app/entities/post/detail/PostTOC.tsx b/app/entities/post/detail/PostTOC.tsx index 8039f90..a36d814 100644 --- a/app/entities/post/detail/PostTOC.tsx +++ b/app/entities/post/detail/PostTOC.tsx @@ -12,7 +12,7 @@ const PostTOC = ({ postContent }: { postContent: string }) => { }; return ( -
+

📌 Table of Contents

    {parseHeadings(postContent).map((heading) => { diff --git a/app/entities/post/write/BlogForm.tsx b/app/entities/post/write/BlogForm.tsx index a7ad1b5..aa45b11 100644 --- a/app/entities/post/write/BlogForm.tsx +++ b/app/entities/post/write/BlogForm.tsx @@ -2,26 +2,21 @@ import '@uiw/react-md-editor/markdown-editor.css'; import '@uiw/react-markdown-preview/markdown.css'; import { useEffect, useState } from 'react'; - -import * as commands from '@uiw/react-md-editor/commands'; import dynamic from 'next/dynamic'; import Link from 'next/link'; -import LoadingIndicator from '@/app/entities/common/Loading/LoadingIndicator'; import { PostBody } from '@/app/types/Post'; import { StaticImport } from 'next/dist/shared/lib/get-img-props'; import LoadingSpinner from '@/app/entities/common/Loading/LoadingSpinner'; import axios from 'axios'; import useToast from '@/app/hooks/useToast'; import { useBlockNavigate } from '@/app/hooks/useBlockNavigate'; +import { useRouter, useSearchParams } from 'next/navigation'; const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { ssr: false }); -interface BlogFormProps { - postBlog: (post: PostBody) => Promise; - postId: string | null; -} - -const BlogForm = ({ postBlog, postId }: BlogFormProps) => { +const BlogForm = () => { + const params = useSearchParams(); + const slug = params.get('slug'); const [submitLoading, setSubmitLoading] = useState(false); const [title, setTitle] = useState(''); const [subTitle, setSubTitle] = useState(''); @@ -30,16 +25,17 @@ const BlogForm = ({ postBlog, postId }: BlogFormProps) => { const [thumbnailImage, setThumbnailImage] = useState(); const [errors, setErrors] = useState([]); const toast = useToast(); + const router = useRouter(); const buttonStyle = `font-bold py-2 px-4 rounded mr-2 disabled:bg-opacity-75 `; const NICKNAME = '개발자 서정우'; useBlockNavigate({ title, content: content || '' }); useEffect(() => { - if (postId) { + if (slug) { getPostDetail(); } - }, [postId]); + }, [slug]); const postBody: PostBody = { title, @@ -50,6 +46,33 @@ const BlogForm = ({ postBlog, postId }: BlogFormProps) => { thumbnailImage, }; + const postBlog = async (post: PostBody) => { + try { + const response = await axios.post('/api/posts', post); + const data = await response.data; + if (response.status === 201) { + toast.success('글이 성공적으로 발행되었습니다.'); + router.push('/posts'); + } + } catch (e) { + toast.error('글 발행 중 오류 발생했습니다.'); + console.error('글 발행 중 오류 발생', e); + } + }; + + const updatePost = async (post: PostBody) => { + try { + const response = await axios.put(`/api/posts/${slug}`, post); + if (response.status === 200) { + toast.success('글이 성공적으로 수정되었습니다.'); + router.push('/posts'); + } + } catch (e) { + toast.error('글 수정 중 오류 발생했습니다.'); + console.error('글 수정 중 오류 발생', e); + } + }; + const validatePost = ( post: PostBody ): { isValid: boolean; errors: string[] } => { @@ -101,7 +124,11 @@ const BlogForm = ({ postBlog, postId }: BlogFormProps) => { return; } - postBlog(post); + if (slug) { + updatePost(post); + } else { + postBlog(post); + } } catch (e) { console.error('글 발행 중 오류 발생', e); setSubmitLoading(false); @@ -110,7 +137,7 @@ const BlogForm = ({ postBlog, postId }: BlogFormProps) => { const getPostDetail = async () => { try { - const response = await axios.get(`/api/posts/${postId}`); + const response = await axios.get(`/api/posts/${slug}`); const data = await response.data; setTitle(data.post.title || 'dd'); setSubTitle(data.post.subTitle); @@ -169,7 +196,7 @@ const BlogForm = ({ postBlog, postId }: BlogFormProps) => { submitHandler(postBody); }} > - {submitLoading ? : postId ? '글 수정' : '글 발행'} + {submitLoading ? : slug ? '글 수정' : '글 발행'}