diff --git a/src/Routers.tsx b/src/Routers.tsx index 9030138..adbfcc8 100644 --- a/src/Routers.tsx +++ b/src/Routers.tsx @@ -6,6 +6,7 @@ import Login from './pages/Login.tsx' import Register from './pages/Register.tsx' import Editor from './pages/Editor.tsx' import Book from './pages/Book.tsx' +import Article from './pages/Article.tsx' export default function Routers() { const router = createBrowserRouter([ @@ -19,6 +20,7 @@ export default function Routers() { { path: '/login', element: }, { path: '/register', element: }, { path: '/editor', element: }, + { path: '/article/:articleSlug', element: }, ], }, { diff --git a/src/assets/icons/GoBack.svg b/src/assets/icons/GoBack.svg index 47a8fb5..dff988d 100644 --- a/src/assets/icons/GoBack.svg +++ b/src/assets/icons/GoBack.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/icons/TrashCan.svg b/src/assets/icons/TrashCan.svg index 3fdadcf..dba29e2 100644 --- a/src/assets/icons/TrashCan.svg +++ b/src/assets/icons/TrashCan.svg @@ -1,3 +1,3 @@ - + diff --git a/src/pages/Article.tsx b/src/pages/Article.tsx new file mode 100644 index 0000000..47a89f4 --- /dev/null +++ b/src/pages/Article.tsx @@ -0,0 +1,196 @@ +import { useEffect, useState, useRef } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import { fetchBookData as fetchBookDetails } from '../services/BookService'; +import { HiDotsVertical } from "react-icons/hi"; +import cn from '../libs/cn'; +import Pen from '../assets/icons/Pen.svg'; +import TrashCan from '../assets/icons/TrashCan.svg'; +import DefaultThumbnail from '../assets/images/DefaultThubnail.png'; +import GoBack from '../assets/icons/GoBack.svg'; +import axios from 'axios'; + +interface ArticleData { + title: string; + thumbnail?: string; + context: string; + bookIsbn: string; + date: string; +} + +interface ArticleBookData { + title: string; +} + +export default function Article() { + const { articleSlug } = useParams<{ articleSlug: string }>(); + const [articleData, setArticleData] = useState(null); + const [bookData, setBookData] = useState(null); + const [error, setError] = useState(null); + const [isMenuOpen, setIsMenuOpen] = useState(false); + + const menuRef = useRef(null); + const navigate = useNavigate(); + + useEffect(() => { + if (!articleSlug) return; + + if (articleSlug === 'test') { + setArticleData({ + title: '스벨트는 우주 최강 프레임워크인 것 같다.', + context: '아무래도 리액트를 다 스벨트로 갈아엎어 버리고 싶다. 나는 스벨트를 할 줄 모른다.', + bookIsbn: '9791193926161', + date: '2021-01-01', + thumbnail: undefined, + }); + } else { + const fetchArticleData = async () => { + try { + const response = await axios.get(`/api/article/${articleSlug}`); + setArticleData(response.data); + } catch (error) { + setError('게시글 데이터를 가져오는 중 오류가 발생했습니다.'); + } + }; + fetchArticleData(); + } + }, [articleSlug]); + + useEffect(() => { + if (!articleData?.bookIsbn) return; + + const getBookDetails = async () => { + try { + const data = await fetchBookDetails(articleData.bookIsbn); + setBookData(data); + } catch (err) { + setError('책 정보를 가져오는 중 오류가 발생했습니다.'); + } + }; + getBookDetails(); + }, [articleData?.bookIsbn]); + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (menuRef.current && !menuRef.current.contains(event.target as Node)) { + setIsMenuOpen(false); + } + }; + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, []); + + if (error) { + return 에러가 발생했습니다: {error}; + } + + if (!articleData || !bookData) { + return Loading...; + } + + const { title: articleTitle, context, thumbnail } = articleData; + const { title: bookTitle } = bookData; + + const onEdit = () => { + alert('수정하기'); + }; + + const onDelete = () => { + alert('삭제하기'); + }; + + return ( + + + + + + {/* 게시글 정보 */} + + {articleTitle} + + {`${bookTitle}`}을 읽고 + + {articleData.date} + + + {/* 수정, 삭제 버튼 */} + + + + 독후감 수정 + + + + 삭제하기 + + setIsMenuOpen(!isMenuOpen)} + className='w-6 h-6 md:hidden' + /> + + {/* 메뉴 창 */} + {isMenuOpen && ( + + + 수정 + + + 삭제 + + + )} + + + + {/* 게시글 내용 */} + + {/* 선 만드려고 넣은 div */} + + {context} + + + + {/* 모바일 전용 푸터 */} + + navigate(-1)} + /> + + + ); +} \ No newline at end of file
{context}