diff --git a/backend/.gitignore b/.gitignore similarity index 88% rename from backend/.gitignore rename to .gitignore index 3f00a9c7e73aa1d017ffb40ce3c0586e5cf8b764..66c38cf678f4597ed3f897b3d97f768051ed62b6 100644 --- a/backend/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # compiled output /dist -/node_modules +frontend/node_modules +backend/node_modules # Logs logs @@ -19,7 +20,7 @@ lerna-debug.log* /.nyc_output # production -/build +front/build # IDEs and editors /.idea diff --git a/backend/src/article/article.js b/backend/src/article/article.js index 4f0579b6a41b937cf7aebd0af76d996f7059fa0c..a55149ae425a91125100f37e28ce2a736e243287 100644 --- a/backend/src/article/article.js +++ b/backend/src/article/article.js @@ -48,7 +48,7 @@ const ArticleSchema = new mongoose.Schema({ }, comments: { type: [CommentSchema], - unique: false, + unique: false, }, likes: [{ type: mongoose.Schema.Types.ObjectId, diff --git a/backend/src/article/articleController.js b/backend/src/article/articleController.js index 04e4683b49d3b15cf8da81111e525c4ae1659dcc..fa661b167c2da2db9deacec42cc402bc6e73d38d 100644 --- a/backend/src/article/articleController.js +++ b/backend/src/article/articleController.js @@ -121,11 +121,11 @@ router.put("/:id/like", async (req, res) => { }); router.get("/search/:keyword", async (req, res) => { - if(req.session.sessionid){ - console.log("�몄뀡 O") + if (req.session.sessionid) { + console.log("�몄뀡 O") } else { - console.log("�몄뀡 X") + console.log("�몄뀡 X") } console.log(req.params.keyword) const articles = await articleService.findArticlesByKeyword(req.params.keyword); @@ -133,11 +133,11 @@ router.get("/search/:keyword", async (req, res) => { }); router.get("/sort/:crit", async (req, res) => { - if(req.session.sessionid){ - console.log("�몄뀡 O") + if (req.session.sessionid) { + console.log("�몄뀡 O") } else { - console.log("�몄뀡 X") + console.log("�몄뀡 X") } console.log(req.params.crit) const articles = await articleService.findAllAndSortArticle(req.params.crit); diff --git a/backend/src/article/articleService.js b/backend/src/article/articleService.js index 7d8dc24624f37a28f505d57ffc6ac75685ad5612..0f29cd708da9256f8aff7ed86160b3d4f66151b2 100644 --- a/backend/src/article/articleService.js +++ b/backend/src/article/articleService.js @@ -14,9 +14,9 @@ const articleService = { async findAllArticle() { try { const articles = await Article - .find({}) - .populate('author') - .populate('likes'); + .find({}) + .populate('author') + .populate('likes'); return articles; } catch (err) { throw err; @@ -24,26 +24,27 @@ const articleService = { }, async findAllAndSortArticle(criteria) { - if (criteria==="time"){ + if (criteria === "time") { try { const articles = await Article - .find({}) - .populate('author') - .populate('likes') - .sort({"createdAt": -1}); - + .find({}) + .populate('author') + .populate('likes') + .sort({ "createdAt": -1 }); + return articles; } catch (err) { throw err; } } - else if (criteria==="like") { + else if (criteria === "like") { try { - const agg = - await Article.aggregate( - [ - { "$project": + const agg = + await Article.aggregate( + [ { + "$project": + { "title": 1, "content": 1, "imageUrls": 1, @@ -55,19 +56,19 @@ const articleService = { "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; + } + }, + { "$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; @@ -83,10 +84,10 @@ const articleService = { async findArticleById(articleId) { try { const article = await Article - .findById(articleId) - .populate('author') - .populate('comments.author') - .populate('likes'); + .findById(articleId) + .populate('author') + .populate('comments.author') + .populate('likes'); return article; } catch (err) { throw err; @@ -96,21 +97,21 @@ const articleService = { async findArticlesByAuthor(authorId) { try { const articles = await Article - .find({ author: authorId }) - .populate('author') - .populate('likes'); + .find({ author: authorId }) + .populate('author') + .populate('likes'); return articles; } catch (err) { throw err; } }, - + async findArticlesByKeyword(keyword) { try { const articles = await Article - .find({ keyword: keyword }) - .populate('author') - .populate('likes'); + .find({ keyword: keyword }) + .populate('author') + .populate('likes'); return articles; } catch (err) { throw err; @@ -151,7 +152,7 @@ const articleService = { async setLike(articleId, userId) { try { const article = await Article.findById(articleId); - if(article.likes.includes(userId)) { + if (article.likes.includes(userId)) { article.likes.pull({ _id: userId }); } else { diff --git a/backend/src/auth/authController.js b/backend/src/auth/authController.js index 34ee420d6fe1bd62c4300a684c42d7c79384bcf8..b46d23e8d7430d9dec919fb46d6419cfbf90dc66 100644 --- a/backend/src/auth/authController.js +++ b/backend/src/auth/authController.js @@ -8,16 +8,16 @@ export const router = express.Router(); const sessionTime = 60; // �몄뀡�쒓컙(�꾩떆) router.post('/login', async (req, res) => { - /* - TODO: �좏겙�� 臾닿껐�� 泥댄겕 - �좏겙�� �댁긽�� �녿떎硫�, 濡쒓렇��/�뚯썝媛��� 濡쒖쭅�� �섑뻾 �� jwt 荑좏궎瑜� 蹂대궦��. - */ - const expires = moment().add(sessionTime.toString(),'m').toDate(); + /* + TODO: �좏겙�� 臾닿껐�� 泥댄겕 + �좏겙�� �댁긽�� �녿떎硫�, 濡쒓렇��/�뚯썝媛��� 濡쒖쭅�� �섑뻾 �� jwt 荑좏궎瑜� 蹂대궦��. + */ + const expires = moment().add(sessionTime.toString(), 'm').toDate(); - // �뺣낫媛� �녿떎硫� �뚯썝 媛��� (媛뺤젣?) + // �뺣낫媛� �녿떎硫� �뚯썝 媛��� (媛뺤젣?) const user = await userService.existsByEmail(req.body.email); - if (!user) { // �좎�媛� �녿떎硫� �뚯썝 媛��� �� �몄뀡 �앹꽦 - let userProfilePicture = req.body.picture || null; + if (!user) { // �좎�媛� �녿떎硫� �뚯썝 媛��� �� �몄뀡 �앹꽦 + let userProfilePicture = req.body.picture || null; await userService.createUser({ nickname: req.body.name, email: req.body.email, @@ -26,39 +26,39 @@ router.post('/login', async (req, res) => { profileUrl: userProfilePicture, }, }); - console.log('new user saved!') - } - console.log('login done') + console.log('new user saved!') + } + 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 }); //�ъ슜�� �대쫫 荑좏궎 - req.session.sessionid = req.body; //�꾨줎�몄뿉�� 嫄대꽕諛쏆� JWT濡� �몄뀡 �앹꽦 - res.cookie('name', JSON.stringify({name:req.body.name, id:req.body.email}), {expires}); //�ъ슜�� �대쫫 荑좏궎 - - res.send(req.body.name); // �대쫫 蹂대궡�� 萸먰븯寃�? + res.send(req.body.name); // �대쫫 蹂대궡�� 萸먰븯寃�? }); router.get("/logout", (req, res) => { - res.clearCookie('name'); - if (req.session.sessionid) { - req.session.destroy((err) => { - if (err) { - console.log(err) - return; - } - }); - res.send(req.body.name); - } else { - res.send(req.body.name); - } + res.clearCookie('name'); + if (req.session.sessionid) { + req.session.destroy((err) => { + if (err) { + console.log(err) + return; + } + }); + res.send(req.body.name); + } else { + res.send(req.body.name); + } }); router.get("/session", (req, res) => { - if(req.session.sessionid){ - res.send(true); - } + if (req.session.sessionid) { + res.send(true); + } else { - res.send(false); + res.send(false); } }); diff --git a/backend/src/db.js b/backend/src/db.js index 24e8546bd71aca65f942b29c436357f63e5adca3..9c387d23ce191d3869d08cca464ae6f7e041cb16 100644 --- a/backend/src/db.js +++ b/backend/src/db.js @@ -9,7 +9,7 @@ const connectDB = async () => { await mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }); console.log('Database connected'); } catch (error) { - console.error('Database connection failed',error); + console.error('Database connection failed', error); } }; diff --git a/backend/src/index.js b/backend/src/index.js index 33a62e67742eefbc7e0e9a92c8e317ef5526a69b..ad59141554c64fcaff26deefdafd4f3b7518e1b8 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -20,15 +20,15 @@ const sessionTime = 60; // �몄뀡�쒓컙(�꾩떆) connectDB(); -const maxAge = 1000 * 60 * sessionTime; +const maxAge = 1000 * 60 * sessionTime; app.use(session({ - secret: '12345', - resave: true, - saveUninitialized: true, - cookie: { - secure: false, - maxAge: maxAge - } + secret: '12345', + resave: true, + saveUninitialized: true, + cookie: { + secure: false, + maxAge: maxAge + } })) app.use( cors({ diff --git a/backend/src/multer.js b/backend/src/multer.js index 7204ff8170faac80881d21e5ea13bc25eac27f88..cac79bf119dad50b59f49abc82c419dccf3336b6 100644 --- a/backend/src/multer.js +++ b/backend/src/multer.js @@ -10,7 +10,7 @@ import multer from 'multer'; // memoryStorage瑜� �ъ슜�� 寃쎌슦 const multerStorage = multer.memoryStorage(); -const upload = multer({storage: multerStorage}); +const upload = multer({ storage: multerStorage }); // multer �쇱씠釉뚮윭由ш� �꾩옱 �띿뒪�몃� latin1 �쇰줈 泥섎━�섏뿬 �쒓�濡쒕맂 �뚯씪 �대쫫�� 源⑥��� 臾몄젣媛� �덈떎. // Parser �⑥닔瑜� �곕줈 援ы쁽�섏뿬 �ъ슜�섎룄濡� �쒕떎. @@ -18,6 +18,6 @@ export const fileNameParser = fileName => Buffer.from(fileName, 'latin1').toStri // �대떦 �덉젣�먯꽌�� �뚯씪 �곗씠�� �щ윭媛�, JSON�쇰줈 �� �띿뒪�� �곗씠�� �섎굹瑜� 諛쏅뒗 �쇱쓣 媛��뺥븳��. export const articleFormDataHandler = upload.fields([ - {name: 'files', maxCount: 10}, - {name: 'data', maxCount: 1}, + { name: 'files', maxCount: 10 }, + { name: 'data', maxCount: 1 }, ]); \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index 3f00a9c7e73aa1d017ffb40ce3c0586e5cf8b764..0000000000000000000000000000000000000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,41 +0,0 @@ -# compiled output -/dist -/node_modules - -# Logs -logs -*.log -npm-debug.log* -pnpm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# OS -.DS_Store - -# Tests -/coverage -/.nyc_output - -# production -/build - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - -*.env -*.local.env \ No newline at end of file diff --git a/frontend/src/App.js b/frontend/src/App.js index feb13bad280e6d322cbb5f51db7c5b1d0e018508..134840470f5448d9bfa7d62f66ba3be8a06ca30e 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,6 +1,6 @@ import "./css/App.css"; -import {Routes, Route, Link, useNavigate, Navigate } from 'react-router-dom'; -import React, { useEffect, useState, useContext} from 'react'; +import { Routes, Route, Link, useNavigate, Navigate } from 'react-router-dom'; +import React, { useEffect, useState, useContext } from 'react'; import cookie from 'react-cookies'; import { UserContext } from './Context.js'; @@ -17,81 +17,81 @@ import axios from 'axios'; axios.defaults.withCredentials = true; function App() { - - const [ isloggedIn, SetIsloggedIn] = useState(false); - const [ userName, setUserName] = useState(null); - const navigate = useNavigate(); - function MoveTo(link){ - navigate(link) - } - const userinfo = cookie.load('name') - // �ㅻ뜑 �낅뜲�댄듃 - const LogIn = (name)=>{ - // API 濡쒓렇�꾩썐 �붿껌 - // 濡쒓렇�꾩썐 �깃났�� �ㅻ뜑 諛섏쁺 - SetIsloggedIn(true) - setUserName(name) + const [isloggedIn, SetIsloggedIn] = useState(false); + const [userName, setUserName] = useState(null); + const navigate = useNavigate(); + function MoveTo(link) { + navigate(link) + } + + const userinfo = cookie.load('name') + // �ㅻ뜑 �낅뜲�댄듃 + const LogIn = (name) => { + // API 濡쒓렇�꾩썐 �붿껌 + // 濡쒓렇�꾩썐 �깃났�� �ㅻ뜑 諛섏쁺 + SetIsloggedIn(true) + setUserName(name) - console.log("Usercontext:LogIn") - console.log(isloggedIn) - }; - - const LogOut = ()=>{ - // API 濡쒓렇�꾩썐 �붿껌 - requestLogout().then( - (response) => { - // 濡쒓렇�꾩썐 �깃났�� �ㅻ뜑 諛섏쁺 - SetIsloggedIn(false) - setUserName(null) - console.log("Usercontext:LogOut") - console.log(userName) - alert("�뺤긽�곸쑝濡� 濡쒓렇�꾩썐 �섏뿀�듬땲��.") - MoveTo('/') - } - ) - .catch((response)=>{ - console.log("error!:LogOut") - console.log(response) - }) - }; + console.log("Usercontext:LogIn") + console.log(isloggedIn) + }; - const CheckSession = ()=>{ - return requestCheckSession(); - }; + const LogOut = () => { + // API 濡쒓렇�꾩썐 �붿껌 + requestLogout().then( + (response) => { + // 濡쒓렇�꾩썐 �깃났�� �ㅻ뜑 諛섏쁺 + SetIsloggedIn(false) + setUserName(null) + console.log("Usercontext:LogOut") + console.log(userName) + alert("�뺤긽�곸쑝濡� 濡쒓렇�꾩썐 �섏뿀�듬땲��.") + MoveTo('/') + } + ) + .catch((response) => { + console.log("error!:LogOut") + console.log(response) + }) + }; + const CheckSession = () => { + return requestCheckSession(); + }; - return( + + return ( <div className="App"> - <UserContext.Provider value={{isloggedIn, userName, LogIn, LogOut, CheckSession}}> - <Header cookie={userinfo} username={userName}></Header> - <Routes> - <Route path="/" element={<Main/>}></Route> - <Route path="/login" element={<Login/>}></Route> - <Route path="/search" element={<Search/>}></Route> - <Route path="/postwrite" element={<PostWrite/>}></Route> - <Route path="/post/:id" element={<PostRead/>}></Route> - </Routes> - </UserContext.Provider> - {/* <Footer/> */} + <UserContext.Provider value={{ isloggedIn, userName, LogIn, LogOut, CheckSession }}> + <Header cookie={userinfo} username={userName}></Header> + <Routes> + <Route path="/" element={<Main />}></Route> + <Route path="/login" element={<Login />}></Route> + <Route path="/search" element={<Search />}></Route> + <Route path="/postwrite" element={<PostWrite />}></Route> + <Route path="/post/:id" element={<PostRead />}></Route> + </Routes> + </UserContext.Provider> + {/* <Footer/> */} </div> - ); + ); } async function requestLogout() { - const response = await axios({ - url: 'http://localhost:8080/auth/logout', // �듭떊�� �밸Ц�� - method: 'get', // �듭떊�� 諛⑹떇 - }); - return response; - } + const response = await axios({ + url: 'http://localhost:8080/auth/logout', // �듭떊�� �밸Ц�� + method: 'get', // �듭떊�� 諛⑹떇 + }); + return response; +} async function requestCheckSession() { - const response = await axios({ - url: 'http://localhost:8080/auth/session', // �듭떊�� �밸Ц�� - method: 'get', // �듭떊�� 諛⑹떇 - }); - return response; - } + const response = await axios({ + url: 'http://localhost:8080/auth/session', // �듭떊�� �밸Ц�� + method: 'get', // �듭떊�� 諛⑹떇 + }); + return response; +} export default App; \ No newline at end of file diff --git a/frontend/src/Context.js b/frontend/src/Context.js index 056890b00117d649850914cbe0daf1ab8b1070fa..f074140eafbc48335a1c5b31a42e29e6e694c4ac 100644 --- a/frontend/src/Context.js +++ b/frontend/src/Context.js @@ -1,15 +1,15 @@ import { createContext } from 'react'; const UserContext = createContext({ - IsloggedIn : false, - UserName : "", - LogIn : ()=>{}, - LogOut : ()=>{}, - CheckSession : ()=>{} + IsloggedIn: false, + UserName: "", + LogIn: () => { }, + LogOut: () => { }, + CheckSession: () => { } }); const ArticleContext = createContext({ - Aritcle: {} + Aritcle: {} }); -export {UserContext, ArticleContext} \ No newline at end of file +export { UserContext, ArticleContext } \ No newline at end of file diff --git a/frontend/src/components/Article.js b/frontend/src/components/Article.js index 1c778fd22bc888b6443e9c3ccf5f283e6d11dbc7..bbca44185922a7a70faf4892944e5f4167361fdf 100644 --- a/frontend/src/components/Article.js +++ b/frontend/src/components/Article.js @@ -9,7 +9,7 @@ function Article({ data }) { const { _id, title, content, imageUrls, author, keyword, latitude, longitude, - comments, likes, createdAt} = data; + comments, likes, createdAt } = data; const navigate = useNavigate(); function MoveTo(link) { @@ -26,16 +26,16 @@ function Article({ data }) { ) }); - const date = DateTime.fromISO(createdAt).toFormat('yyyy�� MM�� dd�� HH:mm'); + const date = DateTime.fromISO(createdAt).toFormat('yyyy-MM-dd HH:mm'); return ( <div className="article" onClick={() => { console.log(_id); MoveTo(`/post/${_id}`) }}> + <p>{keyword}</p> <h1>{title}</h1> - <h2>{keyword}</h2> <h3>{author.nickname} {date}</h3> <p>{content}</p> <p>{listItem}</p> - <p>�볤�: {comments.length} // 議곗���: {likes.length}</p> + <p>�볤� {comments.length} | 醫뗭븘�� {likes.length}</p> </div> ); } diff --git a/frontend/src/components/Comment.js b/frontend/src/components/Comment.js index d002ab71881a8fe4f48ecac97f5bd69d209c9514..d945a6853f51765b1499181e70b3a2672c784e3c 100644 --- a/frontend/src/components/Comment.js +++ b/frontend/src/components/Comment.js @@ -1,8 +1,8 @@ import "../css/Article.css" -import React, { useEffect, useState, useContext} from 'react'; +import React, { useEffect, useState, useContext } from 'react'; import cookie from 'react-cookies'; -import {Routes, Route, Link, useNavigate, Navigate, useParams } from 'react-router-dom'; +import { Routes, Route, Link, useNavigate, Navigate, useParams } from 'react-router-dom'; import { UserContext, ArticleContext } from '../Context.js'; @@ -10,26 +10,25 @@ import { DateTime } from 'luxon'; import axios from 'axios'; axios.defaults.withCredentials = true; -function Comments({data}) { +function Comments({ data }) { const { - _id, content, author, createdAt} = data; + _id, content, author, createdAt } = data; let params = useParams(); const navigate = useNavigate(); - function MoveTo(link){ + function MoveTo(link) { navigate(link) - } + } const articleContext = useContext(ArticleContext); const userinfo = cookie.load('name') - const date = DateTime.fromISO(createdAt).toFormat('yyyy�� MM�� dd�� HH:mm'); + const date = DateTime.fromISO(createdAt).toFormat('yyyy-MM-dd HH:mm'); function DeleteComment(e) { - const data = {id: _id} + const data = { id: _id } axios .delete(`http://localhost:8080/article/${params.id}/comment/${_id}`, data, { - headers: {"Content-Type": 'application/json'} + headers: { "Content-Type": 'application/json' } }) .then(res => { - alert("The comment is successfully deleted"); return articleContext.requestLoadArticleById(params.id) }) .then(res => { @@ -40,19 +39,19 @@ function Comments({data}) { }); }; - if (userinfo.id===author.email) { + if (userinfo.id === author.google.id) { return ( - <div class="comment" style={{display: 'flex'}}> + <div class="comment" style={{ display: 'flex' }}> <p>{author.nickname}</p> <p>{content}</p> <p>{date}</p> - <button style={{height: '30px'}} onClick={DeleteComment} type="submit">吏��곌린</button> + <button style={{ width: '30px', height: '30px' }} onClick={DeleteComment} type="submit">X</button> </div> ); } else { return ( - <div class="comment" style={{display: 'flex'}}> + <div class="comment" style={{ display: 'flex' }}> <p>{author.nickname}</p> <p>{content}</p> <p>{date}</p> diff --git a/frontend/src/components/GoogleLoginButton.js b/frontend/src/components/GoogleLoginButton.js index dc33d9d266094924f6fd4e3eda66924cf3756812..0a8be540e0113e3c4a7e2448c83e52b875689e4b 100644 --- a/frontend/src/components/GoogleLoginButton.js +++ b/frontend/src/components/GoogleLoginButton.js @@ -2,7 +2,7 @@ import { GoogleLogin } from "@react-oauth/google"; import { GoogleOAuthProvider } from "@react-oauth/google"; import { useNavigate, Navigate } from "react-router-dom"; import { useCookies } from 'react-cookie' -import React, { useEffect, useState, useContext} from 'react'; +import React, { useEffect, useState, useContext } from 'react'; import { UserContext } from '../Context.js'; // �덉뜥�� �먮룞�쇰줈 �쒓뎅 �쒓컙�� 遺덈윭�⑤떎. 紐낇솗�섍쾶 �섍린 �꾪빐 import @@ -15,37 +15,37 @@ import axios from 'axios'; axios.defaults.withCredentials = true; const GoogleLoginButton = () => { - + const userContext = useContext(UserContext); const [cookies, setCookie, removeCookie] = useCookies(); const clientId = '716858812522-rb0pfisq317unkh4so5hvbu16p19kqp8.apps.googleusercontent.com' const navigate = useNavigate(); - + const goMain = () => { navigate("/"); } return ( - <GoogleOAuthProvider clientId={clientId}> - <GoogleLogin - onSuccess={(res) => { - let datas = res.credential.split('.') - const obj = JSON.parse(b64DecodeUnicode(datas[1])); - - requestLogin(obj).then( - (response) => { - console.log(response); - userContext.LogIn(response.data); - goMain(); - } - ) - }} - onFailure={(err) => { - console.log("Login Failed"); - console.log(err); - }} - /> - </GoogleOAuthProvider> + <GoogleOAuthProvider clientId={clientId}> + <GoogleLogin + onSuccess={(res) => { + let datas = res.credential.split('.') + const obj = JSON.parse(b64DecodeUnicode(datas[1])); + + requestLogin(obj).then( + (response) => { + console.log(response); + userContext.LogIn(response.data); + goMain(); + } + ) + }} + onFailure={(err) => { + console.log("Login Failed"); + console.log(err); + }} + /> + </GoogleOAuthProvider> ); }; diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js index 72a20ef588e94d6d1ce5cd10e7163c377bbac6a4..ef0252f8f8bdcd6c0250596f41e0a5d41365010e 100644 --- a/frontend/src/components/Header.js +++ b/frontend/src/components/Header.js @@ -3,64 +3,64 @@ import '../css/Header.css'; import { UserContext } from '../Context.js'; -import React, { useEffect, useState, useContext} from 'react'; +import React, { useEffect, useState, useContext } from 'react'; import { Link, useNavigate, Navigate } from "react-router-dom"; -function ButtonLink({link, status, children}){ +function ButtonLink({ link, status, children }) { - const userContext = useContext(UserContext); - const navigate = useNavigate(); - function MoveTo(link){ - navigate(link) - } - - if (status) { - return ( - <div> - <label className='Labelheader' htmlFor={children}>{children}</label> - <button id={children} onClick = {()=>{userContext.LogOut()}} style={{ display: "none"}}> - {children} - </button> - </div> + const userContext = useContext(UserContext); + const navigate = useNavigate(); + function MoveTo(link) { + navigate(link) + } - ) - } - else { - return ( - <div> - <label className='Labelheader' htmlFor={children}>{children}</label> - <button id={children} onClick = {()=>{MoveTo(link)}} style={{ display: "none"}}> - {children} - </button> - </div> - ) - } + if (status) { + return ( + <div> + <label className='Labelheader' htmlFor={children}>{children}</label> + <button id={children} onClick={() => { userContext.LogOut() }} style={{ display: "none" }}> + {children} + </button> + </div> + + ) + } + else { + return ( + <div> + <label className='Labelheader' htmlFor={children}>{children}</label> + <button id={children} onClick={() => { MoveTo(link) }} style={{ display: "none" }}> + {children} + </button> + </div> + ) + } } -function Header({cookie}){ +function Header({ cookie }) { - return( - <div className="header"> - <ButtonLink link='/'> - <img className="logo_image" alt="logo" src={logo}/> - </ButtonLink> - <ul> - <p>{cookie?`${cookie.name}��, �섏쁺�⑸땲��`:'濡쒓렇�명븯�몄슂.'}</p> - <ul className="menu_list"> - <li><ButtonLink link='/'>Home</ButtonLink></li> - <li><ButtonLink link='/search'>寃���</ButtonLink></li> - <li><ButtonLink link='/postwrite'>�ъ뒪�� �묒꽦</ButtonLink></li> - <li><ButtonLink link={cookie?'/':'/login'} status={cookie?true:false}>{cookie?'濡쒓렇�꾩썐':'濡쒓렇��'}</ButtonLink></li> {/*濡쒓렇�� �щ� 濡쒖쭅 援ы쁽 �꾩슂*/} - {/* { Object.keys(user).length != 0 ? + return ( + <div className="header"> + <ButtonLink link='/'> + <img className="logo_image" alt="logo" src={logo} /> + </ButtonLink> + <ul> + <p>{cookie ? `${cookie.name}��, �섏쁺�⑸땲��` : '濡쒓렇�명븯�몄슂.'}</p> + <ul className="menu_list"> + <li><ButtonLink link='/'>Home</ButtonLink></li> + <li><ButtonLink link='/search'>寃���</ButtonLink></li> + <li><ButtonLink link='/postwrite'>�ъ뒪�� �묒꽦</ButtonLink></li> + <li><ButtonLink link={cookie ? '/' : '/login'} status={cookie ? true : false}>{cookie ? '濡쒓렇�꾩썐' : '濡쒓렇��'}</ButtonLink></li> {/*濡쒓렇�� �щ� 濡쒖쭅 援ы쁽 �꾩슂*/} + {/* { Object.keys(user).length != 0 ? <li><Link to={`/profile/${getUserId()}`}>profile</Link>/<span onClick={logout}>logout</span></li> : <li><Link to="/login">login</Link></li> } */} - </ul> - </ul> - </div> - ); + </ul> + </ul> + </div> + ); } diff --git a/frontend/src/components/MapForLoaction.js b/frontend/src/components/MapForLoaction.js index 72fce449dcd1ccfbc31b1b0088307a3ebd023be7..dcaff54189d5d424e11c6edcafa9b8a5066e09c1 100644 --- a/frontend/src/components/MapForLoaction.js +++ b/frontend/src/components/MapForLoaction.js @@ -15,20 +15,20 @@ function MapLocator({ loc, keyword }) { return ( <div className="UserInput"> - <div style={{display: 'flex'}}> + <div style={{ display: 'flex' }}> <Map // 吏��꾨� �쒖떆�� Container center={defaultCenter} style={{ // 吏��꾩쓽 �ш린 - width: "300px", + width: "450px", height: "450px" }} onCreate={setMap} isPanto={true} level={3}> - <MapMarker position={defaultCenter}> - <div style={{color:"#000"}}>{keyword}</div> - </MapMarker> + <MapMarker position={defaultCenter}> + <div style={{ color: "#000" }}>{keyword}</div> + </MapMarker> </Map> </div> </div> diff --git a/frontend/src/components/SearchMapByKeyword.js b/frontend/src/components/SearchMapByKeyword.js index 4ba431cd29203caea09ba43446ea82381597c636..f1f8883246b3e5cdf7fecdaac2b3f7ce2d5ff275 100644 --- a/frontend/src/components/SearchMapByKeyword.js +++ b/frontend/src/components/SearchMapByKeyword.js @@ -4,13 +4,13 @@ import React, { useRef, useState, useEffect, useContext } from 'react'; const { kakao } = window; function SearchMapByKeyword({ loc, setLoc }) { - // �꾩<���숆탳瑜� 湲곕낯 �꾩튂濡� �ㅼ젙 const [info, setInfo] = useState() const [markers, setMarkers] = useState([]) const [pagination, setPagination] = useState() const [map, setMap] = useState() - const [searchKeyword, setSearchKeyword] = useState(); //二쇱냼 �낅젰 + const [searchKeyword, setSearchKeyword] = useState(); + // �꾩<���숆탳瑜� 湲곕낯 �꾩튂濡� �ㅼ젙 const defaultCenter = { lat: 37.28238488648025, lng: 127.04350967609274 } const ps = new kakao.maps.services.Places() @@ -21,15 +21,12 @@ function SearchMapByKeyword({ loc, setLoc }) { const handleSearch = () => { ps.keywordSearch(searchKeyword, (data, status, _pagination) => { if (status === kakao.maps.services.Status.OK) { - // 寃��됰맂 �μ냼 �꾩튂瑜� 湲곗��쇰줈 吏��� 踰붿쐞瑜� �ъ꽕�뺥븯湲곗쐞�� - // LatLngBounds 媛앹껜�� 醫뚰몴瑜� 異붽��⑸땲�� const bounds = new kakao.maps.LatLngBounds() let markers = [] setPagination(_pagination); for (var i = 0; i < data.length; i++) { - // @ts-ignore markers.push({ position: { lat: data[i].y, @@ -37,14 +34,12 @@ function SearchMapByKeyword({ loc, setLoc }) { }, content: data[i].place_name, }) - // @ts-ignore bounds.extend(new kakao.maps.LatLng(data[i].y, data[i].x)) } - setMarkers(markers) + setMarkers(markers); - // 寃��됰맂 �μ냼 �꾩튂瑜� 湲곗��쇰줈 吏��� 踰붿쐞瑜� �ъ꽕�뺥빀�덈떎 - map.setBounds(bounds) + map.setBounds(bounds); } }, { category_group_code: 'FD6' }) } @@ -53,8 +48,8 @@ function SearchMapByKeyword({ loc, setLoc }) { const links = []; for (let i = 1; i <= pagination.last; i++) { links.push(<a href="#" key={i} - style={{ textDecoration: "none", color: "black" }} - onClick={() => pagination.gotoPage(i)}>{i}</a>); + style={{ textDecoration: "none", color: "black" }} + onClick={() => pagination.gotoPage(i)}>{i}</a>); } return links; @@ -63,10 +58,7 @@ function SearchMapByKeyword({ loc, setLoc }) { return ( <div className="UserInput"> <input onChange={handleInput} /> - <button onClick={() => handleSearch()}>寃���</button><br></br> - {/* <input readOnly={true} type="text" placeholder="�μ냼 �ㅼ썙��" value={loc.keyword} /> - <input readOnly={true} type="text" placeholder="�꾨룄" value={loc.center.lat} /> - <input readOnly={true} type="text" placeholder="寃쎈룄" value={loc.center.lng} /> */} + <button onClick={() => handleSearch()} style={{ width: '50px' }}>寃���</button><br></br> <div style={{ display: 'flex' }}> <Map // 吏��꾨� �쒖떆�� Container center={info && info.position || defaultCenter} @@ -82,15 +74,11 @@ function SearchMapByKeyword({ loc, setLoc }) { <MapMarker key={`marker-${marker.content}-${marker.position.lat},${marker.position.lng}`} position={marker.position} - clickable={true} // 留덉빱瑜� �대┃�덉쓣 �� 吏��꾩쓽 �대┃ �대깽�멸� 諛쒖깮�섏� �딅룄濡� �ㅼ젙�⑸땲�� - // 留덉빱�� 留덉슦�ㅼ삤踰� �대깽�몃� �깅줉�⑸땲�� + clickable={true} onMouseOver={ - // 留덉빱�� 留덉슦�ㅼ삤踰� �대깽�멸� 諛쒖깮�섎㈃ �명룷�덈룄�곕� 留덉빱�꾩뿉 �쒖떆�⑸땲�� () => setInfo(marker) } - // 留덉빱�� 留덉슦�ㅼ븘�� �대깽�몃� �깅줉�⑸땲�� onMouseOut={ - // 留덉빱�� 留덉슦�ㅼ븘�� �대깽�멸� 諛쒖깮�섎㈃ �명룷�덈룄�곕� �쒓굅�⑸땲�� () => setInfo({ position: marker.position }) } onClick={() => { diff --git a/frontend/src/css/Article.css b/frontend/src/css/Article.css index d68f5eab74fb6a72bd6cb0884a6c631eb73e7733..29b8edafd5e5be848f4123d64733c3256e1caada 100644 --- a/frontend/src/css/Article.css +++ b/frontend/src/css/Article.css @@ -1,8 +1,9 @@ .article { - background-color: #ffffff; - border: 2px solid gray; + background-color: #ffffff; + border: 1px solid gray; + border-radius: 10px; } .article:hover { - background-color: #dddddd; - } \ No newline at end of file + background-color: #dddddd; +} \ No newline at end of file diff --git a/frontend/src/index.js b/frontend/src/index.js index 58c38f05c2cb8dc1d0d5815063d21e82bfc452da..a97e148ffb005895fce34b1bc72c245239c900fd 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -6,9 +6,9 @@ import App from "./App"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( -// <React.StrictMode> - <BrowserRouter> - <App/> - </BrowserRouter> -// </React.StrictMode> + // <React.StrictMode> + <BrowserRouter> + <App /> + </BrowserRouter> + // </React.StrictMode> ); diff --git a/frontend/src/pages/Login.js b/frontend/src/pages/Login.js index b21550ea33e49e1e155092ff1ffe8bc6b3e26fab..fbce60e458f49890499a70d7d8b276f19147c967 100644 --- a/frontend/src/pages/Login.js +++ b/frontend/src/pages/Login.js @@ -3,10 +3,10 @@ import GoogleLoginButton from "../components/GoogleLoginButton.js"; import React, { useState, useEffect, useContext } from 'react'; import { UserContext } from '../Context.js'; -function Button({history, children}){ +function Button({ history, children }) { const navigate = useNavigate(); - return( - <button onClick={() => {navigate('/search');}}> + return ( + <button onClick={() => { navigate('/search'); }}> {children} </button> ); @@ -16,16 +16,11 @@ function Login() { const userContext = useContext(UserContext); - useEffect(() => { - // console.log(userContext) - }); - - return( + return ( <div className="App"> - <h1>濡쒓렇�� '�댁쨾'</h1> - <GoogleLoginButton></GoogleLoginButton> - </div>) - ; + <h1>濡쒓렇��</h1> + <GoogleLoginButton></GoogleLoginButton> + </div>); } export default Login; \ No newline at end of file diff --git a/frontend/src/pages/Main.js b/frontend/src/pages/Main.js index 56f4967ff4e28aa9138941a660489040726b50fe..eb52783db7e0cc4a0c1d245c5aa87a857643e8cb 100644 --- a/frontend/src/pages/Main.js +++ b/frontend/src/pages/Main.js @@ -2,84 +2,81 @@ import { useNavigate } from 'react-router-dom'; import { UserContext } from '../Context.js'; import Article from '../components/Article.js'; -import React, { useEffect, useState, useContext} from 'react'; +import React, { useEffect, useState, useContext } from 'react'; import axios from 'axios'; axios.defaults.withCredentials = true; -function Button({history, children}){ - const navigate = useNavigate(); - return( - <button onClick={() => {navigate('/search');}}> - {children} - </button> - ); +function Button({ history, children }) { + const navigate = useNavigate(); + return ( + <button style={{ width: '40px', height: '30px' }} onClick={() => { navigate('/search'); }}> + {children} + </button> + ); } function Main() { const userContext = useContext(UserContext); - const [articleList, setArticleList] = useState([]) + const [articleList, setArticleList] = useState([]); let listItem = []; - listItem = articleList.map((article)=>{ - return( - <Article - key={article._id} - data={article} - ></Article> + listItem = articleList.map((article) => { + return ( + <Article + key={article._id} + data={article} + ></Article> ) } ) useEffect(() => { - requestLoadArticle() - .then((response) => { - console.log(response) - setArticleList(response.data) - }) + requestSortArticle("time") + .then((response) => { + console.log(response) + setArticleList(response.data) + }) }, []); const handleSortChange = (event) => { - console.log(event.target.value) requestSortArticle(event.target.value) - .then((response) => { - console.log(response) - setArticleList(response.data) - }) - }; + .then((response) => { + console.log(response) + setArticleList(response.data) + }) + }; - return( + return ( <div className="App"> - <h1>硫붿씤 �섏씠吏� �낅땲��.</h1> - <div className="introduction"> - �뚭컻 �댁슜�� �댁쓣 怨듦컙 - </div> - <div style={{display: 'flex'}}> - <Button>寃���</Button> - <select id="addInputPrior" onChange={handleSortChange}> - <option value="time">理쒖떊��</option> - <option value="like">�멸린��</option> - </select> - </div> + <h1>紐⑤몢�� 繇잓걪與�</h1> + <div className="introduction"> + 媛�蹂닿퀬 �띠� �앸떦�� 李얠븘蹂닿퀬, 媛�蹂� �앸떦�� 湲곕줉�대낫�몄슂! + </div> + <div style={{ display: 'flex' }}> + <select id="addInputPrior" defaultValue={"time"} onChange={handleSortChange}> + <option value="time">理쒖떊��</option> + <option value="like">�멸린��</option> + </select> + </div> - {listItem} - </div>) - ; + {listItem} + </div>); } async function requestLoadArticle() { - const response = await axios({ - url: 'http://localhost:8080/article', // �듭떊�� �밸Ц�� - method: 'get', // �듭떊�� 諛⑹떇 - }); - return response; - } + 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}`, // �듭떊�� �밸Ц�� - method: 'get', // �듭떊�� 諛⑹떇 - }); - 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/PostRead.js b/frontend/src/pages/PostRead.js index af80f9e8d85f5e74b9b5ae753d2ccc4960112705..c8a34bbb3bb840e66f63a0541dce19acd59bef74 100644 --- a/frontend/src/pages/PostRead.js +++ b/frontend/src/pages/PostRead.js @@ -1,5 +1,5 @@ import { useNavigate, useParams } from 'react-router-dom'; -import React, { useEffect, useState, useContext} from 'react'; +import React, { useEffect, useState, useContext } from 'react'; import Article from '../components/Article.js'; import { UserContext, ArticleContext } from '../Context.js'; import MapLocator from '../components/MapForLoaction.js'; @@ -18,48 +18,47 @@ function PostRead() { const [inputComment, setInputComment] = useState("") const [commentList, setCommentList] = useState("") const navigate = useNavigate(); - function MoveTo(link){ + function MoveTo(link) { navigate(link) - } + } useEffect(() => { + console.log(userinfo); userContext.CheckSession() - .then((response) => { - if (!response.data) { - alert("�몄뀡�� 留뚮즺�섏뿀�듬땲��. �ㅼ떆 濡쒓렇�� 諛붾엻�덈떎.") - MoveTo('/login') - } - else{ - return requestLoadArticleById(params.id) - } - }) - .then((response) => { - console.log(response) - setArticle(response.data) - - }) - .catch((response)=>{ - console.log("error!:LogOut") - console.log(response) - }) + .then((response) => { + if (!response.data) { + alert("濡쒓렇�� 諛붾엻�덈떎."); + MoveTo('/login'); + } + else { + return requestLoadArticleById(params.id) + } + }) + .then((response) => { + console.log(response) + setArticle(response.data) + }) + .catch((response) => { + console.log("error!:LogOut") + console.log(response) + }) - }, []); + }, []); - function SetLike(){ + function SetLike() { axios.put(`http://localhost:8080/article/${params.id}/like`) - .then(res => { - alert("The comment is successfully uploaded"); - return requestLoadArticleById(params.id) - }) - .then(res => { - setArticle(res.data) - }) - .catch(err => { - console.error(err); - }); + .then(res => { + return requestLoadArticleById(params.id) + }) + .then(res => { + setArticle(res.data) + }) + .catch(err => { + console.error(err); + }); } const onTextChange = (e) => { - const {value} = e.target; + const { value } = e.target; setInputComment(value); } @@ -69,79 +68,77 @@ function PostRead() { alert("�볤��� �묒꽦�댁<�몄슂."); return } - const data = {content: inputComment} + const data = { content: inputComment } axios.post(`http://localhost:8080/article/${params.id}/comment`, data, - { - headers: {"Content-Type": 'application/json'} - }) - .then(res => { - alert("The comment is successfully uploaded"); - return requestLoadArticleById(params.id) - }) - .then(res => { - setArticle(res.data) - }) - .catch(err => { - console.error(err); - }); + { + headers: { "Content-Type": 'application/json' } + }) + .then(res => { + return requestLoadArticleById(params.id) + }) + .then(res => { + setArticle(res.data) + }) + .catch(err => { + console.error(err); + }); }; - function DelButton({isThatYou, target}){ - function deleteArticle(){ + function DelButton({ isThatYou, target }) { + function deleteArticle() { console.log(target._id) requestDeleteArticleById(target._id).then(res => { - alert("The article is successfully deleted"); + alert("寃뚯떆湲��� ��젣�섏뿀�듬땲��"); MoveTo('/') }) - .catch(err => { - console.error(err); - }); + .catch(err => { + console.error(err); + }); } - + if (isThatYou) { - return(<button onClick={deleteArticle}>吏��곌린</button>) + return (<button onClick={deleteArticle}>吏��곌린</button>) } else { return null } - + } if (article) { - return( + return ( <> - <div className="introduction" style={{display: 'flex'}}> - <MapLocator loc={{lat: article.latitude, lng: article.longitude}} keyword={article.keyword}></MapLocator> + <div className="introduction" style={{ display: 'flex' }}> + <MapLocator loc={{ lat: article.latitude, lng: article.longitude }} keyword={article.keyword}></MapLocator> <div> <Article data={article}></Article> - <div style={{display: 'flex'}}> - <button onClick={SetLike}>議곗���</button> - <DelButton isThatYou={userinfo.id === article.author.user_id} target={article}></DelButton> + <div style={{ display: 'flex' }}> + <button onClick={SetLike}>醫뗭븘��</button> + <DelButton isThatYou={userinfo.id === article.author.google.id} target={article}></DelButton> </div> - + <ArticleContext.Provider value={{ requestLoadArticleById, setArticle }}> + { + article.comments.map((el) => { + return ( + <Comment key={el._id} data={el}></Comment> + ) + }) + } + </ArticleContext.Provider> </div> </div> <form onSubmit={onSubmit}> - <div style={{display: 'flex'}}> + <div style={{ display: 'flex' }}> <button>�볤� �묒꽦</button> <input type="text" onChange={onTextChange}></input> </div> - </form> - <ArticleContext.Provider value={{requestLoadArticleById, setArticle}}> - { - article.comments.map((el)=>{ - return( - <Comment key={el._id} data={el}></Comment> - ) - }) - } - </ArticleContext.Provider> + </form> </> - ) + ) } else { - return( - <div className="introduction" style={{display: 'flex'}}> - <p>濡쒕뵫以�</p> + return ( + <div className="introduction" style={{ display: 'flex' }}> + <p>濡쒕뵫以묒엯�덈떎...</p> </div> ) } diff --git a/frontend/src/pages/PostWrite.js b/frontend/src/pages/PostWrite.js index 3016ca9dc6ea6dc7b867fa5c71490d2aa08d9ee1..4881cd140272fa961b97f8e1c99473800766fb04 100644 --- a/frontend/src/pages/PostWrite.js +++ b/frontend/src/pages/PostWrite.js @@ -6,178 +6,171 @@ import SearchMap from '../components/SearchMapByKeyword.js' import axios from 'axios'; axios.defaults.withCredentials = true; -function PostWrite(){ - - const [location, setLocation] = useState({ - keyword: "", - center: { lat: null, lng: null } - }); - const navigate = useNavigate(); - function MoveTo(link){ - navigate(link) - } - const userContext = useContext(UserContext); - useEffect(() => { - userContext.CheckSession() - .then((response) => { - if (!response.data) { - alert("�몄뀡�� 留뚮즺�섏뿀�듬땲��. �ㅼ떆 濡쒓렇�� 諛붾엻�덈떎.") - MoveTo('/login') - } - }) - .catch((response)=>{ - console.log("error!:LogOut") - console.log(response) - }) - }); - - const [previewImg, setPreviewImg] = useState({ - imageUrls: [], - }); - - const [content, setContent] = useState(""); - const [inputs, setInputs] = useState({ - title: "", - content: "", - }); - - - - const onTextChange = (e) => { - const {value, name} = e.target; - setInputs({ - ...inputs, - [name]: value - }); - } - - const onImgChange = e => { - let temp = [] - for (let i=0; i< e.target.files.length; i++) { - temp.push(e.target.files[i]) +function PostWrite() { + + const [location, setLocation] = useState({ + keyword: "", + center: { lat: null, lng: null } + }); + const navigate = useNavigate(); + function MoveTo(link) { + navigate(link) + } + const userContext = useContext(UserContext); + useEffect(() => { + userContext.CheckSession() + .then((response) => { + if (!response.data) { + alert("濡쒓렇�� 諛붾엻�덈떎."); + MoveTo('/login'); } - - setContent(e.target.files); - - Array.from(e.target.files).forEach((file) => { - const reader = new FileReader(); - console.log(file) - reader.readAsDataURL(file); - reader.onloadend = () => { - previewImg.imageUrls.push(reader.result); - setPreviewImg({ - imageUrls: previewImg.imageUrls - }); - }; + }) + .catch((response) => { + console.log("error!:LogOut") + console.log(response) + }) + }); + + const [previewImg, setPreviewImg] = useState({ + imageUrls: [], + }); + + const [content, setContent] = useState(""); + const [inputs, setInputs] = useState({ + title: "", + content: "", + }); + + + + const onTextChange = (e) => { + const { value, name } = e.target; + setInputs({ + ...inputs, + [name]: value + }); + } + + const onImgChange = e => { + let temp = [] + for (let i = 0; i < e.target.files.length; i++) { + temp.push(e.target.files[i]) + } + + setContent(e.target.files); + + Array.from(e.target.files).forEach((file) => { + const reader = new FileReader(); + console.log(file) + reader.readAsDataURL(file); + reader.onloadend = () => { + previewImg.imageUrls.push(reader.result); + setPreviewImg({ + imageUrls: previewImg.imageUrls }); }; + }); + }; + + let imglist = []; + imglist = previewImg.imageUrls.map((image) => { + return ( + <img + src={image ? image : null} + alt="�대�吏�" + style={{ width: "100px", height: "100px" }} + /> + ) + } + ); - let imglist = []; - imglist = previewImg.imageUrls.map((image)=>{ - return( - <img - src={image ? image :null} - alt="�대�吏�" - style={{ width: "100px", height: "100px"}} - /> - ) - } - ); - - const onSubmit = e => { - - e.preventDefault(); - - if (!location.keyword) { - alert("�꾩튂瑜� �뚮젮二쇱꽭��."); - return - } + const onSubmit = e => { - if (!inputs.title) { - alert("�쒕ぉ�� �낅젰�댁<�몄슂."); - return - } + e.preventDefault(); - if (!inputs.content) { - alert("�댁슜�� �낅젰�댁<�몄슂."); - return - } + if (!location.keyword) { + alert("�꾩튂瑜� �낅젰�댁<�몄슂."); + return; + } - const formData = new FormData(); - Array.from(content).forEach((el) => { - formData.append("img", el); - }); - formData.append("title", inputs.title); - formData.append("content", inputs.content); - formData.append("keyword", location.keyword); - formData.append("latitude", location.center.lat); - formData.append("longitude", location.center.lng); - axios - .post("http://localhost:8080/article", formData, - { - headers: {"Content-Type": "multipart/form-data"} - }) - .then(res => { - alert("The file is successfully uploaded"); - MoveTo('/') - }) - .catch(err => { - console.error(err); - }); - }; + if (!inputs.title) { + alert("�쒕ぉ�� �낅젰�댁<�몄슂."); + return; + } - // <input readOnly={true} type="text" placeholder="�μ냼 �ㅼ썙��" value={location.keyword} /> - // <input readOnly={true} type="text" placeholder="�꾨룄" value={location.center.lat} /> - // <input readOnly={true} type="text" placeholder="寃쎈룄" value={location.center.lng} /> + if (!inputs.content) { + alert("�댁슜�� �낅젰�댁<�몄슂."); + return; + } - return( + const formData = new FormData(); + Array.from(content).forEach((el) => { + formData.append("img", el); + }); + formData.append("title", inputs.title); + formData.append("content", inputs.content); + formData.append("keyword", location.keyword); + formData.append("latitude", location.center.lat); + formData.append("longitude", location.center.lng); + axios + .post("http://localhost:8080/article", formData, + { + headers: { "Content-Type": "multipart/form-data" } + }) + .then(res => { + MoveTo('/') + }) + .catch(err => { + console.error(err); + }); + }; + return ( <> - <section style={{display: "flex"}}> + <section style={{ display: "flex" }}> <div> - <SearchMap loc={location} setLoc={setLocation}></SearchMap> + <SearchMap loc={location} setLoc={setLocation}></SearchMap> </div> <div> - <form onSubmit={onSubmit}> - <div style={{display: "flex"}}> - <input readOnly={true} type="text" placeholder="�μ냼 �ㅼ썙��" value={location.keyword} /> - <button type="button" onClick={()=>{ - setLocation({ - keyword: "", - center: { lat: null, lng: null } - })}}>�좏깮 �댁젣</button> - </div> - <div style={{display: "grid"}}> - <label>�쒕ぉ</label> - <input - type="text" - name='title' - onChange={onTextChange} - /> - </div> - <div style={{display: "grid"}}> - <label>Content</label> - <input - type="text" - name='content' - onChange={onTextChange} - /> - </div> - <div style={{display: "grid"}}> - <div style={{display: "flex"}}> - {imglist} - </div> - <label htmlFor="profileImg">�대�吏� �낅줈��</label> - <input style={{ display: "none"}} id="profileImg" type="file" onChange={onImgChange} multiple/> - </div> - <button type="submit">�ъ뒪��!</button> - - </form> - </div> - - </section> - </> - ) + <form onSubmit={onSubmit}> + <div style={{ display: "flex" }}> + <input readOnly={true} type="text" placeholder="�μ냼 �ㅼ썙��" value={location.keyword} /> + <button type="button" onClick={() => { + setLocation({ + keyword: "", + center: { lat: null, lng: null } + }) + }}>�좏깮 �댁젣</button> + </div> + <div style={{ display: "grid" }}> + <label>�쒕ぉ</label> + <input + type="text" + name='title' + onChange={onTextChange} + /> + </div> + <div style={{ display: "grid" }}> + <label>Content</label> + <input + type="text" + name='content' + onChange={onTextChange} + /> + </div> + <div style={{ display: "grid" }}> + <div style={{ display: "flex" }}> + {imglist} + </div> + <label htmlFor="profileImg">�대�吏� �낅줈��</label> + <input style={{ display: "none" }} id="profileImg" type="file" onChange={onImgChange} multiple /> + </div> + <button type="submit">�ъ뒪��!</button> + </form> + </div> + </section> + </> + ) } /* diff --git a/frontend/src/pages/Search.js b/frontend/src/pages/Search.js index 5f01b8213624c0cac1c06d0befe20e0d585e0742..bdbd18a0f27c41b038ecbd2d3c85ac0460c7a832 100644 --- a/frontend/src/pages/Search.js +++ b/frontend/src/pages/Search.js @@ -1,113 +1,112 @@ import { Map, MapMarker } from "react-kakao-maps-sdk"; import React, { useState, useEffect, useContext } from 'react'; -import {Routes, Route, Link, useNavigate, Navigate } from 'react-router-dom'; +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; +const { kakao } = window; function Search(props) { - const [articleList, setArticleList] = useState([]) - const userContext = useContext(UserContext); - const navigate = useNavigate(); - function MoveTo(link){ - navigate(link) - } - - const [location, setLocation] = useState({ - keyword: "", - center: { lat: null, lng: null } - }); + const [articleList, setArticleList] = useState([]) + const userContext = useContext(UserContext); + const navigate = useNavigate(); + function MoveTo(link) { + navigate(link) + } - useEffect(() => { - const session = userContext.CheckSession() - .then((response) => { - 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) - }) - }, []); + const [location, setLocation] = useState({ + keyword: "", + center: { lat: null, lng: null } + }); - let listItem = []; - listItem = articleList.map((article)=>{ - return( - <Article - key={article._id} - data={article} - ></Article> - ) + useEffect(() => { + const session = userContext.CheckSession() + .then((response) => { + 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) }) + }, []); - const onSubmit = e => { - e.preventDefault(); - if (!location.keyword){ - alert("寃��됰��곸쓣吏��뺥빐二쇱꽭��"); - return - } - requestLoadArticleByKeyword(location.keyword) - .then((response) => { - console.log(response) - setArticleList(response.data) - }) - }; + useEffect(() => { + if (!location.keyword) { + return; + } + requestLoadArticleByKeyword(location.keyword) + .then((response) => { + console.log(response); + setArticleList(response.data); + }); + }, [location.keyword]); + + 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> - <p>臾댁뾿�� �쒖떆怨� �띕굹��? �대뵒 怨꾩떆二�?</p> - <SearchMap loc={location} setLoc={setLocation}></SearchMap> + return ( + <div style={{ display: 'flex' }}> + <div className="search"> + <h1 style={{ textAlign: 'center' }}>寃���</h1> + <SearchMap loc={location} setLoc={setLocation}></SearchMap> + </div> - </div> + <div className="searchresult"> + <h3>{(articleList.length === 0 ? '寃��됯껐怨� �놁쓬' : (`寃��됯껐怨� ${listItem.length} 媛� �뺤씤`))}</h3> + {listItem} + </div> + </div> - <div className="searchresult"> - <p>�좏깮�� �ㅼ썙�쒕줈 寃��됲빀�덈떎.</p> - <form onSubmit={onSubmit} style={{display: 'flex'}}> - <input readonly value={location.keyword} type="text"></input> - <button type="submit">寃���!</button> - <button type="button" onClick={()=>{ - setLocation({ - keyword: "", - center: { lat: null, lng: null } - })}}>�좏깮 �댁젣</button> - </form> - <h1>寃��됯껐怨� {listItem.length} 媛� �뺤씤</h1> - {listItem} - </div> - </div> - - ); + ); } async function requestLoadArticle() { - const response = await axios({ - url: 'http://localhost:8080/article', // �듭떊�� �밸Ц�� - method: 'get', // �듭떊�� 諛⑹떇 - }); - return response; - } + 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; + const response = await axios({ + url: `http://localhost:8080/article/search/${keyword}`, // �듭떊�� �밸Ц�� + method: 'get', // �듭떊�� 諛⑹떇 + }); + return response; } export default Search; \ No newline at end of file