diff --git a/src/App.js b/src/App.js index f0a576f..66530ae 100644 --- a/src/App.js +++ b/src/App.js @@ -5,7 +5,9 @@ import Footer from './components/Footer'; import Home from './pages/Home'; import About from './pages/About'; import PostList from './pages/PostList'; +import PostDetail from './pages/PostDetail'; import PostCreate from './pages/PostCreate'; +import PostEdit from './pages/PostEdit'; import PostCategory from './pages/PostCategory'; import Login from './pages/Login'; import { AuthProvider } from './context/AuthContext'; @@ -21,7 +23,9 @@ function App() { } /> } /> } /> + } /> } /> + } /> } /> } /> diff --git a/src/pages/PostDetail.js b/src/pages/PostDetail.js new file mode 100644 index 0000000..d6fee8b --- /dev/null +++ b/src/pages/PostDetail.js @@ -0,0 +1,66 @@ +import React, { useEffect, useState } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import blogApi from '../api/blogApi'; +import { useAuth } from '../context/AuthContext'; + +const PostDetail = () => { + const { id } = useParams(); + const navigate = useNavigate(); + const { isLoggedIn } = useAuth(); + const [post, setPost] = useState(null); + + useEffect(() => { + blogApi.get(`/api/blog/posts/${id}/`) + .then(res => setPost(res.data)) + .catch(err => console.error('게시글 조회 실패:', err)); + }, [id]); + + const handleDelete = async () => { + if (!window.confirm('정말 삭제하시겠습니까?')) return; + + try { + await blogApi.delete(`/api/blog/posts/${id}/`); + alert('게시글이 삭제되었습니다.'); + navigate('/posts'); + } catch (err) { + console.error(err); + alert('삭제 중 오류가 발생했습니다.'); + } + }; + + if (!post) return
Loading...
; + + return ( +
+
+

{post.title}

+ {isLoggedIn && ( +
+ + +
+ )} + +
+

작성자: {post.author_name}

+

+ 작성일: {new Date(post.created_at).toLocaleString()} +

+
+ {post.content} +
+
+ ); +}; + +export default PostDetail; diff --git a/src/pages/PostEdit.js b/src/pages/PostEdit.js new file mode 100644 index 0000000..8b0a821 --- /dev/null +++ b/src/pages/PostEdit.js @@ -0,0 +1,70 @@ +import React, { useEffect, useState } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import blogApi from '../api/blogApi'; +import { useAuth } from '../context/AuthContext'; + +const PostEdit = () => { + const { id } = useParams(); + const navigate = useNavigate(); + const { isLoggedIn } = useAuth(); + const [title, setTitle] = useState(''); + const [content, setContent] = useState(''); + + useEffect(() => { + blogApi.get(`/api/blog/posts/${id}/`) + .then(res => { + setTitle(res.data.title); + setContent(res.data.content); + }) + .catch(err => { + console.error('게시글 불러오기 실패:', err); + alert('게시글을 불러오지 못했습니다.'); + }); + }, [id]); + + const handleSubmit = async () => { + try { + await blogApi.put(`/api/blog/posts/${id}/`, { title, content }); + alert('게시글이 수정되었습니다.'); + navigate(`/posts/${id}`); + } catch (err) { + console.error(err); + alert('수정 실패: ' + (err.response?.data?.detail || '서버 오류')); + } + }; + + if (!isLoggedIn) return
로그인이 필요합니다.
; + + return ( +
+

게시글 수정

+ setTitle(e.target.value)} + /> + +
+ + +
+
+ ); +}; + +export default PostEdit; diff --git a/src/pages/PostList.js b/src/pages/PostList.js index 88b37c8..803a4ae 100644 --- a/src/pages/PostList.js +++ b/src/pages/PostList.js @@ -31,7 +31,11 @@ const PostList = () => {
    {posts.map(post => ( -
  • +
  • navigate(`/posts/${post.id}`)} + >

    {post.title}

    작성자: {post.author_name}

    diff --git a/version b/version index 05b19b1..fa3de58 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.0.4 \ No newline at end of file +0.0.5 \ No newline at end of file