diff --git a/package-lock.json b/package-lock.json
index 93a56a7..f865f85 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,8 @@
"version": "0.0.0",
"dependencies": {
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.23.1"
},
"devDependencies": {
"@types/react": "^18.2.14",
@@ -901,6 +902,14 @@
"node": ">= 8"
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
+ "integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -3306,6 +3315,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.23.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz",
+ "integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==",
+ "dependencies": {
+ "@remix-run/router": "1.16.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.23.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz",
+ "integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==",
+ "dependencies": {
+ "@remix-run/router": "1.16.1",
+ "react-router": "6.23.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/reflect.getprototypeof": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
diff --git a/package.json b/package.json
index aab6f17..21e3dac 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,8 @@
},
"dependencies": {
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.23.1"
},
"devDependencies": {
"@types/react": "^18.2.14",
diff --git a/src/App.jsx b/src/App.jsx
index b7f9f7b..66749f5 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,11 +1,18 @@
+import { Route, Routes } from "react-router-dom";
import { NavBar } from "./components/NavBar";
import HomePage from "./pages/HomePage";
+import PostPage from "./pages/PostPage";
+import NewPostPage from "./pages/NewPostPage";
export default function App() {
return (
<>
-
+
+ } />
+ } />
+ } />
+
>
);
}
diff --git a/src/components/Card.jsx b/src/components/Card.jsx
index 471de3b..00ec0f2 100644
--- a/src/components/Card.jsx
+++ b/src/components/Card.jsx
@@ -1,25 +1,30 @@
+import { useNavigate } from "react-router-dom";
import styles from "./Card.module.css";
-export const Card = ({ title, author, likes, createdAt }) => {
- return (
-
-
- {title}
- ❤️ {likes}
-
+export const Card = ({ id, title, author, likes, createdAt }) => {
+ const navigate = useNavigate();
+ return (
+
navigate(`/posts/${id}`)}
+ >
+
+ {title}
+ ❤️{likes}
+
-
글쓴이 : {author}
-
작성일 : {createdAt}
-
- );
+
글쓴이 : {author}
+
작성일 : {createdAt}
+
+ );
};
export const CardSkeleton = () => {
- return (
-
- );
+ return (
+
+ );
};
diff --git a/src/components/Card.module.css b/src/components/Card.module.css
index 813c67b..d425221 100644
--- a/src/components/Card.module.css
+++ b/src/components/Card.module.css
@@ -1,14 +1,19 @@
.card_wrapper {
- width: min(100%, 500px);
+ width: min(100%, 1000px);
margin: 20px auto;
padding: 20px;
- border-radius: 15px;
box-shadow: 0px 0px 50px 0px rgba(0, 0, 0, 0.2);
cursor: pointer;
}
+.card_wrapper:hover {
+ box-shadow: 0px 0px 50px 0px rgba(0, 0, 0, 0.4);
+ background-color: #44559930;
+ transition: 0.25s;
+ cursor: pointer;
+}
.card_head {
display: flex;
diff --git a/src/components/NavBar.jsx b/src/components/NavBar.jsx
index 9f6c588..bdd2b36 100644
--- a/src/components/NavBar.jsx
+++ b/src/components/NavBar.jsx
@@ -1,23 +1,24 @@
+import { Link } from "react-router-dom";
import styles from "./NavBar.module.css";
export const NavBar = () => {
- return (
-
+ );
};
diff --git a/src/components/NavBar.module.css b/src/components/NavBar.module.css
index bd52500..1d211f3 100644
--- a/src/components/NavBar.module.css
+++ b/src/components/NavBar.module.css
@@ -2,7 +2,7 @@
width: 100%;
height: 60px;
- background-color: #303030;
+ background-color: #445599;
color: #fff;
}
diff --git a/src/components/Post.jsx b/src/components/Post.jsx
new file mode 100644
index 0000000..a01da95
--- /dev/null
+++ b/src/components/Post.jsx
@@ -0,0 +1,23 @@
+import { useNavigate } from "react-router-dom";
+import styles from "./Post.module.css";
+
+export const Post = ({ id, title, author, likes, createdAt, content }) => {
+ const navigate = useNavigate();
+ return (
+
+
#{id}번째 게시글
+
+ {title}
+ ❤️ {likes}
+
+
+ {author}
+ {createdAt}
+
+
+
+
+ );
+};
diff --git a/src/components/Post.module.css b/src/components/Post.module.css
new file mode 100644
index 0000000..28b0932
--- /dev/null
+++ b/src/components/Post.module.css
@@ -0,0 +1,44 @@
+.post_wrapper {
+ width: min(100%, 900px);
+
+ margin: 20px auto;
+ padding: 20px;
+
+ box-shadow: 0px 0px 50px 0px rgba(0, 0, 0, 0.2);
+}
+.post_auth {
+ display: flex;
+ gap: 10px;
+ align-items: end;
+ margin: 2px 0px;
+}
+.post_auth > span:first-child {
+ font-weight: bold;
+}
+.post_auth > span:last-child {
+ color: grey;
+ font-size: 14px;
+}
+.post_content {
+ margin: 30px 0px;
+ padding: 20px 0px;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+}
+
+.post_wrapper > button {
+ position: relative;
+ left: 88%;
+ width: 100px;
+ padding: 5px 0px;
+ border: 1px solid #303030;
+ border-radius: 5px;
+ color: #303030;
+ background-color: white;
+}
+.post_wrapper > button:hover {
+ background-color: #44559940;
+ border: 1px solid #303030;
+ transition: 0.5s;
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/src/globals.css b/src/globals.css
index 10f4a31..e7d95e9 100644
--- a/src/globals.css
+++ b/src/globals.css
@@ -18,4 +18,4 @@ a:visited {
}
#root {
-}
+}
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
index fb934ac..2f55934 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -2,9 +2,10 @@ import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./globals.css";
+import { BrowserRouter } from "react-router-dom";
ReactDOM.createRoot(document.getElementById("root")).render(
-
-
-
+
+
+
);
diff --git a/src/pages/PostPage.jsx b/src/pages/PostPage.jsx
new file mode 100644
index 0000000..11c389a
--- /dev/null
+++ b/src/pages/PostPage.jsx
@@ -0,0 +1,50 @@
+import { useEffect, useState } from "react";
+import { Post } from "../components/Post";
+import { useParams } from "react-router-dom";
+
+export default function PostPage() {
+ const [isPending, setIsPending] = useState(false);
+ const [post, setPost] = useState([]);
+ const params = useParams();
+
+ useEffect(() => {
+ setIsPending(true);
+ fetch(`http://localhost:8080/posts/${params.id}`)
+ .then((response) => {
+ return response.json();
+ })
+ .then((post) => {
+ setPost(post);
+ })
+ .finally(() => {
+ setIsPending(false);
+ });
+ }, []);
+ return (
+ <>
+ {isPending ? (
+ <>
+ 로딩중 ...
+ >
+ ) : (
+
+ )}
+ >
+ );
+}