diff --git a/README.md b/README.md index aa858b2cc71071cde642b0426f3dd73a1442877d..6e5239d7c16134fdb944bbab0731de4489115e58 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ |---|---|---|---| |POST|/article|{<br>"title": string,<br>"content": string,<br>"img": string[],<br>"keyword": string,<br>"latitiude":number,<br>"longitude": number<br>}|寃뚯떆湲� �묒꽦 �붿껌| |DELETE|/article/[id]||�뱀젙 寃뚯떆湲� ��젣 �붿껌| -|GET|/article||�꾩껜 寃뚯떆湲� �붿껌| +|GET|/article?keyword=?criteria=||議곌굔�� 留욌뒗 �꾩껜 寃뚯떆湲� �붿껌| |GET|/article/[id]||�뱀젙 寃뚯떆湲� �붿껌| +|GET|/article/user/[userId]||�뱀젙 �ъ슜�먯쓽 寃뚯떆湲� �붿껌| |GET|/article/search/[keyword]||�ㅼ썙�쒕줈 寃뚯떆湲� 寃��� �붿껌| |GET|/article/sort/[crit]||寃뚯떆湲� �뺣젹 �붿껌| |POST|/article/[id]/comment|{<br>"content": string<br>}|�볤� �묒꽦 �붿껌| diff --git a/backend/src/article/articleController.js b/backend/src/article/articleController.js index fa661b167c2da2db9deacec42cc402bc6e73d38d..fef9cfbb1ea49e2e5d6816bb67e61605c08f344a 100644 --- a/backend/src/article/articleController.js +++ b/backend/src/article/articleController.js @@ -61,7 +61,8 @@ router.get("/", async (req, res) => { if (!req.session.sessionid) { console.log("No session"); } - const articles = await articleService.findAllArticle(); + + const articles = await articleService.findArticles(req.query.keyword ? req.query.keyword : null, req.query.criteria); articles.forEach((article) => { article.imageUrls.forEach( (urls) => { @@ -82,7 +83,9 @@ router.get("/:id", async (req, res) => { } const articles = await articleService.findArticleById(req.params.id); res.send(JSON.stringify(articles)); -}).delete("/:id", async (req, res) => { +}); + +router.delete("/:id", async (req, res) => { if (!req.session.sessionid) { console.log("No session - del"); } @@ -90,6 +93,14 @@ router.get("/:id", async (req, res) => { res.send(JSON.stringify(articles)); }); +router.get("/user/:id", async (req, res) => { + if (!req.session.sessionid) { + console.log("No session"); + } + const articles = await articleService.findArticlesByAuthor(req.params.id); + res.send(JSON.stringify(articles)); +}); + router.post("/:id/comment", async (req, res) => { if (!req.session.sessionid) { console.log("No session"); @@ -120,28 +131,4 @@ router.put("/:id/like", async (req, res) => { res.send(JSON.stringify(articles)); }); -router.get("/search/:keyword", async (req, res) => { - if (req.session.sessionid) { - console.log("�몄뀡 O") - } - else { - console.log("�몄뀡 X") - } - console.log(req.params.keyword) - const articles = await articleService.findArticlesByKeyword(req.params.keyword); - res.send(JSON.stringify(articles)); -}); - -router.get("/sort/:crit", async (req, res) => { - if (req.session.sessionid) { - console.log("�몄뀡 O") - } - else { - console.log("�몄뀡 X") - } - console.log(req.params.crit) - const articles = await articleService.findAllAndSortArticle(req.params.crit); - res.send(JSON.stringify(articles)); -}); - export default router; diff --git a/backend/src/article/articleService.js b/backend/src/article/articleService.js index 0f29cd708da9256f8aff7ed86160b3d4f66151b2..bbb1a02b857988077cad33e90782dc62aa8d576d 100644 --- a/backend/src/article/articleService.js +++ b/backend/src/article/articleService.js @@ -11,15 +11,67 @@ const articleService = { } }, - async findAllArticle() { - try { - const articles = await Article - .find({}) - .populate('author') - .populate('likes'); - return articles; - } catch (err) { - throw err; + async findArticles(keyword, criteria) { + if (criteria === "like") { + try { + const agg = + await Article.aggregate( + [ + { + "$project": + { + "title": 1, + "content": 1, + "imageUrls": 1, + "author": 1, + "keyword": 1, + "latitude": 1, + "longitude": 1, + "comments": 1, + "likes": 1, + "createdAt": 1, + "length": { "$size": "$likes" } + } + }, + { "$sort": { "length": -1 } }, + ] + ) + let articles = null; + const result = await Article.populate(agg, { path: "author" }).then( + (res) => { return Article.populate(res, { path: "likes" }) } + ).then( + (res) => { articles = res; } + ); + return articles; + } catch (err) { + throw err; + } + } + else { + if (keyword === null) { + try { + const articles = await Article + .find({}) + .populate('author') + .populate('likes') + .sort({ "createdAt": -1 }); + return articles; + } catch (err) { + throw err; + } + } + else { + try { + const articles = await Article + .find({ keyword: keyword }) + .populate('author') + .populate('likes') + .sort({ "createdAt": -1 }); + return articles; + } catch (err) { + throw err; + } + } } }, @@ -99,7 +151,8 @@ const articleService = { const articles = await Article .find({ author: authorId }) .populate('author') - .populate('likes'); + .populate('likes') + .sort({ "createdAt": -1 }); return articles; } catch (err) { throw err; @@ -111,7 +164,8 @@ const articleService = { const articles = await Article .find({ keyword: keyword }) .populate('author') - .populate('likes'); + .populate('likes') + .sort({ "createdAt": -1 }); return articles; } catch (err) { throw err; diff --git a/backend/src/auth/authController.js b/backend/src/auth/authController.js index b46d23e8d7430d9dec919fb46d6419cfbf90dc66..d7ba4917e94b7a9f39e16500f82c06f3131ac3c6 100644 --- a/backend/src/auth/authController.js +++ b/backend/src/auth/authController.js @@ -15,23 +15,27 @@ router.post('/login', async (req, res) => { const expires = moment().add(sessionTime.toString(), 'm').toDate(); // �뺣낫媛� �녿떎硫� �뚯썝 媛��� (媛뺤젣?) - const user = await userService.existsByEmail(req.body.email); + const user = await userService.findUserByEmail(req.body.email); + let userId = null; if (!user) { // �좎�媛� �녿떎硫� �뚯썝 媛��� �� �몄뀡 �앹꽦 let userProfilePicture = req.body.picture || null; - await userService.createUser({ + userId = await userService.createUser({ nickname: req.body.name, email: req.body.email, google: { id: req.body.sub, profileUrl: userProfilePicture, }, - }); - console.log('new user saved!') + }).then((user) => user._id); + console.log('new user saved!'); + } + else { + userId = user._id; } - console.log('login done') + console.log('login done'); req.session.sessionid = req.body; //�꾨줎�몄뿉�� 嫄대꽕諛쏆� JWT濡� �몄뀡 �앹꽦 - res.cookie('name', JSON.stringify({ name: req.body.name, email: req.body.email, id: req.body.sub }), { expires }); //�ъ슜�� �대쫫 荑좏궎 + res.cookie('name', JSON.stringify({ name: req.body.name, email: req.body.email, id: userId }), { expires }); //�ъ슜�� �대쫫 荑좏궎 res.send(req.body.name); // �대쫫 蹂대궡�� 萸먰븯寃�? diff --git a/frontend/src/App.js b/frontend/src/App.js index 134840470f5448d9bfa7d62f66ba3be8a06ca30e..f4a0442b813612d6d8477e8256518dca890b01ac 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -14,6 +14,7 @@ import PostRead from "./pages/PostRead.js" import Header from "./components/Header.js"; import axios from 'axios'; +import MyPage from "./pages/MyPage.js"; axios.defaults.withCredentials = true; function App() { @@ -71,6 +72,7 @@ function App() { <Route path="/search" element={<Search />}></Route> <Route path="/postwrite" element={<PostWrite />}></Route> <Route path="/post/:id" element={<PostRead />}></Route> + <Route path="/mypage" element={<MyPage />}></Route> </Routes> </UserContext.Provider> {/* <Footer/> */} diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js index ef0252f8f8bdcd6c0250596f41e0a5d41365010e..e8b2e5a9de37ba235fb4894b577d2ae412b0c12f 100644 --- a/frontend/src/components/Header.js +++ b/frontend/src/components/Header.js @@ -47,7 +47,7 @@ function Header({ cookie }) { <img className="logo_image" alt="logo" src={logo} /> </ButtonLink> <ul> - <p>{cookie ? `${cookie.name}��, �섏쁺�⑸땲��` : '濡쒓렇�명븯�몄슂.'}</p> + <p>{cookie ? (<Link to="/mypage" style={{ textDecoration: "none", color: "black" }}>{cookie.name}��, �섏쁺�⑸땲��</Link>) : '濡쒓렇�명븯�몄슂.'}</p> <ul className="menu_list"> <li><ButtonLink link='/'>Home</ButtonLink></li> <li><ButtonLink link='/search'>寃���</ButtonLink></li> diff --git a/frontend/src/components/SearchMapByKeyword.js b/frontend/src/components/SearchMapByKeyword.js index f1f8883246b3e5cdf7fecdaac2b3f7ce2d5ff275..f7e4abaa39accf590b94ca8b8855a5a79465d46c 100644 --- a/frontend/src/components/SearchMapByKeyword.js +++ b/frontend/src/components/SearchMapByKeyword.js @@ -58,7 +58,7 @@ function SearchMapByKeyword({ loc, setLoc }) { return ( <div className="UserInput"> <input onChange={handleInput} /> - <button onClick={() => handleSearch()} style={{ width: '50px' }}>寃���</button><br></br> + <button onClick={() => handleSearch()} style={{ width: '50px', height: '30px' }}>寃���</button><br></br> <div style={{ display: 'flex' }}> <Map // 吏��꾨� �쒖떆�� Container center={info && info.position || defaultCenter} diff --git a/frontend/src/pages/Main.js b/frontend/src/pages/Main.js index 40f083ab426a3b3b43c62592dfeb1d3da0b28dd0..2757d01a1530b23449b62e277e0e0f5d7e77a7fa 100644 --- a/frontend/src/pages/Main.js +++ b/frontend/src/pages/Main.js @@ -34,7 +34,7 @@ function Main() { .then((response) => { console.log(response) setArticleList(response.data) - }) + }); }, []); const handleSortChange = (event) => { @@ -49,7 +49,7 @@ function Main() { <div className="App"> <h1>紐⑤몢�� 繇잓걪與�</h1> <div className="intro"> - <p>媛�蹂닿퀬 �띠� �앸떦�� 李얠븘蹂닿퀬, <br/>媛�蹂� �앸떦�� 湲곕줉�대낫�몄슂!</p> + <p>媛�蹂닿퀬 �띠� �앸떦�� 李얠븘蹂닿퀬, <br />媛�蹂� �앸떦�� 湲곕줉�대낫�몄슂!</p> </div> <div style={{ display: 'flex' }}> <select id="addInputPrior" defaultValue={"time"} onChange={handleSortChange}> @@ -61,17 +61,9 @@ function Main() { </div>); } -async function requestLoadArticle() { - const response = await axios({ - url: 'http://localhost:8080/article', // �듭떊�� �밸Ц�� - method: 'get', // �듭떊�� 諛⑹떇 - }); - return response; -} - async function requestSortArticle(crit) { const response = await axios({ - url: `http://localhost:8080/article/sort/${crit}`, // �듭떊�� �밸Ц�� + url: `http://localhost:8080/article/?criteria=${crit}`, // �듭떊�� �밸Ц�� method: 'get', // �듭떊�� 諛⑹떇 }); return response; diff --git a/frontend/src/pages/MyPage.js b/frontend/src/pages/MyPage.js new file mode 100644 index 0000000000000000000000000000000000000000..be8f413d321c40478f6e4923aeca5ba26ff49502 --- /dev/null +++ b/frontend/src/pages/MyPage.js @@ -0,0 +1,52 @@ +import { useNavigate } from 'react-router-dom'; + +import { UserContext } from '../Context.js'; +import Article from '../components/Article.js'; +import cookie from 'react-cookies'; +import React, { useEffect, useState, useContext } from 'react'; + +import axios from 'axios'; +axios.defaults.withCredentials = true; + +function MyPage() { + const userContext = useContext(UserContext); + const [articleList, setArticleList] = useState([]); + const userinfo = cookie.load('name'); + + let listItem = []; + listItem = articleList.map((article) => { + return ( + <Article + key={article._id} + data={article} + ></Article> + ) + }); + + useEffect(() => { + requestArticles(userinfo.id) + .then((response) => { + setArticleList(response.data) + }) + }, []); + + return ( + <div className="App"> + <h1>{userinfo.name}�섏쓽 �섏씠吏�</h1> + <div className="introduction"> + {articleList.length}媛쒖쓽 寃뚯떆湲��� �덉뒿�덈떎. + </div> + + {listItem} + </div>); +} + +async function requestArticles(id) { + const response = await axios({ + url: `http://localhost:8080/article/user/${id}`, // �듭떊�� �밸Ц�� + method: 'get', // �듭떊�� 諛⑹떇 + }); + return response; +} + +export default MyPage; \ No newline at end of file diff --git a/frontend/src/pages/PostRead.js b/frontend/src/pages/PostRead.js index c8a34bbb3bb840e66f63a0541dce19acd59bef74..a017827080992fd4fdf97086243ad3ffdadfc22e 100644 --- a/frontend/src/pages/PostRead.js +++ b/frontend/src/pages/PostRead.js @@ -113,7 +113,7 @@ function PostRead() { <Article data={article}></Article> <div style={{ display: 'flex' }}> <button onClick={SetLike}>醫뗭븘��</button> - <DelButton isThatYou={userinfo.id === article.author.google.id} target={article}></DelButton> + <DelButton isThatYou={userinfo.id === article.author._id} target={article}></DelButton> </div> <ArticleContext.Provider value={{ requestLoadArticleById, setArticle }}> { diff --git a/frontend/src/pages/Search.js b/frontend/src/pages/Search.js index bdbd18a0f27c41b038ecbd2d3c85ac0460c7a832..ccab414f35f6a7e6baa9a5d6f48b6f33ecfaf61c 100644 --- a/frontend/src/pages/Search.js +++ b/frontend/src/pages/Search.js @@ -28,13 +28,6 @@ function Search(props) { alert("濡쒓렇�� 諛붾엻�덈떎."); MoveTo('/login'); } - else { - // requestLoadArticle() - // .then((response) => { - // console.log(response) - // setArticleList(response.data) - // }) - } }) .catch((response) => { console.log("error!:LogOut") @@ -88,22 +81,12 @@ function Search(props) { {listItem} </div> </div> - - - ); } -async function requestLoadArticle() { - const response = await axios({ - url: 'http://localhost:8080/article', // �듭떊�� �밸Ц�� - method: 'get', // �듭떊�� 諛⑹떇 - }); - return response; -} async function requestLoadArticleByKeyword(keyword) { const response = await axios({ - url: `http://localhost:8080/article/search/${keyword}`, // �듭떊�� �밸Ц�� + url: `http://localhost:8080/article/?keyword=${keyword}`, // �듭떊�� �밸Ц�� method: 'get', // �듭떊�� 諛⑹떇 }); return response;