Commit 1bd65831 authored by baesangjune's avatar baesangjune
Browse files

Merge remote-tracking branch 'origin/cherry' into BAE

parents 1b46e125 e08aede8
[{"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\index.js":"1","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\reportWebVitals.js":"2","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Place.js":"3","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Paginations.js":"4","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\Search.js":"5","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\App.js":"6"},{"size":939,"mtime":1611497444385,"results":"7","hashOfConfig":"8"},{"size":375,"mtime":1611254909401,"results":"9","hashOfConfig":"8"},{"size":1624,"mtime":1611724576486,"results":"10","hashOfConfig":"8"},{"size":3724,"mtime":1611712847775,"results":"11","hashOfConfig":"8"},{"size":7880,"mtime":1611732726663,"results":"12","hashOfConfig":"8"},{"size":4190,"mtime":1611732347337,"results":"13","hashOfConfig":"8"},{"filePath":"14","messages":"15","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"16"},"13y9yvi",{"filePath":"17","messages":"18","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"19","messages":"20","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"21"},{"filePath":"22","messages":"23","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"24","messages":"25","errorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"26","messages":"27","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\index.js",["28"],"import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport './index.css';\r\nimport 'bootstrap/dist/css/bootstrap.min.css';\r\nimport App from './Pages/App';\r\nimport Search from './Pages/Search';\r\nimport axios from 'axios';\r\nimport reportWebVitals from './reportWebVitals';\r\nimport {\r\n BrowserRouter as Router,\r\n Switch,\r\n Route,\r\n Redirect,\r\n} from \"react-router-dom\";\r\n\r\nReactDOM.render(\r\n <React.StrictMode>\r\n <Router>\r\n <Switch>\r\n <Route exact path=\"/\" component={App} />\r\n <Route path=\"/search\" component={Search} />\r\n <Redirect path=\"/search\" to=\"/search\" />\r\n </Switch>\r\n </Router>\r\n </React.StrictMode>,\r\n document.getElementById('root')\r\n);\r\n\r\n// If you want to start measuring performance in your app, pass a function\r\n// to log results (for example: reportWebVitals(console.log))\r\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\r\nreportWebVitals();\r\n","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\reportWebVitals.js",[],"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Place.js",["29","30"],"import axios from 'axios';\r\nimport React, { useEffect, useState } from 'react';\r\nimport { Modal, Container, Row, Button, } from 'react-bootstrap';\r\n\r\nfunction Place(props) {\r\n const [reviews, setReviews] = useState()\r\n const [db, setDb] = useState(false)\r\n const getReview = () => {\r\n axios({ url: `/api/review?keyword=${props.place.name}`, method: 'post', data: { db: db } })\r\n .then(res => {\r\n console.log(\"place res.data\", res.data)\r\n setReviews(res.data)\r\n })\r\n .catch(err => {\r\n console.log(err)\r\n })\r\n }\r\n\r\n useEffect(() => {\r\n getReview();\r\n }, [])\r\n\r\n return (\r\n <Modal {...props}\r\n size=\"xl\"\r\n keyboard=\"true\"\r\n variant=\"backdrop.in\"\r\n aria-labelledby=\"example-modal-sizes-title-lg\">\r\n <Modal.Header closeButton>\r\n <Modal.Title id=\"contained-modal-title-vcenter\" style={{ fontSize: '40px' }}>\r\n {props.place.name}\r\n </Modal.Title>\r\n </Modal.Header>\r\n <Modal.Body className=\"show-grid\">\r\n <Container style={{ fontSize: '40px' }}>\r\n {Array.isArray(reviews) ? reviews.map((review) => {\r\n return (\r\n <Row className=\"mt-4\">\r\n <a href={review.link}>{review.title}</a>\r\n <div>{review.summary}</div>\r\n <div>{review.content}</div>\r\n </Row>\r\n )\r\n })\r\n : \"리뷰가 없습니다.\"}\r\n </Container>\r\n\r\n </Modal.Body>\r\n <Modal.Footer>\r\n <Button block onClick={props.onHide}>Close</Button>\r\n </Modal.Footer>\r\n </Modal>\r\n );\r\n}\r\n\r\nexport default Place;\r\n","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Paginations.js",[],"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\Search.js",["31","32","33","34","35","36"],"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\App.js",[],{"ruleId":"37","severity":1,"message":"38","line":7,"column":8,"nodeType":"39","messageId":"40","endLine":7,"endColumn":13},{"ruleId":"37","severity":1,"message":"41","line":7,"column":14,"nodeType":"39","messageId":"40","endLine":7,"endColumn":19},{"ruleId":"42","severity":1,"message":"43","line":21,"column":6,"nodeType":"44","endLine":21,"endColumn":8,"suggestions":"45"},{"ruleId":"37","severity":1,"message":"46","line":16,"column":12,"nodeType":"39","messageId":"40","endLine":16,"endColumn":18},{"ruleId":"42","severity":1,"message":"47","line":44,"column":8,"nodeType":"44","endLine":44,"endColumn":10,"suggestions":"48"},{"ruleId":"42","severity":1,"message":"49","line":65,"column":8,"nodeType":"44","endLine":65,"endColumn":15,"suggestions":"50"},{"ruleId":"37","severity":1,"message":"51","line":68,"column":11,"nodeType":"39","messageId":"40","endLine":68,"endColumn":17},{"ruleId":"37","severity":1,"message":"52","line":133,"column":9,"nodeType":"39","messageId":"40","endLine":133,"endColumn":13},{"ruleId":"53","severity":1,"message":"54","line":138,"column":35,"nodeType":"55","endLine":138,"endColumn":76},"no-unused-vars","'axios' is defined but never used.","Identifier","unusedVar","'setDb' is assigned a value but never used.","react-hooks/exhaustive-deps","React Hook useEffect has a missing dependency: 'getReview'. Either include it or remove the dependency array.","ArrayExpression",["56"],"'mobile' is assigned a value but never used.","React Hook useEffect has a missing dependency: 'getAssociation'. Either include it or remove the dependency array.",["57"],"React Hook useEffect has missing dependencies: 'getAssociation', 'props.history', and 'search'. Either include them or remove the dependency array.",["58"],"'places' is assigned a value but never used.","'time' is assigned a value but never used.","react/jsx-no-duplicate-props","No duplicate props allowed","JSXAttribute",{"desc":"59","fix":"60"},{"desc":"61","fix":"62"},{"desc":"63","fix":"64"},"Update the dependencies array to be: [getReview]",{"range":"65","text":"66"},"Update the dependencies array to be: [getAssociation]",{"range":"67","text":"68"},"Update the dependencies array to be: [getAssociation, props.history, search, state]",{"range":"69","text":"70"},[605,607],"[getReview]",[1563,1565],"[getAssociation]",[2123,2130],"[getAssociation, props.history, search, state]"]
\ No newline at end of file
[{"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\index.js":"1","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\reportWebVitals.js":"2","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Place.js":"3","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Paginations.js":"4","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\Search.js":"5","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\App.js":"6"},{"size":939,"mtime":1611497444385,"results":"7","hashOfConfig":"8"},{"size":375,"mtime":1611254909401,"results":"9","hashOfConfig":"8"},{"size":1624,"mtime":1611724576486,"results":"10","hashOfConfig":"8"},{"size":3724,"mtime":1611712847775,"results":"11","hashOfConfig":"8"},{"size":7880,"mtime":1611732726663,"results":"12","hashOfConfig":"8"},{"size":4190,"mtime":1611732347337,"results":"13","hashOfConfig":"8"},{"filePath":"14","messages":"15","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"16"},"13y9yvi",{"filePath":"17","messages":"18","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"19","messages":"20","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"21"},{"filePath":"22","messages":"23","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"24","messages":"25","errorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"26","messages":"27","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\index.js",["28"],"import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport './index.css';\r\nimport 'bootstrap/dist/css/bootstrap.min.css';\r\nimport App from './Pages/App';\r\nimport Search from './Pages/Search';\r\nimport axios from 'axios';\r\nimport reportWebVitals from './reportWebVitals';\r\nimport {\r\n BrowserRouter as Router,\r\n Switch,\r\n Route,\r\n Redirect,\r\n} from \"react-router-dom\";\r\n\r\nReactDOM.render(\r\n <React.StrictMode>\r\n <Router>\r\n <Switch>\r\n <Route exact path=\"/\" component={App} />\r\n <Route path=\"/search\" component={Search} />\r\n <Redirect path=\"/search\" to=\"/search\" />\r\n </Switch>\r\n </Router>\r\n </React.StrictMode>,\r\n document.getElementById('root')\r\n);\r\n\r\n// If you want to start measuring performance in your app, pass a function\r\n// to log results (for example: reportWebVitals(console.log))\r\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\r\nreportWebVitals();\r\n","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\reportWebVitals.js",[],"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Place.js",["29","30"],"import axios from 'axios';\r\nimport React, { useEffect, useState } from 'react';\r\nimport { Modal, Container, Row, Button, } from 'react-bootstrap';\r\n\r\nfunction Place(props) {\r\n const [reviews, setReviews] = useState()\r\n const [db, setDb] = useState(false)\r\n const getReview = () => {\r\n axios({ url: `/api/review?keyword=${props.place.name}`, method: 'post', data: { db: db } })\r\n .then(res => {\r\n console.log(\"place res.data\", res.data)\r\n setReviews(res.data)\r\n })\r\n .catch(err => {\r\n console.log(err)\r\n })\r\n }\r\n\r\n useEffect(() => {\r\n getReview();\r\n }, [])\r\n\r\n return (\r\n <Modal {...props}\r\n size=\"xl\"\r\n keyboard=\"true\"\r\n variant=\"backdrop.in\"\r\n aria-labelledby=\"example-modal-sizes-title-lg\">\r\n <Modal.Header closeButton>\r\n <Modal.Title id=\"contained-modal-title-vcenter\" style={{ fontSize: '40px' }}>\r\n {props.place.name}\r\n </Modal.Title>\r\n </Modal.Header>\r\n <Modal.Body className=\"show-grid\">\r\n <Container style={{ fontSize: '40px' }}>\r\n {Array.isArray(reviews) ? reviews.map((review) => {\r\n return (\r\n <Row className=\"mt-4\">\r\n <a href={review.link}>{review.title}</a>\r\n <div>{review.summary}</div>\r\n <div>{review.content}</div>\r\n </Row>\r\n )\r\n })\r\n : \"리뷰가 없습니다.\"}\r\n </Container>\r\n\r\n </Modal.Body>\r\n <Modal.Footer>\r\n <Button block onClick={props.onHide}>Close</Button>\r\n </Modal.Footer>\r\n </Modal>\r\n );\r\n}\r\n\r\nexport default Place;\r\n","C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Components\\Paginations.js",[],"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\Search.js",["31","32","33","34","35","36"],"C:\\Users\\노트북펜\\Desktop\\2021YDK\\search-page\\client\\src\\Pages\\App.js",[],{"ruleId":"37","severity":1,"message":"38","line":7,"column":8,"nodeType":"39","messageId":"40","endLine":7,"endColumn":13},{"ruleId":"37","severity":1,"message":"41","line":7,"column":14,"nodeType":"39","messageId":"40","endLine":7,"endColumn":19},{"ruleId":"42","severity":1,"message":"43","line":21,"column":6,"nodeType":"44","endLine":21,"endColumn":8,"suggestions":"45"},{"ruleId":"37","severity":1,"message":"46","line":16,"column":12,"nodeType":"39","messageId":"40","endLine":16,"endColumn":18},{"ruleId":"42","severity":1,"message":"47","line":44,"column":8,"nodeType":"44","endLine":44,"endColumn":10,"suggestions":"48"},{"ruleId":"42","severity":1,"message":"49","line":65,"column":8,"nodeType":"44","endLine":65,"endColumn":15,"suggestions":"50"},{"ruleId":"37","severity":1,"message":"51","line":68,"column":11,"nodeType":"39","messageId":"40","endLine":68,"endColumn":17},{"ruleId":"37","severity":1,"message":"52","line":133,"column":9,"nodeType":"39","messageId":"40","endLine":133,"endColumn":13},{"ruleId":"53","severity":1,"message":"54","line":138,"column":35,"nodeType":"55","endLine":138,"endColumn":76},"no-unused-vars","'axios' is defined but never used.","Identifier","unusedVar","'setDb' is assigned a value but never used.","react-hooks/exhaustive-deps","React Hook useEffect has a missing dependency: 'getReview'. Either include it or remove the dependency array.","ArrayExpression",["56"],"'mobile' is assigned a value but never used.","React Hook useEffect has a missing dependency: 'getAssociation'. Either include it or remove the dependency array.",["57"],"React Hook useEffect has missing dependencies: 'getAssociation', 'props.history', and 'search'. Either include them or remove the dependency array.",["58"],"'places' is assigned a value but never used.","'time' is assigned a value but never used.","react/jsx-no-duplicate-props","No duplicate props allowed","JSXAttribute",{"desc":"59","fix":"60"},{"desc":"61","fix":"62"},{"desc":"63","fix":"64"},"Update the dependencies array to be: [getReview]",{"range":"65","text":"66"},"Update the dependencies array to be: [getAssociation]",{"range":"67","text":"68"},"Update the dependencies array to be: [getAssociation, props.history, search, state]",{"range":"69","text":"70"},[605,607],"[getReview]",[1563,1565],"[getAssociation]",[2123,2130],"[getAssociation, props.history, search, state]"]
......@@ -6,7 +6,7 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
In the project directory, you can run:
### `yarn start`
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
......@@ -14,12 +14,12 @@ Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.\
You will also see any lint errors in the console.
### `yarn test`
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `yarn build`
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
......@@ -29,7 +29,7 @@ Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `yarn eject`
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
......@@ -65,6 +65,6 @@ This section has moved here: [https://facebook.github.io/create-react-app/docs/a
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `yarn build` fails to minify
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
[0122/091810.668:ERROR:directory_reader_win.cc(43)] FindFirstFile: 지정된 경로를 찾을 수 없습니다. (0x3)
[0125/001732.960:ERROR:directory_reader_win.cc(43)] FindFirstFile: 지정된 경로를 찾을 수 없습니다. (0x3)
[0125/093515.306:ERROR:directory_reader_win.cc(43)] FindFirstFile: 지정된 경로를 찾을 수 없습니다. (0x3)
......@@ -9288,22 +9288,6 @@
"prepend-http": "^1.0.0",
"query-string": "^4.1.0",
"sort-keys": "^1.0.0"
},
"dependencies": {
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"requires": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
}
}
},
"npm-run-path": {
......@@ -11120,13 +11104,12 @@
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"query-string": {
"version": "6.13.8",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.8.tgz",
"integrity": "sha512-jxJzQI2edQPE/NPUOusNjO/ZOGqr1o2OBa/3M00fU76FsLXDVbJDv/p7ng5OdQyorKrkRz1oqfwmbe5MAMePQg==",
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
"requires": {
"decode-uri-component": "^0.2.0",
"split-on-first": "^1.0.0",
"strict-uri-encode": "^2.0.0"
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"querystring": {
......@@ -12955,11 +12938,6 @@
"wbuf": "^1.7.3"
}
},
"split-on-first": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
"integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="
},
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
......@@ -13135,9 +13113,9 @@
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
},
"strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
},
"string-length": {
"version": "4.0.1",
......
......@@ -7,7 +7,6 @@
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"bootstrap": "^4.5.3",
"query-string": "^6.13.8",
"react": "^17.0.1",
"react-bootstrap": "^1.4.0",
"react-dom": "^17.0.1",
......@@ -39,5 +38,5 @@
"last 1 safari version"
]
},
"proxy": "http://localhost:3001"
"proxy":"http://localhost:3001"
}
import React, { useState, useEffect } from 'react'
import { Alert, Col, Card, Container, Form, Row, Button, Nav, Navbar } from "react-bootstrap"
import axios from "axios"
import catchErrors from './utils/catchErrors.js'
import { isAuthenticated } from './utils/auth'
import * as Icon from 'react-bootstrap-icons';
import Place from './Components/Place.js'
const INIT_PAGE = {
bookmark: []
}
function Bookmark() {
const [page, setPage] = useState(INIT_PAGE)
const [index, setIndex] = useState(1);
const [error, setError] = useState('')
const [state, setState] = useState(false);
const [bookmark, setBookmark] = useState([false, false, false, false])
const [pagePlace, setPagePlace] = useState([])
const [showSet, setShowSet] = useState([false, false, false, false]);
const user = isAuthenticated()
async function getBookmark() {
try {
const response = await axios.get(`/api/users/bookmark?ID=${user}`)
setPagePlace(response.data.bookmark)
} catch (error) {
catchErrors(error, setError)
}
}
async function handleBookmark(index) {
if (!bookmark[index]) {
console.log(pagePlace[index])
try {
const response = await axios.put(`/api/users/bookmark?ID=${user}&place=${pagePlace[index]._id}`)
alert(response.data, '북마크가 저장되었습니다.')
const showArr = bookmark
showArr[index] = true
setBookmark(showArr)
console.log("bookmark=", bookmark)
} catch (error) {
catchErrors(error, setError)
}
} else {
try {
const response = await axios.delete(`/api/users/bookmark?ID=${user}`)
alert(response.data, '저장된 북마크가 삭제되었습니다.')
const showArr = bookmark
showArr[index] = false
setBookmark(showArr)
console.log("bookmark=", bookmark)
} catch (error) {
catchErrors(error, setError)
}
}
}
useEffect(() => {
getBookmark()
}, [])
return (
<Container>
<Navbar bg="info" variant="dark">
<Navbar.Brand href="/">북마크</Navbar.Brand>
<Nav className="mr-auto">
<Nav.Link href="/">Home</Nav.Link>
</Nav>
</Navbar>
<Row className="d-flex flex-wrap">
{console.log("#####################33", pagePlace)}
{pagePlace.map((place, index) => {
return (
<Col key={index} md={6} >
<Card align="center" border="info" style={{ margin: "3%" }}>
<Card.Title className="d-flex justify-content-center" style={{ margin: "3%", fontSize: '200%', fontWeight: 'bold' }} >{place.name}
{user ?
<Button
variant={bookmark[index] ? "primary" : "light"}
onClick={() => handleBookmark(index, place)}>
<Icon.BookmarkStarFill size={35} />
{console.log("bookmark", bookmark)}
{console.log("bookmark[index]", bookmark[index])}</Button> : null}
</Card.Title>
<Card.Img variant="top" style={{ padding: "5%", width: "100%", height: "340px" }} src={place.img} />
<Card.Body >
<Card.Text style={{ overflow: 'auto', fontSize: '25px', width: '100%', height: "80px" }} >
{place.address} </Card.Text>
<Button variant="info" onClick={() => {
const showArr = [false, false, false, false]
showArr[index] = true
setShowSet(showArr)
}}>{place.name} 자세히 살펴보기</Button>
{/* <Place place={place} index={index} show={showSet[index]} onHide={() => setShowSet([false, false, false, false])} /> */}
</Card.Body>
</Card>
</Col>
)
})}
</Row>
</Container>
)
}
export default Bookmark
// async function handleSubmit(e){
// setState(true); //버튼이 눌려서 handlesubmit이될때 setState값이 true로 바뀐다
// try { //respons 서버에 post로 요청하여 데이터를 받아온다
// const response = await axios.post('/api/users/bookmark', page)
// setSuccess(true)
// } catch (error) {
// console.log(error)
// catchErrors(error, setError)
// }
// }
// useEffect(() => {
// getBookmark(user)
// }, [user])
\ No newline at end of file
import React, { useState, useEffect } from 'react'
import { Alert, Col, Container, Form, Row, Button, Spinner } from "react-bootstrap"
import axios from "axios"
import catchErrors from '../utils/catchErrors'
import { Redirect } from 'react-router-dom'
import { handleLogin } from '../utils/auth'
const INIT_USER = {
email: '',
password: ''
} //초기 유저에 이메일 비밀번호 설정
function Login() {
//const [<상태 값 저장 변수>, <상태 값 갱신 함수>] = useState(<상태 초기 값>);
const [user, setUser] = useState(INIT_USER)
const [disabled, setDisabled] = useState(true)
const [error, setError] = useState('')
const [success, setSuccess] = useState(false)
const [loading, setLoading] = useState(false)
useEffect(() => { //참거짓 판단 값들의 원소들이 element로 들어간다
const isUser = Object.values(user).every(el => Boolean(el))
isUser ? setDisabled(false) : setDisabled(true)
}, [user])
function handleChange(event) {
const {name, value} = event.target //{}안에 값을 이벤트.타겟에 지정?한다
setUser({...user, [name]: value})
}
async function handleSubmit(event) {
event.preventDefault() //리셋을 막는다
try {
setLoading(true)
setError('') //값을 배열로 설정
const response = await axios.post('/api/auth/login', user)
console.log(response.data)
handleLogin(response.data.userId)//로그인했을때 userid data를 넣는다
setSuccess(true)
} catch (error) {
catchErrors(error, setError)
} finally {
setLoading(false)
}
}
if (success) {
console.log('success', success)
return <Redirect to= '/'/> //성공하면 홈화면으로 간다
}
return (
<Container>
<Row className= 'vh-100 flex-column align-items-center justify-content-center'>
<h2>로그인</h2>
<Col md={6}>
{error && <Alert variant='danger'>
{error}
</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Label>이메일</Form.Label>
<Form.Control name='email' type='email'value={user.email} onChange={handleChange}/>
</Form.Group>
<Form.Group>
<Form.Label>비밀번호</Form.Label>
<Form.Control name='password' type='password' value={user.password} onChange={handleChange}/>
</Form.Group>
<Button disabled={disabled || setLoading} type='submit'
block>
{loading && <Spinner as= 'span' animation= 'border' size='sm'
role= 'status' aria-hidden= 'true' />}{' '}확인</Button>
</Form>
</Col>
</Row>
</Container>
)
}
export default Login
......@@ -8,7 +8,7 @@ function Paginations(props) {
return (
<>
{(props.endPage > 5) ?
<Pagination>
<Pagination >
<Pagination.First onClick={() => props.handlePage(1)} />
{props.index === 1 ? <Pagination.Prev onClick={() => props.handlePage(props.index)} /> : <Pagination.Prev onClick={() => props.handlePage(props.index - 1)} />}
{props.index === props.endPage - 1 ? <Pagination.Item onClick={() => props.handlePage(props.index - 3)}>{props.index - 3}</Pagination.Item> : ""}
......
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { Modal, Container, Row, Button, } from 'react-bootstrap';
function Place(props) {
const [reviews, setReviews] = useState()
const [db, setDb] = useState(false)
const getReview = () => {
axios({ url: `/api/review?keyword=${props.place.name}`, method: 'post', data: { db: db } })
.then(res => {
console.log("place res.data", res.data)
setReviews(res.data)
})
.catch(err => {
console.log(err)
})
}
useEffect(() => {
getReview();
}, [])
return (
<Modal {...props}
size="xl"
keyboard="true"
variant="backdrop.in"
aria-labelledby="example-modal-sizes-title-lg">
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter" style={{ fontSize: '40px' }}>
{props.place.name}
</Modal.Title>
</Modal.Header>
<Modal.Body className="show-grid">
<Container style={{ fontSize: '40px' }}>
{Array.isArray(reviews) ? reviews.map((review) => {
return (
<Row className="mt-4">
<a href={review.link}>{review.title}</a>
<div>{review.summary}</div>
<div>{review.content}</div>
</Row>
)
})
: "리뷰가 없습니다."}
</Container>
</Modal.Body>
<Modal.Footer>
<Button block onClick={props.onHide}>Close</Button>
</Modal.Footer>
</Modal>
);
}
export default Place;
import React from 'react'
import { Route, Redirect } from 'react-router-dom'
import { isAuthenticated } from "../utils/auth";
function PrivateRoute({path, children}) {
if (isAuthenticated()) {
return (
<Route path={path}>
{children}
</Route>
)
} else {
return (
<Redirect to='/login' />
)
}
}
export default PrivateRoute
import React, { useState, useEffect } from 'react'
import { Col, Container, Form, Row, Button, Alert } from "react-bootstrap"
import axios from "axios"
import catchErrors from '../utils/catchErrors'
import { Redirect } from 'react-router-dom'
const INIT_USER = {
name: '',
email: '',
password: ''
} // 초기유저에 이름, 이메일, 비밀번호를 빈배열로 지정한다.
function Signup() {
const [user, setUser] = useState(INIT_USER)
const [disabled, setDisabled] = useState(true)
const [error, setError] = useState('')
const [success, setSuccess] = useState(false)
useEffect(() => {
const isUser = Object.values(user).every(el => Boolean(el))
isUser ? setDisabled(false) : setDisabled(true)
}, [user])
//바뀌는것이 있을때 이벤트가 발생하는 함수
function handleChange(event) {
const {name, value} = event.target
setUser({...user, [name]: value})
}
async function handleSubmit(event) {
event.preventDefault() //submit을 누르면 이벤트가 실행
try {
setError('') //post로 경로를 지정해서 서버에서 값을 받는다
const response = await axios.post('/api/users/signup', user)
console.log(response.data)
console.log(user)
setSuccess(true)
} catch (error) {
console.log(error)
catchErrors(error, setError)
}
}
//성공시 알림창이 뜨고 원래 페이지로 돌아간다
if (success) {
alert('회원가입 되었습니다.')
return <Redirect to='/'/>
}
return (
<Container>
<Row className= 'vh-100 flex-column align-items-center justify-content-center'>
<h2>회원가입</h2>
<Col md={5}>
{error && <Alert variant='danger'>
{error}
</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Label>이름</Form.Label>
<Form.Control name='name' value={user.name} onChange={handleChange}/>
</Form.Group>
<Form.Group>
<Form.Label>이메일</Form.Label>
<Form.Control name='email' type='email'value={user.email} onChange={handleChange}/>
</Form.Group>
<Form.Group>
<Form.Label>비밀번호</Form.Label>
<Form.Control name='password' type='password' value={user.password} onChange={handleChange}/>
</Form.Group>
<Button disabled={disabled} type='submit' block>확인</Button>
</Form>
</Col>
</Row>
</Container>
)
}
export default Signup
......@@ -4,6 +4,9 @@ import ohuh from '../ohuh.PNG';
import { Container, Row, Form, Image, InputGroup, Button, Col, Card } from 'react-bootstrap';
import axios from 'axios';
import Place from '../Components/Place';
import ohuh from '../ohuh.PNG'
import { Container, Row, Form, Image, InputGroup, Button, Col, Nav } from 'react-bootstrap';
import { handleLogout, isAuthenticated } from '../utils/auth.js'
function App() {
const [state, setState] = useState(false);
......@@ -17,6 +20,7 @@ function App() {
getRecommend()
getLatest()
}, []);
const user = isAuthenticated()
if (state !== false) {
return <Redirect to={`/search?keyword=${search}`} />;
......@@ -24,11 +28,11 @@ function App() {
const handleChange = (e) => {
setSearch(e.target.value);
}
} //바뀌는 것이 있을때 이벤트 발생
const handleSubmit = () => {
setState(true);
}
} //submit 버튼을 누르면 state 값을 true로 바뀐다
const getRecommend = () => {
axios.get(`/api/app/recommend`)
......@@ -54,14 +58,30 @@ function App() {
return (
<Container className="vh-100 ">
<Col md={12} >
<Row className="justify-content-center" >
<Image src={ohuh} style={{ margin: "5%", marginTop : "3%" }} />
// <Container className="vh-100 ">
// <Col md={12} >
// <Row className="justify-content-center" >
// <Image src={ohuh} style={{ margin: "5%", marginTop : "3%" }} />
// </Row>
// <Row style={{ marginBottom: "5%" }}>
<Container className="vh-100 d-flex justify-content-md-center align-items-center">
<Col md={6} style={{ marginTop: 140 }}>
<Nav className="justify-content-end" bg="#fff" variant="light" >
{user ? <Nav.Link onClick={() => handleLogout()}>로그아웃</Nav.Link>
: (
<>
<Nav.Link href="/signup">회원가입</Nav.Link>
<Nav.Link href="/login">로그인</Nav.Link>
</>
)}
<Nav.Link href='/bookmark'>북마크</Nav.Link>
</Nav>
<Row style={{ marginBottom: 20 }}>
<Image src={ohuh} />
</Row>
<Row style={{ marginBottom: "5%" }}>
<Row style={{ marginBottom: 500 }}>
<Form className="vw-100" onSubmit={handleSubmit}>
<InputGroup>
<InputGroup style={{ width: 560 }}>
<Form.Control
size="lg"
placeholder="검색어를 입력하세요."
......@@ -115,4 +135,4 @@ function App() {
);
}
export default App;
\ No newline at end of file
export default App;
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { Container, Row, Button, } from 'react-bootstrap';
import queryString from 'query-string'
function Place(props) {
console.log(props)
const [db, setDb] = useState(false)
const [index, setIndex] = useState(0)
const [reviews, setReviews] = useState([])
const place = queryString.parse(props.location.search).place
const getReview = (index) => {
console.log(index, "dlseprtm")
axios({ url: `/api/review?keyword=${place}&index=${index}`, method: 'post', data: { db: db } })
.then(res => {
console.log("place res.data", res.data)
setReviews([...reviews, ...res.data.review])
setDb(res.data.db)
setIndex(res.data.index)
})
.then(() => {
console.log(index, "인텍스", db)
})
.catch(err => {
console.log(err)
})
}
useEffect(() => {
getReview();
window.addEventListener("scroll", infiniteScroll);
return () => { window.removeEventListener("scroll", infiniteScroll); }
}, []);
// useEffect(() => {
// getReview();
// }, [index])
const infiniteScroll = () => {
const { documentElement, body } = document;
const scrollHeight = Math.max(documentElement.scrollHeight, body.scrollHeight);
const scrollTop = Math.max(documentElement.scrollTop, body.scrollTop);
const clientHeight = documentElement.clientHeight;
if (scrollTop + clientHeight >= scrollHeight) {
// setIndex(index + 1)
getReview(index + 1);
console.log("더불러", index + 1)
}
console.log(scrollHeight, scrollTop, clientHeight)
}
return (
<Container {...props}>
{place}
{Array.isArray(reviews) ? reviews.map((review, index) => {
return (
<Row className="mt-4">
<a href={review.link}>{review.title}</a>
<div>{review.summary}</div>
<div>{review.content}</div>
</Row>
)
})
: "리뷰가 없습니다."}
</Container>
);
}
export default Place;
......@@ -2,10 +2,13 @@ import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import ohuh from '../ohuh-sm.PNG';
import Place from '../Components/Place';
import { Container, Form, Row, Col, Card, Image, InputGroup, FormControl, Button } from 'react-bootstrap';
import { Container, Form, Row, Col, Card, Image, InputGroup, FormControl, Button, Nav } from 'react-bootstrap';
import Paginations from '../Components/Paginations';
import axios from 'axios';
import queryString from 'query-string'
import * as Icon from 'react-bootstrap-icons';
import { isAuthenticated } from '../utils/auth';
import catchErrors from '../utils/catchErrors'
function Search(props) {
......@@ -13,12 +16,22 @@ function Search(props) {
const [index, setIndex] = useState(1);
const [showSet, setShowSet] = useState([false, false, false, false]);
const [search, setSearch] = useState(queryString.parse(props.location.search).keyword);
const [bookmark, setBookmark] = useState([false, false, false, false])
const user = isAuthenticated()
const [mobile, setMobile] = useState();
const [association, setAssociation] = useState([{ name: " ", address: " ", img: " " }])
const [pagePlace, setPagePlace] = useState([{ name: " ", address: " ", img: " " }, { name: " ", address: " ", img: " " }])
const [endPage, setEndPage] = useState(1)
const [error, setError] = useState('')
async function getBookmark() {
try {
const response = await axios.get(`/api/users/bookmark?ID=${user}`)
// setBookmark(response.data.bookmark)
} catch (error) {
catchErrors(error, setError)
}
}
const getAssociation = () => {
axios.get(`/api/search/association?keyword=${search}`)
......@@ -35,12 +48,6 @@ function Search(props) {
useEffect(() => {
getAssociation()
if (window.innerWidth < 960) {
setMobile(true)
} else {
setMobile(false)
}
}, []);
useEffect(() => {
......@@ -51,18 +58,39 @@ function Search(props) {
setPagePlace(paginate(association, index, 4))
}
setEndPage(Math.floor((association.length / 4)))
<<<<<<< HEAD
=======
console.log("7489309484839", endPage)
>>>>>>> origin/cherry
}, [association, index])
useEffect(() => {
getAssociation()
if (state) {
// window.location.reload()
// return <Redirect to={{
// pathname: `/search?keyword=${search}`,
// state: { id: search },
// }} />;
props.history.push('/search?keyword=' + search)
setState(false)
console.log("search야", search)
// console.log("search야", search)
} window.addEventListener("scroll", infiniteScroll);
return () => { window.removeEventListener("scroll", infiniteScroll); }
}, [state]);
const infiniteScroll = () => {
const { documentElement, body } = document;
const scrollHeight = Math.max(documentElement.scrollHeight, body.scrollHeight);
const scrollTop = Math.max(documentElement.scrollTop, body.scrollTop);
const clientHeight = documentElement.clientHeight;
if (scrollTop + clientHeight >= scrollHeight) {
// getReview();
console.log("더불러")
}
}, [state])
console.log(scrollHeight, scrollTop, clientHeight)
}
const places = [{
......@@ -127,14 +155,39 @@ function Search(props) {
}
//usestate 쓰거나 한번에 useeffect에 넣기
async function handlebookmark(index) {
if (!bookmark[index]) {
console.log(pagePlace[index])
try {
const response = await axios.put(`/api/users/bookmark?ID=${user}&place=${pagePlace[index]._id}`)
alert(response.data, '북마크가 저장되었습니다.')
const showArr = bookmark
showArr[index] = true
setBookmark(showArr)
console.log("bookmark=", bookmark)
} catch (error) {
catchErrors(error, setError)
}
} else {
try {
const response = await axios.delete(`/api/users/bookmark?ID=${user}&place=${pagePlace[index]._id}`)
alert(response.data, '저장된 북마크가 삭제되었습니다.')
const showArr = bookmark
showArr[index] = false
setBookmark(showArr)
console.log("bookmark=", bookmark)
} catch (error) {
catchErrors(error, setError)
}
}
}
let time = new Date()
return (
<Container >
<Link to="/" className="d-flex justify-content-center"><Image src={ohuh} /></Link>
<Link to="/path" className="d-flex justify-content-center"><Image src={ohuh} /></Link>
<Row className="mb-2" className="d-flex justify-content-center">
<Form style={{ width: "90vw" }} onSubmit={handleSubmit}>
<InputGroup size="lg">
......@@ -159,29 +212,33 @@ function Search(props) {
return (
<Col key={index} md={6} >
<Card align="center" border="info" style={{ margin: "3%" }}>
<Card.Title style={{ margin: "3%", fontSize: '200%', fontWeight: 'bold' }} >{place.name}</Card.Title>
<Card.Title className="d-flex justify-content-center" style={{ margin: "3%", fontSize: '200%', fontWeight: 'bold' }} >{place.name}
{user ?
<Button
variant={bookmark[index] ? "primary" : "light"}
onClick={() => handlebookmark(index, place)}>
<Icon.BookmarkStarFill size={35} />
{console.log("bookmark", bookmark)}
{console.log("bookmark[index]", bookmark[index])}</Button> : null}
</Card.Title>
<Card.Img variant="top" style={{ padding: "5%", width: "100%", height: "340px" }} src={place.img} />
<Card.Body >
<Card.Body>
<Card.Text style={{ overflow: 'auto', fontSize: '25px', width: '100%', height: "80px" }} >
{place.address} </Card.Text>
<Button variant="primary" onClick={() => {
const showArr = [false, false, false, false]
showArr[index] = true
setShowSet(showArr)
}}>{place.name} 자세히 살펴보기</Button>
<Place place={place} index={index} show={showSet[index]} onHide={() => setShowSet([false, false, false, false])} />
<Link to={`/place?id=${index}&place=${place.name}`} >
<Button variant="primary"> {place.name} 자세히 살펴보기</Button>
</Link>
</Card.Body>
</Card>
</Col>
)
})}
</Row>
<Row className="mt-2 d-flex justify-content-center">
<Paginations index={index} endPage={endPage} handlePage={handlePage}></Paginations>
</Row>
</Container>
</Container >
);
}
......
......@@ -2,16 +2,20 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import App from './Pages/App';
import App from './Pages/App'
import Search from './Pages/Search';
import axios from 'axios';
import reportWebVitals from './reportWebVitals';
import Signup from './Components/Signup'
import Login from './Components/Login'
import PrivateRoute from "./Components/PrivateRoute";
import Bookmark from "./Bookmark"
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
} from "react-router-dom";
import Place from './Pages/Place';
ReactDOM.render(
<React.StrictMode>
......@@ -19,6 +23,10 @@ ReactDOM.render(
<Switch>
<Route exact path="/" component={App} />
<Route path="/search" component={Search} />
<Route path="/place" component={Place} />
<Route path='/signup' component={Signup}/>
<Route path='/login' component={Login} />
<PrivateRoute path='/bookmark'><Bookmark/></PrivateRoute>
<Redirect path="/search" to="/search" />
</Switch>
</Router>
......
import axios from "axios"
export function handleLogin(userId) { //로그인할때 로컬스토리지에 유저 아이디를 설정한다
localStorage.setItem('loginStatus', userId)
}
export async function handleLogout() {
localStorage.removeItem('loginStatus') //로컬스토리지에서 로그인상태를 지운다
await axios.get('/api/auth/logout')
window.location.href='/' //경로 지정
}
//유저가 로그인 했는 지 확인하는 함수
export function isAuthenticated() {
const userId = localStorage.getItem('loginStatus') //유저아이디를 로컬스토리지에서 가져와서 저장
if (userId) {
return userId
}else{
return false
}
}
\ No newline at end of file
function catchErrors(error, displayError) {
let errorMsg
if (error.response) {
errorMsg = error.response.data
console.log(errorMsg)
}else if (error.requset) {
errorMsg = error.requset
console.log(errorMsg)
} else {
errorMsg = error.message
console.log(errorMsg)
}
displayError(errorMsg)
}
export default catchErrors
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment