diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..35596405 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +.next/ +.env +.env.local +.DS_Store +npm-debug.log* +yarn-debug.log* +yarn-error.log* \ No newline at end of file diff --git a/README.md b/README.md index fc259f87..b341a0bf 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +<<<<<<< HEAD # ๐Ÿผ ํŒ๋‹ค๋งˆ์ผ“ ํ”„๋กœ์ ํŠธ > _์ด ์ €์žฅ์†Œ๋Š” ํŒ๋‹ค๋งˆ์ผ“ ํ”„๋กœ์ ํŠธ์˜ ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋ฅผ ํด๋ก ํ•˜์—ฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•˜๊ณ , ๊ฐ ๋ธŒ๋žœ์น˜์—์„œ ํ•ด๋‹น ์Šคํ”„๋ฆฐํŠธ ๋ฏธ์…˜์„ ์ˆ˜ํ–‰ํ•ด ์ฃผ์„ธ์š”!_ ๐Ÿ› ๏ธ @@ -48,3 +49,21 @@ _์œ„ ์ด๋ฏธ์ง€๋Š” ํŒ๋‹ค๋งˆ์ผ“์˜ ๋Œ€ํ‘œ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค._ ๐Ÿ“ธ --- ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” [์ฝ”๋“œ์ž‡](https://www.codeit.kr)์˜ ์†Œ์œ ์ด๋ฉฐ, ๊ต์œก ๋ชฉ์ ์œผ๋กœ๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ยฉ 2024 Codeit. All rights reserved. +======= +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## React Compiler + +The React Compiler is not enabled on this template. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. +>>>>>>> d825b2c (CSS ๋ฆฌํŒฉํ† ๋ง ๋ฐ ์ด๋ฏธ์ง€ ๊ด€๋ฆฌ ๊ตฌ์กฐ ๊ฐœ์„ ) diff --git a/app/board/[id]/page.js b/app/board/[id]/page.js new file mode 100644 index 00000000..8fdad135 --- /dev/null +++ b/app/board/[id]/page.js @@ -0,0 +1,360 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import Link from 'next/link'; +import Image from 'next/image'; +import { useRouter, useParams } from 'next/navigation'; + +export default function PostDetailPage() { + const router = useRouter(); + const params = useParams(); + const postId = params?.id; + + const [post, setPost] = useState(null); + const [comments, setComments] = useState([]); + const [commentInput, setCommentInput] = useState(''); + const [editingCommentId, setEditingCommentId] = useState(null); + const [editingContent, setEditingContent] = useState(''); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (postId) { + fetchPostDetail(); + fetchComments(); + } + }, [postId]); + + const fetchPostDetail = async () => { + try { + const response = await fetch(`https://panda-market-api.vercel.app/articles/${postId}`); + if (response.ok) { + const data = await response.json(); + setPost(data); + } + } catch (error) { + console.error('๊ฒŒ์‹œ๊ธ€ ๋กœ๋“œ ์‹คํŒจ:', error); + } finally { + setLoading(false); + } + }; + + const fetchComments = async () => { + try { + const response = await fetch(`https://panda-market-api.vercel.app/articles/${postId}/comments`); + if (response.ok) { + const data = await response.json(); + setComments(data.list || []); + } + } catch (error) { + console.error('๋Œ“๊ธ€ ๋กœ๋“œ ์‹คํŒจ:', error); + } + }; + + const handleCommentSubmit = async () => { + if (!commentInput.trim()) return; + + try { + const response = await fetch(`https://panda-market-api.vercel.app/articles/${postId}/comments`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ content: commentInput.trim() }), + }); + + if (response.ok) { + setCommentInput(''); + fetchComments(); + } + } catch (error) { + console.error('๋Œ“๊ธ€ ๋“ฑ๋ก ์‹คํŒจ:', error); + } + }; + + const handleCommentEdit = async (commentId) => { + if (!editingContent.trim()) return; + + try { + const response = await fetch(`https://panda-market-api.vercel.app/comments/${commentId}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ content: editingContent.trim() }), + }); + + if (response.ok) { + setEditingCommentId(null); + setEditingContent(''); + fetchComments(); + } + } catch (error) { + console.error('๋Œ“๊ธ€ ์ˆ˜์ • ์‹คํŒจ:', error); + } + }; + + const handleCommentDelete = async (commentId) => { + if (!confirm('๋Œ“๊ธ€์„ ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?')) return; + + try { + const response = await fetch(`https://panda-market-api.vercel.app/comments/${commentId}`, { + method: 'DELETE', + }); + + if (response.ok) { + fetchComments(); + } + } catch (error) { + console.error('๋Œ“๊ธ€ ์‚ญ์ œ ์‹คํŒจ:', error); + } + }; + + const handlePostDelete = async () => { + if (!confirm('๊ฒŒ์‹œ๊ธ€์„ ์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?')) return; + + try { + const response = await fetch(`https://panda-market-api.vercel.app/articles/${postId}`, { + method: 'DELETE', + }); + + if (response.ok) { + alert('๊ฒŒ์‹œ๊ธ€์ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.'); + router.push('/board'); + } + } catch (error) { + console.error('๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ์‹คํŒจ:', error); + } + }; + + const formatDate = (dateString) => { + if (!dateString) return ''; + const date = new Date(dateString); + return date.toLocaleDateString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\. /g, '. '); + }; + + if (loading) { + return ( +
+
+
+ + + + +
+ ๋กœ๊ทธ์ธ +
+
+
+
+
๊ฒŒ์‹œ๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค...
+
+
+ ); + } + + if (!post) { + return ( +
+
+
+ + + + +
+ ๋กœ๊ทธ์ธ +
+
+
+
+
๊ฒŒ์‹œ๊ธ€์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
+
+
+ ); + } + + return ( +
+
+
+ + + + + + +
+ + ๋กœ๊ทธ์ธ + +
+
+
+ +
+
+
+ + โ† ๋ชฉ๋ก์œผ๋กœ + + +
+

{post.title}

+ + {post.image && ( +
+ {post.title} { + e.target.style.display = 'none'; + }} + /> +
+ )} + +
+
+ ํŒ๋‹ค๋งˆ์ผ“ + {formatDate(post.createdAt)} +
+
+ ๐Ÿ–ค {post.likeCount || 0} + +
+
+ +
+ {post.content} +
+
+ +
+

+ ๋Œ“๊ธ€ ({comments.length}) +

+ +
+