From 86cfc7172bfc66bb33ee3ceb7bc93df5faaeeed8 Mon Sep 17 00:00:00 2001 From: Hyun Woo Jeong <jhw0714@ajou.ac.kr> Date: Tue, 5 Dec 2023 14:43:01 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=95=EB=A0=AC,=20=EA=B2=80=EC=83=89=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/article/articleController.js | 26 +++++++- backend/src/article/articleService.js | 69 +++++++++++++++++++++ backend/src/index.js | 2 +- frontend/src/components/Article.js | 4 +- frontend/src/pages/Main.js | 26 +++++++- frontend/src/pages/Search.js | 77 +++++++++++++++++++++--- 6 files changed, 190 insertions(+), 14 deletions(-) diff --git a/backend/src/article/articleController.js b/backend/src/article/articleController.js index 7a9dd006..78f6a888 100644 --- a/backend/src/article/articleController.js +++ b/backend/src/article/articleController.js @@ -6,8 +6,6 @@ import moment from 'moment' import userService from '../user/userService.js'; import articleService from './articleService.js'; - - const __dirname = path.resolve(); export const router = express.Router(); @@ -116,4 +114,28 @@ 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 61e55028..7d8dc246 100644 --- a/backend/src/article/articleService.js +++ b/backend/src/article/articleService.js @@ -23,6 +23,63 @@ const articleService = { } }, + async findAllAndSortArticle(criteria) { + if (criteria==="time"){ + try { + const articles = await Article + .find({}) + .populate('author') + .populate('likes') + .sort({"createdAt": -1}); + + return articles; + } catch (err) { + throw err; + } + } + else 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 { + console.log("invalid criteria."); + return; + } + + }, + async findArticleById(articleId) { try { const article = await Article @@ -47,6 +104,18 @@ const articleService = { throw err; } }, + + async findArticlesByKeyword(keyword) { + try { + const articles = await Article + .find({ keyword: keyword }) + .populate('author') + .populate('likes'); + return articles; + } catch (err) { + throw err; + } + }, async deleteArticle(articleId) { try { diff --git a/backend/src/index.js b/backend/src/index.js index f7f3d1ff..33a62e67 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -38,7 +38,7 @@ app.use( ); //cors �ㅼ젙�� �쒕떎.. // app.use(express.static(path.join(process.cwd(), '../public'))); -app.use(express.static('files')); +app.use(express.static('public')); app.use(cookieParser()); app.use(express.json()); diff --git a/frontend/src/components/Article.js b/frontend/src/components/Article.js index bdefbd81..1c778fd2 100644 --- a/frontend/src/components/Article.js +++ b/frontend/src/components/Article.js @@ -20,8 +20,8 @@ function Article({ data }) { // http://localhost:8080/uploads/21701487062905.png return ( <img - src={`http://localhost:8080/${el.replaceAll("\\", "/").substring(5)}`} - alt={`http://localhost:8080/${el.replaceAll("\\", "/").substring(5)}`} + src={`http://localhost:8080/${el.replaceAll("\\", "/").substring(7)}`} + alt={`http://localhost:8080/${el.replaceAll("\\", "/").substring(7)}`} style={{ width: "100px", height: "100px" }} /> ) }); diff --git a/frontend/src/pages/Main.js b/frontend/src/pages/Main.js index 6f29dc04..56f4967f 100644 --- a/frontend/src/pages/Main.js +++ b/frontend/src/pages/Main.js @@ -38,13 +38,29 @@ function Main() { }) }, []); + const handleSortChange = (event) => { + console.log(event.target.value) + requestSortArticle(event.target.value) + .then((response) => { + console.log(response) + setArticleList(response.data) + }) + }; + return( <div className="App"> <h1>硫붿씤 �섏씠吏� �낅땲��.</h1> <div className="introduction"> �뚭컻 �댁슜�� �댁쓣 怨듦컙 </div> - <Button>寃���</Button> + <div style={{display: 'flex'}}> + <Button>寃���</Button> + <select id="addInputPrior" onChange={handleSortChange}> + <option value="time">理쒖떊��</option> + <option value="like">�멸린��</option> + </select> + </div> + {listItem} </div>) ; @@ -58,4 +74,12 @@ async function requestLoadArticle() { return response; } + async function requestSortArticle(crit) { + const response = await axios({ + url: `http://localhost:8080/article/sort/${crit}`, // �듭떊�� �밸Ц�� + method: 'get', // �듭떊�� 諛⑹떇 + }); + return response; + } + export default Main; diff --git a/frontend/src/pages/Search.js b/frontend/src/pages/Search.js index c380e2db..7c4cdeea 100644 --- a/frontend/src/pages/Search.js +++ b/frontend/src/pages/Search.js @@ -3,10 +3,13 @@ import React, { useState, useEffect, useContext } from 'react'; import {Routes, Route, Link, useNavigate, Navigate } from 'react-router-dom'; import SearchMap from '../components/SearchMapByKeyword.js' import { UserContext } from '../Context.js'; +import Article from '../components/Article.js'; +import axios from 'axios'; +axios.defaults.withCredentials = true; const {kakao} = window; - function Search(props) { + const [articleList, setArticleList] = useState([]) const userContext = useContext(UserContext); const navigate = useNavigate(); function MoveTo(link){ @@ -24,21 +27,79 @@ function Search(props) { if (!response.data) { alert("�몄뀡�� 留뚮즺�섏뿀�듬땲��. �ㅼ떆 濡쒓렇�� 諛붾엻�덈떎.") MoveTo('/login') - } + } + else { + requestLoadArticle() + .then((response) => { + console.log(response) + setArticleList(response.data) + }) + } }) .catch((response)=>{ console.log("error!:LogOut") console.log(response) }) - }); + }, []); + + let listItem = []; + listItem = articleList.map((article)=>{ + return( + <Article + key={article._id} + data={article} + ></Article> + ) + }) + + const onSubmit = e => { + e.preventDefault(); + if (!location.keyword){ + alert("寃��됰��곸쓣吏��뺥빐二쇱꽭��"); + return + } + requestLoadArticleByKeyword(location.keyword) + .then((response) => { + console.log(response) + setArticleList(response.data) + }) + }; + + return ( + <div style={{display: 'flex'}}> + <div className="search"> + <h1>寃��됲럹�댁��낅땲��.</h1> + <SearchMap loc={location} setLoc={setLocation}></SearchMap> + <form onSubmit={onSubmit} style={{display: 'flex'}}> + <input readonly value={location.keyword} type="text"></input> + <input type="submit"></input> + </form> + </div> + + <div className="searchresult"> + <h1>寃��됯껐怨� {listItem.length} 媛� �뺤씤</h1> + {listItem} + </div> + </div> + + - return ( - <div className="search"> - <h1>寃��됲럹�댁��낅땲��.</h1> - <SearchMap loc={location} setLoc={setLocation}></SearchMap> - </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}`, // �듭떊�� �밸Ц�� + method: 'get', // �듭떊�� 諛⑹떇 + }); + return response; +} export default Search; \ No newline at end of file -- GitLab