From 86e9efc7c30d2ed1f3538998996e3c6f305efe3e Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 16 Jul 2023 22:27:09 +0900 Subject: [PATCH 01/23] =?UTF-8?q?[fix]:=20global=20style=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit globalstyle 컴포넌트의 위치로 인한 렌더링 문제 해결 --- src/App.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/App.js b/src/App.js index 88dc2c6..6fa357b 100644 --- a/src/App.js +++ b/src/App.js @@ -5,11 +5,14 @@ import SignIn from './pages/SignIn'; const App = () => { return ( - + <> - } /> - } /> - + + } /> + } /> + + + ); } From 9299d1731a8a9e26637d02417699097d8e31d1c5 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 16 Jul 2023 22:28:57 +0900 Subject: [PATCH 02/23] initial commit of diary page --- src/pages/Diary.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/pages/Diary.js diff --git a/src/pages/Diary.js b/src/pages/Diary.js new file mode 100644 index 0000000..ee0d422 --- /dev/null +++ b/src/pages/Diary.js @@ -0,0 +1,16 @@ +import React from 'react' +import styled from 'styled-components' + +const Diary = () => { + return ( + <> + diary + + ) +} + +export default Diary + +const StyledComponent = styled.div` + +`; \ No newline at end of file From eef4097eadc8aedeb1c37ac6dc42fb71d881da09 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sat, 22 Jul 2023 14:06:46 +0900 Subject: [PATCH 03/23] =?UTF-8?q?[feature]:=20=EC=84=9C=EB=B2=84=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=9D=BC=EA=B8=B0=EC=9E=A5=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=9A=8D=EB=93=9D,=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EC=97=90=20=EA=B2=8C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit axios를 통해 서버와 통신, 페이지네이션 바의 페이지 버튼을 클릭함으로서 그 페이지에 해당하는 게시글을 반환, 추후 페이지네이션 기능 추가 예정 --- .gitignore | 1 + package.json | 3 +- src/App.js | 2 + src/assets/pen.svg | 3 + src/components/diary/PaginationBar.js | 47 ++++++++ src/pages/Diary.js | 68 ++++++++++- src/store/fakeDiary.js | 159 ++++++++++++++++++++++++++ src/utils/axios.js | 24 ++++ yarn.lock | 120 ++++++++++++++----- 9 files changed, 394 insertions(+), 33 deletions(-) create mode 100644 src/assets/pen.svg create mode 100644 src/components/diary/PaginationBar.js create mode 100644 src/store/fakeDiary.js create mode 100644 src/utils/axios.js diff --git a/.gitignore b/.gitignore index a09cb36..fc67fbb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ # misc .DS_Store +.env .env.local .env.development.local .env.test.local diff --git a/package.json b/package.json index c744fa6..e2d80f3 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,11 @@ "@testing-library/react": "^13.0.0", "@testing-library/user-event": "^13.2.1", "axios": "^1.4.0", - "dotenv": "^16.3.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.1.1", "react-router-dom": "^6.14.1", - "react-scripts": "5.0.1", + "react-scripts": "^5.0.1", "redux": "^4.2.1", "redux-devtools-extension": "^2.13.9", "redux-logger": "^3.0.6", diff --git a/src/App.js b/src/App.js index 6fa357b..31baa88 100644 --- a/src/App.js +++ b/src/App.js @@ -2,6 +2,7 @@ import { Route, Routes } from 'react-router'; import GlobalStyle from './styles/globalStyle'; import Landing from './pages/Landing'; import SignIn from './pages/SignIn'; +import Diary from './pages/Diary'; const App = () => { return ( @@ -10,6 +11,7 @@ const App = () => { } /> } /> + } /> diff --git a/src/assets/pen.svg b/src/assets/pen.svg new file mode 100644 index 0000000..f11b4cd --- /dev/null +++ b/src/assets/pen.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/diary/PaginationBar.js b/src/components/diary/PaginationBar.js new file mode 100644 index 0000000..6f87f67 --- /dev/null +++ b/src/components/diary/PaginationBar.js @@ -0,0 +1,47 @@ +import React from 'react' +import { Link } from 'react-router-dom'; +import styled from 'styled-components' + +const PaginationBar = ({currentPage, totalPages, setPage}) => { + const handlePageChange = (e) => { + const newPage = e.currentTarget.key; + setPage(newPage); + } + const renderLinks = (totalPages) => { + const links = []; + for (let pageNum = 1; pageNum <= totalPages; pageNum++) { + links.push( + + {pageNum} + + ); + } + return links; + } + return ( + <> + + {renderLinks(totalPages)} + + + ) +} + +export default PaginationBar + +const Container = styled.div` + display: flex; + align-items: center; + justify-content: center; + margin: auto; + a { + padding: 0.5rem; + text-decoration: none; + color: #313338; + } + .current { + font-weight: 600; + font-size: 18px + } +`; + diff --git a/src/pages/Diary.js b/src/pages/Diary.js index ee0d422..d787fb0 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -1,10 +1,41 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import styled from 'styled-components' +import { ReactComponent as WriteIcon } from "../assets/pen.svg"; +import { DiaryList } from '../store/fakeDiary' +import PaginationBar from '../components/diary/PaginationBar' +import { useLocation } from 'react-router-dom'; +import { getDiaryList } from '../utils/axios'; const Diary = () => { + const currentURL = useLocation().search; + const diaryList = [...DiaryList] + const [currentPage, setcurrentPage] = useState(1); + + useEffect(() => { + const extractPageNumFromURL = () => { + const urlParams = new URLSearchParams(currentURL); + const pageParam = urlParams.get('page'); + pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)); + } + extractPageNumFromURL(); + getDiaryList(1, 1); + }, [currentURL]); + return ( <> diary + + + + + {diaryList.map((post) => ( + + {post.title} + {post.content || "내용이 없다"} + + ))} + + ) } @@ -12,5 +43,38 @@ const Diary = () => { export default Diary const StyledComponent = styled.div` +`; + +const WritePostButton = styled.div` + right: 10vw; + bottom: 10vh; + position : absolute; + display: flex; + align-items: center; + justify-content: center; + width: 7vw; + height: 7vh; + background: #7054ff; + border-radius: 100px; + margin-left: 34px; + cursor: pointer; + :hover { + opacity: 0.8; + transition: 0.3s; + } +`; + +const DiaryListContainer = styled.div` + width: 100vw; + text-align: center; +`; + +const DiaryBlock = styled.div` + width: 300px; + margin: auto; + border : 1px solid +`; + +const Title = styled.div``; -`; \ No newline at end of file +const Content = styled.div``; \ No newline at end of file diff --git a/src/store/fakeDiary.js b/src/store/fakeDiary.js new file mode 100644 index 0000000..b08d10f --- /dev/null +++ b/src/store/fakeDiary.js @@ -0,0 +1,159 @@ +export const DiaryList = +[ + { + "postId": 1, + "title": "누군가의 일기장", + "content": "오늘은 개발을 시작했따", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false + }, + { + "postId": 2, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, { + "postId": 3, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, { + "postId": 4, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, { + "postId": 5, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, { + "postId": 6, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, { + "postId": 7, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, { + "postId": 8, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, { + "postId": 9, + "title": "누군가의 일기장", + "thumbnailImgURL": "", + "likeCount": 3, + "commentCount": 1, + "viewCount": 12, + "user": { + "userId": 2019102240, + "profileImgURL": "", + "name": "한우준", + }, + "createdDate": "2023/07/20", + "isAnonymous": false, + "isMyPost": true, + "isLiked": false, + "isBookmarked": false +}, +] \ No newline at end of file diff --git a/src/utils/axios.js b/src/utils/axios.js new file mode 100644 index 0000000..179c664 --- /dev/null +++ b/src/utils/axios.js @@ -0,0 +1,24 @@ +import axios from 'axios'; + +export const getDiaryList = (cursor, size) => { + const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; + let config = { + method: 'get', + maxBodyLength: Infinity, + url: `https://khu-return.site/diary/list?cursor=${cursor}&size=${size}`, + headers: { + 'Authorization': `${authorizationCode}`, + 'Cookie': `authorization=${authorizationCode}` + } + }; + + axios.request(config) + .then((response) => { + console.log(JSON.stringify(response.data)); + }) + .catch((error) => { + console.log(error); + }); + +} + diff --git a/yarn.lock b/yarn.lock index 9ec88a8..781f3be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2816,6 +2816,18 @@ array.prototype.tosorted@^1.1.1: es-shim-unscopables "^1.0.0" get-intrinsic "^1.1.3" +arraybuffer.prototype.slice@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" + integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -3198,7 +3210,12 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001464: + version "1.0.30001517" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz#90fabae294215c3495807eb24fc809e11dc2f0a8" + integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA== + +caniuse-lite@^1.0.30001503: version "1.0.30001516" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz#621b1be7d85a8843ee7d210fd9d87b52e3daab3a" integrity sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g== @@ -4006,11 +4023,6 @@ dotenv@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== -dotenv@^16.3.1: - version "16.3.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" - integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== - duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -4091,11 +4103,12 @@ error-stack-parser@^2.0.6: stackframe "^1.3.4" es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.21.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.3.tgz#8aaa0ffc080e8a6fef6ace72631dc1ec5d47bf94" - integrity sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg== + version "1.22.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== dependencies: array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" @@ -4122,10 +4135,13 @@ es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21 object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" safe-regex-test "^1.0.0" string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" @@ -4317,9 +4333,9 @@ eslint-plugin-react-hooks@^4.3.0: integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== eslint-plugin-react@^7.27.1: - version "7.32.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10" - integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg== + version "7.33.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.0.tgz#6c356fb0862fec2cd1b04426c669ea746e9b6eb3" + integrity sha512-qewL/8P34WkY8jAqdQxsiL82pDUeT7nhs8IsuXgfgnsEloKCT4miAV9N9kGtx7/KM9NH/NCGUE7Edt9iGxLXFw== dependencies: array-includes "^3.1.6" array.prototype.flatmap "^1.3.1" @@ -4334,7 +4350,7 @@ eslint-plugin-react@^7.27.1: object.values "^1.1.6" prop-types "^15.8.1" resolve "^2.0.0-next.4" - semver "^6.3.0" + semver "^6.3.1" string.prototype.matchall "^4.0.8" eslint-plugin-testing-library@^5.0.1: @@ -5487,7 +5503,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.9: +is-typed-array@^1.1.10: version "1.1.10" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== @@ -5498,6 +5514,13 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.0" +is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -7541,7 +7564,16 @@ postcss@^7.0.35: picocolors "^0.2.1" source-map "^0.6.1" -postcss@^8.3.5, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.4: +postcss@^8.3.5, postcss@^8.4.21, postcss@^8.4.4: + version "8.4.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057" + integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +postcss@^8.4.23: version "8.4.26" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.26.tgz#1bc62ab19f8e1e5463d98cf74af39702a00a9e94" integrity sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw== @@ -7801,7 +7833,7 @@ react-router@6.14.1: dependencies: "@remix-run/router" "1.7.1" -react-scripts@5.0.1: +react-scripts@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.1.tgz#6285dbd65a8ba6e49ca8d651ce30645a6d980003" integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ== @@ -8671,9 +8703,9 @@ stylis@^4.3.0: integrity sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ== sucrase@^3.32.0: - version "3.33.0" - resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.33.0.tgz#092c8d2f99a191f2cd9f1fdd52113772f4241f6e" - integrity sha512-ARGC7vbufOHfpvyGcZZXFaXCMZ9A4fffOGC5ucOW7+WHDGlAe8LJdf3Jts1sWhDeiI1RSWrKy5Hodl+JWGdW2A== + version "3.34.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f" + integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw== dependencies: "@jridgewell/gen-mapping" "^0.3.2" commander "^4.0.0" @@ -8832,9 +8864,9 @@ terser-webpack-plugin@^5.2.5, terser-webpack-plugin@^5.3.7: terser "^5.16.8" terser@^5.0.0, terser@^5.10.0, terser@^5.16.8: - version "5.19.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.0.tgz#7b3137b01226bdd179978207b9c8148754a6da9c" - integrity sha512-JpcpGOQLOXm2jsomozdMDpd5f8ZHh1rR48OFgWUH3QsyZcfPgv2qDCYbcDEAYNd4OZRj2bWYKpwdll/udZCk/Q== + version "5.19.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.2.tgz#bdb8017a9a4a8de4663a7983f45c506534f9234e" + integrity sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -8997,6 +9029,25 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + typed-array-byte-offset@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" @@ -9294,9 +9345,9 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.64.4: - version "5.88.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.1.tgz#21eba01e81bd5edff1968aea726e2fbfd557d3f8" - integrity sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ== + version "5.88.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" + integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.0" @@ -9345,9 +9396,9 @@ whatwg-encoding@^1.0.5: iconv-lite "0.4.24" whatwg-fetch@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" - integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + version "3.6.17" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.17.tgz#009bbbfc122b227b74ba1ff31536b3a1a0e0e212" + integrity sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ== whatwg-mimetype@^2.3.0: version "2.3.0" @@ -9393,7 +9444,18 @@ which-collection@^1.0.1: is-weakmap "^2.0.1" is-weakset "^2.0.1" -which-typed-array@^1.1.10, which-typed-array@^1.1.9: +which-typed-array@^1.1.10, which-typed-array@^1.1.11: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +which-typed-array@^1.1.9: version "1.1.10" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.10.tgz#74baa2789991905c2076abb317103b866c64e69e" integrity sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA== From 05066ffd52fbd4b0f38623deb7c0bfbfbbdbe93f Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sat, 22 Jul 2023 14:21:36 +0900 Subject: [PATCH 04/23] =?UTF-8?q?[fix]:=20=ED=98=84=EC=9E=AC=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=A3=BC=EC=86=8C=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 테스트용으로 고정되어있던 변수를 페이지 주소에 맞게 반환받을 수 있도록 수정, 한 페이지에 표시될 글 개수 변수 추가 --- src/pages/Diary.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/Diary.js b/src/pages/Diary.js index d787fb0..7618596 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -10,16 +10,17 @@ const Diary = () => { const currentURL = useLocation().search; const diaryList = [...DiaryList] const [currentPage, setcurrentPage] = useState(1); + const [pageSize, setPageSize] = useState(10); - useEffect(() => { - const extractPageNumFromURL = () => { + useEffect( () => { + const extractPageNumFromURL = async () => { const urlParams = new URLSearchParams(currentURL); const pageParam = urlParams.get('page'); pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)); + getDiaryList(parseInt(pageParam, 10), pageSize); } extractPageNumFromURL(); - getDiaryList(1, 1); - }, [currentURL]); + }, [currentURL, pageSize]); return ( <> From d5b523a3f98ef863ea71b606f02330497e02c87d Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 23 Jul 2023 14:17:17 +0900 Subject: [PATCH 05/23] =?UTF-8?q?[feature]:=20=EC=B4=9D=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EB=AC=BC=20=EA=B0=9C=EC=88=98=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=88=98=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Diary.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/pages/Diary.js b/src/pages/Diary.js index 7618596..5873435 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -10,23 +10,25 @@ const Diary = () => { const currentURL = useLocation().search; const diaryList = [...DiaryList] const [currentPage, setcurrentPage] = useState(1); - const [pageSize, setPageSize] = useState(10); - - useEffect( () => { - const extractPageNumFromURL = async () => { + const [pageSize, setPageSize] = useState(3); + const [numberOfPages, setNumberOfPages] = useState() + + useEffect(() => { + const extractPageNumFromURL = () => { const urlParams = new URLSearchParams(currentURL); const pageParam = urlParams.get('page'); pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)); getDiaryList(parseInt(pageParam, 10), pageSize); + setNumberOfPages((diaryList.length / pageSize) + 1) } extractPageNumFromURL(); - }, [currentURL, pageSize]); + }, [currentURL, pageSize, diaryList.length]); return ( <> diary - + {diaryList.map((post) => ( @@ -36,7 +38,7 @@ const Diary = () => { ))} - + ) } @@ -53,8 +55,8 @@ const WritePostButton = styled.div` display: flex; align-items: center; justify-content: center; - width: 7vw; - height: 7vh; + width: 128px; + height: 128px; background: #7054ff; border-radius: 100px; margin-left: 34px; From 9a7fb20b875d0cb0b3f0a7207fa19b1f3627bc97 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 23 Jul 2023 14:50:48 +0900 Subject: [PATCH 06/23] =?UTF-8?q?[feature]:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EB=8B=B9=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20=EC=88=98=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=88=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/diary/PaginationBar.js | 3 ++- src/pages/Diary.js | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/diary/PaginationBar.js b/src/components/diary/PaginationBar.js index 6f87f67..767284c 100644 --- a/src/components/diary/PaginationBar.js +++ b/src/components/diary/PaginationBar.js @@ -11,13 +11,14 @@ const PaginationBar = ({currentPage, totalPages, setPage}) => { const links = []; for (let pageNum = 1; pageNum <= totalPages; pageNum++) { links.push( - + {pageNum} ); } return links; } + return ( <> diff --git a/src/pages/Diary.js b/src/pages/Diary.js index 5873435..8807285 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -12,7 +12,7 @@ const Diary = () => { const [currentPage, setcurrentPage] = useState(1); const [pageSize, setPageSize] = useState(3); const [numberOfPages, setNumberOfPages] = useState() - + useEffect(() => { const extractPageNumFromURL = () => { const urlParams = new URLSearchParams(currentURL); @@ -31,6 +31,15 @@ const Diary = () => { + + 페이지 당 게시물 개수 + setPageSize(1)}/> + + setPageSize(5)}/> + + setPageSize(10)}/> + + {diaryList.map((post) => ( {post.title} @@ -72,6 +81,10 @@ const DiaryListContainer = styled.div` text-align: center; `; +const PageSizeRegulator = styled.div``; + +const RegulatorButton = styled.input``; + const DiaryBlock = styled.div` width: 300px; margin: auto; From bd732ab068bf66f9a523ae519bb91c25975679f9 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:29:23 +0900 Subject: [PATCH 07/23] =?UTF-8?q?[chore]:=20Diary=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20useEffect=20=EB=82=B4=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC,=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diary.js 내 useEffect부 extractPageNumFromURL() 내부의 getDiaryList(), setNumberOfPages() 분리 - axios.js, Diary.js 파일 내 To do 주석 추가 --- src/pages/Diary.js | 33 ++++++++++++++++++++------------- src/utils/axios.js | 9 ++++++--- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/pages/Diary.js b/src/pages/Diary.js index 8807285..e608e50 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -1,28 +1,34 @@ import React, { useEffect, useState } from 'react' import styled from 'styled-components' -import { ReactComponent as WriteIcon } from "../assets/pen.svg"; +import { ReactComponent as WriteIcon } from "../assets/pen.svg" import { DiaryList } from '../store/fakeDiary' import PaginationBar from '../components/diary/PaginationBar' -import { useLocation } from 'react-router-dom'; -import { getDiaryList } from '../utils/axios'; +import { useLocation } from 'react-router-dom' +import { getDiaryList } from '../utils/axios' + +/** + * To do + * 1. PageSizeRegulator, DiaryBlock 컴포넌트 분리, 추상화 요망 + * 2. 게시물 작성 UI(Modal) 제작, Post /diary + */ const Diary = () => { - const currentURL = useLocation().search; + const currentURL = useLocation().search const diaryList = [...DiaryList] - const [currentPage, setcurrentPage] = useState(1); - const [pageSize, setPageSize] = useState(3); + const [currentPage, setcurrentPage] = useState(1) + const [pageSize, setPageSize] = useState(3) const [numberOfPages, setNumberOfPages] = useState() useEffect(() => { const extractPageNumFromURL = () => { - const urlParams = new URLSearchParams(currentURL); - const pageParam = urlParams.get('page'); - pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)); - getDiaryList(parseInt(pageParam, 10), pageSize); - setNumberOfPages((diaryList.length / pageSize) + 1) + const urlParams = new URLSearchParams(currentURL) + const pageParam = urlParams.get('page') + pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)) + return parseInt(pageParam,10); } - extractPageNumFromURL(); - }, [currentURL, pageSize, diaryList.length]); + getDiaryList(extractPageNumFromURL(), pageSize) + setNumberOfPages((diaryList.length / pageSize) + 1) + }, [currentURL, pageSize, diaryList.length]) return ( <> @@ -40,6 +46,7 @@ const Diary = () => { setPageSize(10)}/> + {/** To do: 현재 서버의 일기장 리스트가 비어있는 관계로 /store/fakeDiary.js 의 가짜 데이터를 사용중, 추후 서버에 일기장 데이터 추가 시 변경 요망 */} {diaryList.map((post) => ( {post.title} diff --git a/src/utils/axios.js b/src/utils/axios.js index 179c664..7cddac6 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -1,15 +1,18 @@ import axios from 'axios'; + + export const getDiaryList = (cursor, size) => { + /** + * To do: GET /diary/list api가 변경되면 getDiaryList url cursor 부분 변경 요망 + */ const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; let config = { method: 'get', maxBodyLength: Infinity, url: `https://khu-return.site/diary/list?cursor=${cursor}&size=${size}`, headers: { - 'Authorization': `${authorizationCode}`, - 'Cookie': `authorization=${authorizationCode}` - } + 'Authorization': `${authorizationCode}`, } }; axios.request(config) From 27432bb8277dec468267d6a7d71253e3851085b5 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 23 Jul 2023 21:48:57 +0900 Subject: [PATCH 08/23] =?UTF-8?q?[feature]:=20=EA=B2=8C=EC=8B=9C=EB=AC=BC?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=20ui:=20modal=20=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/close_gray.svg | 3 + src/assets/images.svg | 3 + src/components/diary/WritePostModal.js | 191 +++++++++++++++++++++++++ src/pages/Diary.js | 18 ++- 4 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 src/assets/close_gray.svg create mode 100644 src/assets/images.svg create mode 100644 src/components/diary/WritePostModal.js diff --git a/src/assets/close_gray.svg b/src/assets/close_gray.svg new file mode 100644 index 0000000..75fabc8 --- /dev/null +++ b/src/assets/close_gray.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/images.svg b/src/assets/images.svg new file mode 100644 index 0000000..2c4af28 --- /dev/null +++ b/src/assets/images.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/diary/WritePostModal.js b/src/components/diary/WritePostModal.js new file mode 100644 index 0000000..0a4d56b --- /dev/null +++ b/src/components/diary/WritePostModal.js @@ -0,0 +1,191 @@ +import React from "react"; +import styled from "styled-components"; +import { ReactComponent as CloseIcon } from "../../assets/close_gray.svg"; +import { ReactComponent as ImagesIcon } from "../../assets/images.svg"; + +const WritePostModal = ({ setIsModalOpen, name, fileName, setFileName }) => { + const placeholder = `${name}님, 오늘은 어떤 이야기를 나눠볼까요?`; + const handleModalClose = () => { + document.body.style.overflow = "unset"; + setIsModalOpen(false); + }; + const handleFileChange = (e) => { + const newFile = e.target.files[0]; + newFile ? setFileName(newFile.name) : setFileName(""); + }; + return ( + <> + + + handleModalClose()} + /> + + + {name} + + + + {fileName} + + + + + + + + + 게시물 올리기 + + + + + ); +}; + +export default WritePostModal; + +const ModalBackground = styled.div` + display: flex; + box-sizing: border-box; + position: fixed; + top: 64px; + left: 0; + bottom: 0; + right: 0; + width: 100%; + height: 100%; + background: rgba(139, 139, 139, 0.2); + backdrop-filter: blur(15px); + z-index: 999; + overflow: hidden; + transition: .5s; +`; + +const ModalOutlay = styled.div` + position: relative; + top: 0; + left: 0; + bottom: 0; + right: 0; + display: flex; + flex-direction: column; + margin: auto; + width: 764px; + height: 627px; + background: #ffffff; + border: 1px solid #fafafa; + box-sizing: border-box; + border-radius: 10px; + .close-button { + position: absolute; + top: 33px; + left: 712px; + color: #8b8b8b; + width: 14px; + height: 14px; + cursor: pointer; + } +`; + +const ModalHeader = styled.div` + display: flex; + margin: 40px 45px 0px 45px; + height: 30px; +`; + +const ProfileImg = styled.div` + width: 30px; + height: 30px; + border-radius: 100px; + background: #d2d2d2; +`; + +const Name = styled.div` + display: flex; + align-items: center; + height: 30px; + font-family: Pretendard; + font-style: normal; + font-weight: bold; + font-size: 16px; + margin-left: 8px; +`; + +const ModalInner = styled.div` + margin: 18px 45px 0px 45px; +`; + +const AddImageBar = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 8px 18px; + width: 638px; + height: 36px; + background: #f5f3ff; + border-radius: 10px; +`; + +const ImageInput = styled.input` + display: none; +`; + +const AddImageIcon = styled.label` + cursor: pointer; + padding-top: 4px; +`; + +const FileName = styled.div` + font-family: Pretendard; + font-style: normal; + font-weight: normal; + font-size: 16px; + line-height: 16px; + color: #7054ff; +`; + +const PostContent = styled.textarea` + width: 634px; + height: 308px; + margin: 40px 20px 0px 20px; + font-family: Pretendard; + font-style: normal; + font-weight: normal; + font-size: 18px; + line-height: 18px; + color: #313338; + border: none; + resize: none; + outline: none; + ::placeholder { + color: #d2d2d2; + } +`; + +const ModalFooter = styled.div` + display: flex; + justify-content: center; + align-items: center; + margin: 56px 0px 45px 0px; +`; + +const SubmitButton = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + width: 400px; + height: 48px; + background: #7054ff; + border-radius: 30px; + color: #ffffff; + font-family: Pretendard; + font-style: normal; + font-weight: bold; + font-size: 20px; + line-height: 16px; + cursor: pointer; +`; diff --git a/src/pages/Diary.js b/src/pages/Diary.js index e608e50..ba6017a 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -5,6 +5,7 @@ import { DiaryList } from '../store/fakeDiary' import PaginationBar from '../components/diary/PaginationBar' import { useLocation } from 'react-router-dom' import { getDiaryList } from '../utils/axios' +import WritePostModal from '../components/diary/WritePostModal' /** * To do @@ -18,6 +19,13 @@ const Diary = () => { const [currentPage, setcurrentPage] = useState(1) const [pageSize, setPageSize] = useState(3) const [numberOfPages, setNumberOfPages] = useState() + const [isModalOpen, setIsModalOpen] = useState(false); + const [fileName, setFileName] = useState("게시물에 추가"); + + const handleModalOpen = () => { + document.body.style.overflow = "hidden"; + setIsModalOpen(true); + }; useEffect(() => { const extractPageNumFromURL = () => { @@ -33,7 +41,7 @@ const Diary = () => { return ( <> diary - + @@ -55,6 +63,14 @@ const Diary = () => { ))} + {isModalOpen && ( + + )} ) } From 34fbc07ed52d260df715f3f1a5d8f7a9928a03a8 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sat, 29 Jul 2023 02:34:21 +0900 Subject: [PATCH 09/23] =?UTF-8?q?[feat]:=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20wysiwyg=20=ED=8E=B8=EC=A7=91=EA=B8=B0=20ui?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 게시물 작성 ui에 wysiwyg형 적용 --- package.json | 1 + src/assets/pen.svg | 2 +- src/components/diary/PostEditor.js | 29 +++++++ src/components/diary/WritePostModal.js | 73 ++--------------- yarn.lock | 108 +++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 67 deletions(-) create mode 100644 src/components/diary/PostEditor.js diff --git a/package.json b/package.json index e2d80f3..6249ac1 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^13.0.0", "@testing-library/user-event": "^13.2.1", + "@toast-ui/react-editor": "^3.2.3", "axios": "^1.4.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/assets/pen.svg b/src/assets/pen.svg index f11b4cd..a47c296 100644 --- a/src/assets/pen.svg +++ b/src/assets/pen.svg @@ -1,3 +1,3 @@ - + diff --git a/src/components/diary/PostEditor.js b/src/components/diary/PostEditor.js new file mode 100644 index 0000000..9146698 --- /dev/null +++ b/src/components/diary/PostEditor.js @@ -0,0 +1,29 @@ +import '@toast-ui/editor/dist/toastui-editor.css'; +import { Editor } from '@toast-ui/react-editor'; + +const PostEditor = ({editorRef}) => { + const toolbarItems = [ + ['heading', 'bold', 'italic', 'strike'], + ['hr'], + ['ul', 'ol', 'task'], + ['table', 'link'], + ['image'], + ['code'], + ['scrollSync'], + ] + return ( + <> + + + ) +} + +export default PostEditor \ No newline at end of file diff --git a/src/components/diary/WritePostModal.js b/src/components/diary/WritePostModal.js index 0a4d56b..53be4af 100644 --- a/src/components/diary/WritePostModal.js +++ b/src/components/diary/WritePostModal.js @@ -1,18 +1,14 @@ -import React from "react"; +import React, { useRef } from "react"; import styled from "styled-components"; import { ReactComponent as CloseIcon } from "../../assets/close_gray.svg"; -import { ReactComponent as ImagesIcon } from "../../assets/images.svg"; +import PostEditor from './PostEditor'; -const WritePostModal = ({ setIsModalOpen, name, fileName, setFileName }) => { - const placeholder = `${name}님, 오늘은 어떤 이야기를 나눠볼까요?`; +const WritePostModal = ({ setIsModalOpen, name}) => { + const ref = useRef(null); const handleModalClose = () => { document.body.style.overflow = "unset"; setIsModalOpen(false); }; - const handleFileChange = (e) => { - const newFile = e.target.files[0]; - newFile ? setFileName(newFile.name) : setFileName(""); - }; return ( <> @@ -26,14 +22,7 @@ const WritePostModal = ({ setIsModalOpen, name, fileName, setFileName }) => { {name} - - {fileName} - - - - - - + 게시물 올리기 @@ -63,7 +52,7 @@ const ModalBackground = styled.div` transition: .5s; `; -const ModalOutlay = styled.div` +const ModalOutlay = styled.form` position: relative; top: 0; left: 0; @@ -73,7 +62,7 @@ const ModalOutlay = styled.div` flex-direction: column; margin: auto; width: 764px; - height: 627px; + height: 80vh; background: #ffffff; border: 1px solid #fafafa; box-sizing: border-box; @@ -117,54 +106,6 @@ const ModalInner = styled.div` margin: 18px 45px 0px 45px; `; -const AddImageBar = styled.div` - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - padding: 8px 18px; - width: 638px; - height: 36px; - background: #f5f3ff; - border-radius: 10px; -`; - -const ImageInput = styled.input` - display: none; -`; - -const AddImageIcon = styled.label` - cursor: pointer; - padding-top: 4px; -`; - -const FileName = styled.div` - font-family: Pretendard; - font-style: normal; - font-weight: normal; - font-size: 16px; - line-height: 16px; - color: #7054ff; -`; - -const PostContent = styled.textarea` - width: 634px; - height: 308px; - margin: 40px 20px 0px 20px; - font-family: Pretendard; - font-style: normal; - font-weight: normal; - font-size: 18px; - line-height: 18px; - color: #313338; - border: none; - resize: none; - outline: none; - ::placeholder { - color: #d2d2d2; - } -`; - const ModalFooter = styled.div` display: flex; justify-content: center; diff --git a/yarn.lock b/yarn.lock index 781f3be..8c6eba6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1968,6 +1968,27 @@ dependencies: "@babel/runtime" "^7.12.5" +"@toast-ui/editor@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-3.2.2.tgz#1f2837271c5c9c3e29e090d7440bfc6ab23fb4c4" + integrity sha512-ASX7LFjN2ZYQJrwmkUajPs7DRr9FsM1+RQ82CfTO0Y5ZXorBk1VZS4C2Dpxinx9kl55V4F8/A2h2QF4QMDtRbA== + dependencies: + dompurify "^2.3.3" + prosemirror-commands "^1.1.9" + prosemirror-history "^1.1.3" + prosemirror-inputrules "^1.1.3" + prosemirror-keymap "^1.1.4" + prosemirror-model "^1.14.1" + prosemirror-state "^1.3.4" + prosemirror-view "^1.18.7" + +"@toast-ui/react-editor@^3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@toast-ui/react-editor/-/react-editor-3.2.3.tgz#e335f99595709b5b1961d3d77a0338a07c419a32" + integrity sha512-86QdgiOkBeSwRBEUWRKsTpnm6yu5j9HNJ3EfQN8EGcd7kI8k8AhExXyUJ3NNgNTzN7FfSKMw+1VaCDDC+aZ3dw== + dependencies: + "@toast-ui/editor" "^3.2.2" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -3988,6 +4009,11 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" +dompurify@^2.3.3: + version "2.4.7" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.7.tgz#277adeb40a2c84be2d42a8bcd45f582bfa4d0cfc" + integrity sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ== + domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" @@ -6846,6 +6872,11 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" +orderedmap@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.1.1.tgz#61481269c44031c449915497bf5a4ad273c512d2" + integrity sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g== + p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -7657,6 +7688,73 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +prosemirror-commands@^1.1.9: + version "1.5.2" + resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.5.2.tgz#e94aeea52286f658cd984270de9b4c3fff580852" + integrity sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ== + dependencies: + prosemirror-model "^1.0.0" + prosemirror-state "^1.0.0" + prosemirror-transform "^1.0.0" + +prosemirror-history@^1.1.3: + version "1.3.2" + resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.3.2.tgz#ce6ad7ab9db83e761aee716f3040d74738311b15" + integrity sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g== + dependencies: + prosemirror-state "^1.2.2" + prosemirror-transform "^1.0.0" + prosemirror-view "^1.31.0" + rope-sequence "^1.3.0" + +prosemirror-inputrules@^1.1.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prosemirror-inputrules/-/prosemirror-inputrules-1.2.1.tgz#8faf3d78c16150aedac71d326a3e3947417ce557" + integrity sha512-3LrWJX1+ULRh5SZvbIQlwZafOXqp1XuV21MGBu/i5xsztd+9VD15x6OtN6mdqSFI7/8Y77gYUbQ6vwwJ4mr6QQ== + dependencies: + prosemirror-state "^1.0.0" + prosemirror-transform "^1.0.0" + +prosemirror-keymap@^1.1.4: + version "1.2.2" + resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz#14a54763a29c7b2704f561088ccf3384d14eb77e" + integrity sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ== + dependencies: + prosemirror-state "^1.0.0" + w3c-keyname "^2.2.0" + +prosemirror-model@^1.0.0, prosemirror-model@^1.14.1, prosemirror-model@^1.16.0: + version "1.19.3" + resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.19.3.tgz#f0d55285487fefd962d0ac695f716f4ec6705006" + integrity sha512-tgSnwN7BS7/UM0sSARcW+IQryx2vODKX4MI7xpqY2X+iaepJdKBPc7I4aACIsDV/LTaTjt12Z56MhDr9LsyuZQ== + dependencies: + orderedmap "^2.0.0" + +prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.4: + version "1.4.3" + resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.4.3.tgz#94aecf3ffd54ec37e87aa7179d13508da181a080" + integrity sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q== + dependencies: + prosemirror-model "^1.0.0" + prosemirror-transform "^1.0.0" + prosemirror-view "^1.27.0" + +prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0: + version "1.7.4" + resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.7.4.tgz#ea878c90563f3586064dd5ccf6cabb50b2753fd9" + integrity sha512-GO38mvqJ2yeI0BbL5E1CdHcly032Dlfn9nHqlnCHqlNf9e9jZwJixxp6VRtOeDZ1uTDpDIziezMKbA41LpAx3A== + dependencies: + prosemirror-model "^1.0.0" + +prosemirror-view@^1.18.7, prosemirror-view@^1.27.0, prosemirror-view@^1.31.0: + version "1.31.7" + resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.31.7.tgz#dccb2879314e1e1a24d48044c15374754e50ef00" + integrity sha512-Pr7w93yOYmxQwzGIRSaNLZ/1uM6YjnenASzN2H6fO6kGekuzRbgZ/4bHbBTd1u4sIQmL33/TcGmzxxidyPwCjg== + dependencies: + prosemirror-model "^1.16.0" + prosemirror-state "^1.0.0" + prosemirror-transform "^1.1.0" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -8138,6 +8236,11 @@ rollup@^2.43.1: optionalDependencies: fsevents "~2.3.2" +rope-sequence@^1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.4.tgz#df85711aaecd32f1e756f76e43a415171235d425" + integrity sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -9219,6 +9322,11 @@ w3c-hr-time@^1.0.2: dependencies: browser-process-hrtime "^1.0.0" +w3c-keyname@^2.2.0: + version "2.2.8" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" + integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== + w3c-xmlserializer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" From 91648c6c743d7184e17e996fb1789e4752edfc22 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sat, 29 Jul 2023 17:46:35 +0900 Subject: [PATCH 10/23] =?UTF-8?q?[feat]:=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EA=B8=B0=EB=8A=A5(=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EB=AF=B8=EA=B5=AC=ED=98=84)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 현재 서버 api 개선 전 임시용 검색 기능 추가 --- src/components/SearchBar.js | 44 ++++++++++++++++++++ src/pages/Diary.js | 83 ++++++++++++++++++++++++------------- 2 files changed, 98 insertions(+), 29 deletions(-) create mode 100644 src/components/SearchBar.js diff --git a/src/components/SearchBar.js b/src/components/SearchBar.js new file mode 100644 index 0000000..16c886d --- /dev/null +++ b/src/components/SearchBar.js @@ -0,0 +1,44 @@ +import React from "react"; +import styled from "styled-components"; + +const SearchBar = ({ width, height, fontSize, placeholder, value, onChange }) => { + return ( + + + + ); +}; + +export default SearchBar; + +export const StyledSearchBar = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + width: ${(props) => props.requirement.width && props.requirement.width}; + height: ${(props) => props.requirement.height && props.requirement.height}; + min-height: 44px; + min-width: 375px; + padding-left: 30px; + padding-right: 30px; + border-radius: 100px; + background: #fafafa; + input { + width: ${(props) => props.requirement.width && props.requirement.width}; + border: none; + border-radius: 100px; + outline: none; + background: #fafafa; + font-family: Pretendard; + font-size: ${(props) => props.requirement.fontSize && props.requirement.fontSize}; + min-height: 44px; + min-width: 375px; + font-weight: 400; + line-height: 44px; + } +`; \ No newline at end of file diff --git a/src/pages/Diary.js b/src/pages/Diary.js index ba6017a..2b99abc 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -6,11 +6,12 @@ import PaginationBar from '../components/diary/PaginationBar' import { useLocation } from 'react-router-dom' import { getDiaryList } from '../utils/axios' import WritePostModal from '../components/diary/WritePostModal' +import SearchBar from '../components/SearchBar' /** * To do * 1. PageSizeRegulator, DiaryBlock 컴포넌트 분리, 추상화 요망 - * 2. 게시물 작성 UI(Modal) 제작, Post /diary + * 2. 현재 fake data를 array method를 사용해 검색 기능을 구현한 상태. 추후 서버쪽 api 업데이트 되는대로 /diary?cursor={int}&size={int}&search={string} 사용할 것 */ const Diary = () => { @@ -20,13 +21,21 @@ const Diary = () => { const [pageSize, setPageSize] = useState(3) const [numberOfPages, setNumberOfPages] = useState() const [isModalOpen, setIsModalOpen] = useState(false); - const [fileName, setFileName] = useState("게시물에 추가"); + const [searchContent, setsearchContent] = useState('') + const searchedList = searchContent === "" ? diaryList : diaryList.filter((post) => + post.title.toLowerCase().includes(searchContent.toLowerCase()) === true + ) const handleModalOpen = () => { document.body.style.overflow = "hidden"; setIsModalOpen(true); }; + const handleSearch = (e) => { + const newValue = e.currentTarget.value; + setsearchContent(newValue); + } + useEffect(() => { const extractPageNumFromURL = () => { const urlParams = new URLSearchParams(currentURL) @@ -43,34 +52,42 @@ const Diary = () => { diary - - - - 페이지 당 게시물 개수 - setPageSize(1)}/> - - setPageSize(5)}/> - - setPageSize(10)}/> - - - {/** To do: 현재 서버의 일기장 리스트가 비어있는 관계로 /store/fakeDiary.js 의 가짜 데이터를 사용중, 추후 서버에 일기장 데이터 추가 시 변경 요망 */} - {diaryList.map((post) => ( - - {post.title} - {post.content || "내용이 없다"} - - ))} - - - {isModalOpen && ( - + + - )} + + + 페이지 당 게시물 개수 + setPageSize(1)}/> + + setPageSize(5)}/> + + setPageSize(10)}/> + + + {/** To do: 현재 서버의 일기장 리스트가 비어있는 관계로 /store/fakeDiary.js 의 가짜 데이터를 사용중, 추후 서버에 일기장 데이터 추가 시 변경 요망 */} + {searchedList.map((post) => ( + + {post.title} + {post.content || "내용이 없다"} + + ))} + + + {isModalOpen && ( + + )} + ) } @@ -80,6 +97,14 @@ export default Diary const StyledComponent = styled.div` `; +const PageBody = styled.div` + display: flex; + flex-direction: column; + width: 100vw; + align-items: center; + justify-content: center; +`; + const WritePostButton = styled.div` right: 10vw; bottom: 10vh; From 23b9312dd6d7e27d8e9389be4f09533e37e4f115 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 30 Jul 2023 19:47:54 +0900 Subject: [PATCH 11/23] =?UTF-8?q?[feat]:=20=EC=84=9C=EB=B2=84=EC=97=90=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C(=EC=84=9C=EB=B2=84=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=20api=20=EB=AF=B8=EA=B5=AC=ED=98=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 현재 api 명세에 적힌대로의 서버에 게시글 업로드 요청하는 기능 구현 --- src/components/diary/WritePostModal.js | 49 +++++++++++++++++++++++--- src/utils/axios.js | 19 ++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/components/diary/WritePostModal.js b/src/components/diary/WritePostModal.js index 53be4af..41eab95 100644 --- a/src/components/diary/WritePostModal.js +++ b/src/components/diary/WritePostModal.js @@ -1,14 +1,43 @@ -import React, { useRef } from "react"; +import React, { useRef, useState } from "react"; import styled from "styled-components"; import { ReactComponent as CloseIcon } from "../../assets/close_gray.svg"; import PostEditor from './PostEditor'; +import { uploadPost } from '../../utils/axios'; + +const POST_IS_EMPTY = "


" const WritePostModal = ({ setIsModalOpen, name}) => { const ref = useRef(null); + const [title, setTitle] = useState("") + const handleModalClose = () => { document.body.style.overflow = "unset"; setIsModalOpen(false); }; + const handleSubmit = async () => { + try{ + const editorlns = ref?.current?.getInstance(); + const content = editorlns.getHTML(); + const postData = `{ + "title" : ${title}, + "content" : ${content}, + "isAnonymous" : false, + "eventDate" : "2023-07-30 19:36:23", + "thumbnailIndex": ${0}, + }` + if (content === POST_IS_EMPTY) { + alert('내용을 입력해주세요'); + return + } + await uploadPost(postData); + } catch (e) { + console.log(e); + alert('다시 시도해주세요'); + return + } + setIsModalOpen(false); + } + return ( <> @@ -22,10 +51,12 @@ const WritePostModal = ({ setIsModalOpen, name}) => { {name} + 글 제목 + {setTitle(e.currentTarget.value)}}> - 게시물 올리기 + handleSubmit()}>게시물 올리기 @@ -52,7 +83,7 @@ const ModalBackground = styled.div` transition: .5s; `; -const ModalOutlay = styled.form` +const ModalOutlay = styled.div` position: relative; top: 0; left: 0; @@ -106,6 +137,16 @@ const ModalInner = styled.div` margin: 18px 45px 0px 45px; `; +const PostTitle = styled.input` + width: 670px; + outline: none; + border: none; + background: #fafafa; + font-size: 20px; + padding: 10px; + border-radius: 10px; +`; + const ModalFooter = styled.div` display: flex; justify-content: center; @@ -113,7 +154,7 @@ const ModalFooter = styled.div` margin: 56px 0px 45px 0px; `; -const SubmitButton = styled.div` +const SubmitButton = styled.button` display: flex; flex-direction: row; align-items: center; diff --git a/src/utils/axios.js b/src/utils/axios.js index 7cddac6..adefb28 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -25,3 +25,22 @@ export const getDiaryList = (cursor, size) => { } +export const uploadPost = (data) => { +let config = { + method: 'post', + maxBodyLength: Infinity, + url: 'https://khu-return.site/diary', + headers: { + 'Content-Type': 'multipart/form-data' + }, + data : data +}; + +axios.request(config) +.then((response) => { + console.log(JSON.stringify(response.data)); +}) +.catch((error) => { + console.log(error); +}); +} From 9e98c506f2558bb954722d42b3746c5e6a88a439 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Fri, 4 Aug 2023 02:31:04 +0900 Subject: [PATCH 12/23] =?UTF-8?q?[chore]:=20api=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=98=B8=EC=B6=9C=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/diary/WritePostModal.js | 2 +- src/pages/Diary.js | 2 +- src/utils/axios.js | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/diary/WritePostModal.js b/src/components/diary/WritePostModal.js index 41eab95..64e8b4e 100644 --- a/src/components/diary/WritePostModal.js +++ b/src/components/diary/WritePostModal.js @@ -21,7 +21,7 @@ const WritePostModal = ({ setIsModalOpen, name}) => { const postData = `{ "title" : ${title}, "content" : ${content}, - "isAnonymous" : false, + "isAnonymous" : ${false}, "eventDate" : "2023-07-30 19:36:23", "thumbnailIndex": ${0}, }` diff --git a/src/pages/Diary.js b/src/pages/Diary.js index 2b99abc..090e583 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -43,7 +43,7 @@ const Diary = () => { pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)) return parseInt(pageParam,10); } - getDiaryList(extractPageNumFromURL(), pageSize) + getDiaryList(extractPageNumFromURL(), "createdAt") setNumberOfPages((diaryList.length / pageSize) + 1) }, [currentURL, pageSize, diaryList.length]) diff --git a/src/utils/axios.js b/src/utils/axios.js index adefb28..1052503 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -1,16 +1,15 @@ import axios from 'axios'; + const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; - -export const getDiaryList = (cursor, size) => { +export const getDiaryList = (page, sort) => { /** * To do: GET /diary/list api가 변경되면 getDiaryList url cursor 부분 변경 요망 */ - const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; let config = { method: 'get', maxBodyLength: Infinity, - url: `https://khu-return.site/diary/list?cursor=${cursor}&size=${size}`, + url: `https://khu-return.site/diary?page=${page}&sort=${sort}`, headers: { 'Authorization': `${authorizationCode}`, } }; @@ -31,7 +30,8 @@ let config = { maxBodyLength: Infinity, url: 'https://khu-return.site/diary', headers: { - 'Content-Type': 'multipart/form-data' + 'Content-Type': 'multipart/form-data', + 'Authorization': `${authorizationCode}` }, data : data }; From 2ae515b0edf7a65c8ca5038ba2bd14bf95108645 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 6 Aug 2023 16:57:56 +0900 Subject: [PATCH 13/23] =?UTF-8?q?[feat]=20:=20=EC=A2=8B=EC=95=84=EC=9A=94,?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=EC=88=98,=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=20=EB=93=B1=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=84=B8?= =?UTF-8?q?=EB=B6=80=20=EC=A0=95=EB=B3=B4=20=ED=91=9C=EA=B8=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 게시글 목록이 디스플레이되는 화면에서 좋아요, 조회수, 댓글 수 등의 세부 정보가 표시되도록 변경 --- src/pages/Diary.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/pages/Diary.js b/src/pages/Diary.js index 090e583..a4a47ac 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -77,6 +77,11 @@ const Diary = () => { {post.title} {post.content || "내용이 없다"} + + 조회수 {post.viewCount} + 👍 {post.likeCount} + 댓글 {post.commentCount} + ))}
@@ -141,4 +146,21 @@ const DiaryBlock = styled.div` const Title = styled.div``; -const Content = styled.div``; \ No newline at end of file +const Content = styled.div``; + +const DiaryInfoBlock = styled.div` + display: flex; + justify-content: right; +`; + +const ViewCount = styled.div` + +`; + +const LikeCount = styled.div` + padding: 0 10px; +`; + +const CommentCount = styled.div` + padding: 0 10px; +`; \ No newline at end of file From 971e441b109dbb174414e9d79f50da30a7f21c04 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sun, 6 Aug 2023 17:31:51 +0900 Subject: [PATCH 14/23] =?UTF-8?q?[chore]=20:=20api=20url=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .env 처리 --- src/utils/axios.js | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/utils/axios.js b/src/utils/axios.js index 1052503..f7e02d7 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -1,6 +1,7 @@ import axios from 'axios'; - const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; +const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; +const API_URL = process.env.REACT_APP_API; export const getDiaryList = (page, sort) => { /** @@ -9,7 +10,7 @@ export const getDiaryList = (page, sort) => { let config = { method: 'get', maxBodyLength: Infinity, - url: `https://khu-return.site/diary?page=${page}&sort=${sort}`, + url: API_URL + `/diary?page=${page}&sort=${sort}`, headers: { 'Authorization': `${authorizationCode}`, } }; @@ -25,22 +26,23 @@ export const getDiaryList = (page, sort) => { } export const uploadPost = (data) => { -let config = { - method: 'post', - maxBodyLength: Infinity, - url: 'https://khu-return.site/diary', - headers: { - 'Content-Type': 'multipart/form-data', - 'Authorization': `${authorizationCode}` - }, - data : data -}; + let config = { + method: 'post', + maxBodyLength: Infinity, + url: API_URL + '/diary', + headers: { + 'Content-Type': 'multipart/form-data', + 'Authorization': `${authorizationCode}` + }, + data : data + }; -axios.request(config) -.then((response) => { - console.log(JSON.stringify(response.data)); -}) -.catch((error) => { - console.log(error); -}); + axios.request(config) + .then((response) => { + console.log(JSON.stringify(response.data)); + }) + .catch((error) => { + console.log(error); + }); } + From 28e570cbd8569d1263add8d5c188c66ea53f3f7d Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Tue, 15 Aug 2023 15:46:06 +0900 Subject: [PATCH 15/23] =?UTF-8?q?[feat]:=20=EB=8B=A4=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EB=A6=AC=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=A1=9C=EB=94=A9=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 다이어리 첫 페이지 로드 시, 게시글 페이지 변경 시 다이어리 게시글 리스트 로드하도록 서버와 연결 --- src/components/diary/PaginationBar.js | 4 -- src/pages/Diary.js | 35 ++++++++++------- src/utils/axios.js | 55 ++++++++++++++++++++++----- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/components/diary/PaginationBar.js b/src/components/diary/PaginationBar.js index 767284c..00c4b77 100644 --- a/src/components/diary/PaginationBar.js +++ b/src/components/diary/PaginationBar.js @@ -3,10 +3,6 @@ import { Link } from 'react-router-dom'; import styled from 'styled-components' const PaginationBar = ({currentPage, totalPages, setPage}) => { - const handlePageChange = (e) => { - const newPage = e.currentTarget.key; - setPage(newPage); - } const renderLinks = (totalPages) => { const links = []; for (let pageNum = 1; pageNum <= totalPages; pageNum++) { diff --git a/src/pages/Diary.js b/src/pages/Diary.js index a4a47ac..a86601a 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -1,22 +1,22 @@ import React, { useEffect, useState } from 'react' import styled from 'styled-components' import { ReactComponent as WriteIcon } from "../assets/pen.svg" -import { DiaryList } from '../store/fakeDiary' import PaginationBar from '../components/diary/PaginationBar' -import { useLocation } from 'react-router-dom' -import { getDiaryList } from '../utils/axios' +import { useLocation, useNavigate } from 'react-router-dom' +import { getDiaryDetail, getDiaryList } from '../utils/axios' import WritePostModal from '../components/diary/WritePostModal' import SearchBar from '../components/SearchBar' /** * To do - * 1. PageSizeRegulator, DiaryBlock 컴포넌트 분리, 추상화 요망 - * 2. 현재 fake data를 array method를 사용해 검색 기능을 구현한 상태. 추후 서버쪽 api 업데이트 되는대로 /diary?cursor={int}&size={int}&search={string} 사용할 것 + * 1. PageSizeRegulator, DiaryBlock 컴포넌트 분리, 추상화 요망 */ const Diary = () => { const currentURL = useLocation().search - const diaryList = [...DiaryList] + const navigate = useNavigate(); + const [diaryList, setDiaryList] = useState([]) + const [currentPage, setcurrentPage] = useState(1) const [pageSize, setPageSize] = useState(3) const [numberOfPages, setNumberOfPages] = useState() @@ -36,17 +36,26 @@ const Diary = () => { setsearchContent(newValue); } + const handlePostClick = async (post) => { + const postDetail = await getDiaryDetail(post.postId); + navigate(`/diary/${post.postId}`, { state : postDetail }) + } + useEffect(() => { const extractPageNumFromURL = () => { const urlParams = new URLSearchParams(currentURL) const pageParam = urlParams.get('page') - pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)) - return parseInt(pageParam,10); + !!pageParam && setcurrentPage(isNaN(parseInt(pageParam, 10)) ? 1 : parseInt(pageParam, 10)) + return currentPage; } - getDiaryList(extractPageNumFromURL(), "createdAt") + getDiaryList(extractPageNumFromURL(), "createdAt", setDiaryList) + }, [currentURL, currentPage, pageSize]) + + useEffect(() => { setNumberOfPages((diaryList.length / pageSize) + 1) - }, [currentURL, pageSize, diaryList.length]) + }, [diaryList.length, pageSize]) + return ( <> diary @@ -73,8 +82,8 @@ const Diary = () => { {/** To do: 현재 서버의 일기장 리스트가 비어있는 관계로 /store/fakeDiary.js 의 가짜 데이터를 사용중, 추후 서버에 일기장 데이터 추가 시 변경 요망 */} - {searchedList.map((post) => ( - + {searchedList ? (searchedList.map((post) => ( + {navigate(`/diary/${post.postId}`, { state : post })}}> {post.title} {post.content || "내용이 없다"} @@ -83,7 +92,7 @@ const Diary = () => { 댓글 {post.commentCount} - ))} + ))): "Loading"} {isModalOpen && ( diff --git a/src/utils/axios.js b/src/utils/axios.js index f7e02d7..72b897b 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -3,21 +3,18 @@ import axios from 'axios'; const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; const API_URL = process.env.REACT_APP_API; -export const getDiaryList = (page, sort) => { - /** - * To do: GET /diary/list api가 변경되면 getDiaryList url cursor 부분 변경 요망 - */ +export const getDiaryList = (page, sort, setDiaryList) => { let config = { method: 'get', maxBodyLength: Infinity, url: API_URL + `/diary?page=${page}&sort=${sort}`, headers: { - 'Authorization': `${authorizationCode}`, } + 'Authorization': `Bearer ${authorizationCode}`, + } }; - axios.request(config) .then((response) => { - console.log(JSON.stringify(response.data)); + setDiaryList(response.data) }) .catch((error) => { console.log(error); @@ -25,14 +22,16 @@ export const getDiaryList = (page, sort) => { } -export const uploadPost = (data) => { +export const uploadPost = (postData) => { + let data = new FormData(); + data.append(postData); let config = { method: 'post', maxBodyLength: Infinity, url: API_URL + '/diary', headers: { 'Content-Type': 'multipart/form-data', - 'Authorization': `${authorizationCode}` + 'Authorization': `Bearer ${authorizationCode}`, }, data : data }; @@ -46,3 +45,41 @@ export const uploadPost = (data) => { }); } +export const getDiaryDetail = (postId) => { + let config = { + method: 'get', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}`, + headers: { + 'Authorization': `Bearer ${authorizationCode}`, + } + }; + + axios.request(config) + .then((response) => { + console.log(JSON.stringify(response.data)); + }) + .catch((error) => { + console.log(error); + }); + +} + +export const getCommentList = (postId) => { + let config = { + method: 'get', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}/comment`, + headers: { + 'Authorization': `Bearer ${authorizationCode}`, + } + }; + + axios.request(config) + .then((response) => { + console.log(JSON.stringify(response.data)); + }) + .catch((error) => { + console.log(error); + }); +} \ No newline at end of file From b7803ecdd8b73d9b46c0a11980357e44cb9ab2bb Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Tue, 15 Aug 2023 20:34:44 +0900 Subject: [PATCH 16/23] =?UTF-8?q?[chore]=20:=20=EB=8B=A4=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EB=A6=AC=20=EC=9E=91=EC=84=B1=20=EC=96=91=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 서버 api 명세에 따라 양식 수정 --- src/components/diary/WritePostModal.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/diary/WritePostModal.js b/src/components/diary/WritePostModal.js index 64e8b4e..c5a706d 100644 --- a/src/components/diary/WritePostModal.js +++ b/src/components/diary/WritePostModal.js @@ -18,13 +18,13 @@ const WritePostModal = ({ setIsModalOpen, name}) => { try{ const editorlns = ref?.current?.getInstance(); const content = editorlns.getHTML(); - const postData = `{ - "title" : ${title}, - "content" : ${content}, - "isAnonymous" : ${false}, + const postData = { + "title" : title, + "content" : content, + "isAnonymous" : true, "eventDate" : "2023-07-30 19:36:23", - "thumbnailIndex": ${0}, - }` + "thumbnailIndex": 0, + } if (content === POST_IS_EMPTY) { alert('내용을 입력해주세요'); return From 00b5182c91f3a637120813a2ecf213dc33cf9955 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Tue, 15 Aug 2023 20:35:51 +0900 Subject: [PATCH 17/23] =?UTF-8?q?[feat]=20:=20=EB=8B=A4=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EB=A6=AC=20=EC=83=81=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EB=9D=BC=EC=9A=B0=ED=8C=85,=20ui=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 다이어리 상세 페이지 라우팅, ui 작업 --- src/App.js | 2 + src/pages/Diary.js | 64 +++++++++++--- src/pages/DiaryDetail.js | 176 +++++++++++++++++++++++++++++++++++++++ src/utils/axios.js | 8 +- 4 files changed, 235 insertions(+), 15 deletions(-) create mode 100644 src/pages/DiaryDetail.js diff --git a/src/App.js b/src/App.js index 31baa88..26929a0 100644 --- a/src/App.js +++ b/src/App.js @@ -3,6 +3,7 @@ import GlobalStyle from './styles/globalStyle'; import Landing from './pages/Landing'; import SignIn from './pages/SignIn'; import Diary from './pages/Diary'; +import DiaryDetail from './pages/DiaryDetail'; const App = () => { return ( @@ -12,6 +13,7 @@ const App = () => { } /> } /> } /> + } /> diff --git a/src/pages/Diary.js b/src/pages/Diary.js index a86601a..e74884f 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -38,7 +38,7 @@ const Diary = () => { const handlePostClick = async (post) => { const postDetail = await getDiaryDetail(post.postId); - navigate(`/diary/${post.postId}`, { state : postDetail }) + } useEffect(() => { @@ -81,16 +81,25 @@ const Diary = () => { setPageSize(10)}/> - {/** To do: 현재 서버의 일기장 리스트가 비어있는 관계로 /store/fakeDiary.js 의 가짜 데이터를 사용중, 추후 서버에 일기장 데이터 추가 시 변경 요망 */} - {searchedList ? (searchedList.map((post) => ( - {navigate(`/diary/${post.postId}`, { state : post })}}> - {post.title} - {post.content || "내용이 없다"} - - 조회수 {post.viewCount} - 👍 {post.likeCount} - 댓글 {post.commentCount} - + {searchedList ? (searchedList.map((diary) => ( + {getDiaryDetail(diary.diaryId, navigate)}}> + + + + + {diary.title} + + + + + {diary.member.name} + + + 조회수 {diary.viewCount} + 👍 {diary.likeCount} + 댓글 {diary.commentCount} + + ))): "Loading"} @@ -148,15 +157,44 @@ const PageSizeRegulator = styled.div``; const RegulatorButton = styled.input``; const DiaryBlock = styled.div` - width: 300px; + width: 800px; margin: auto; border : 1px solid `; +const DiaryHeader = styled.div` + display: flex; + align-items: center; +`; + +const DiaryBody = styled.div` + display: flex; + justify-content: right; +`; + const Title = styled.div``; -const Content = styled.div``; +const ThumbnailBox = styled.div` + width: 64px; + height: 64px; + background: #f1f1f1; + margin: 10px; +`; + +const ThumbnailImg = styled.img` + width: 64px; + height: 64px; + object-fit: cover; +`; + +const AuthorBlock = styled.div` + display: flex; + margin-right: 10px; +`; + +const AuthorProfileImg = styled.img``; +const Author = styled.div``; const DiaryInfoBlock = styled.div` display: flex; justify-content: right; diff --git a/src/pages/DiaryDetail.js b/src/pages/DiaryDetail.js new file mode 100644 index 0000000..5439e1e --- /dev/null +++ b/src/pages/DiaryDetail.js @@ -0,0 +1,176 @@ +import React, { useEffect, useState } from 'react' +import { useLocation } from 'react-router-dom' +import styled from 'styled-components' +import { getCommentList } from '../utils/axios'; + +const DiaryDetail = () => { + const location = useLocation(); + const { state } = location; + const diary = state; + const [commentList, setCommentList] = useState([]); + const devCommentList = [ + { + "commentId": 1, + "content": "리턴 커뮤니티 다이어리 댓글", + "likeCount": 3, + "recommentCount": 1, + "user": { + "userId" : 1, + "profileImgURL": "", + "name": "김수한무", + }, + "isLiked": true, + "createdDate": "2023-08-13" + }, + { + "commentId": 2, + "content": "리턴 커뮤니티 다이어리 댓글", + "likeCount": 3, + "recommentCount": 1, + "user": { + "userId" : 1, + "profileImgURL": "", + "name": "김수한무", + }, + "isLiked": true, + "createdDate": "2023-08-13" + } +]; + useEffect(() => { + //const newComments = getCommentList(post.postId); + //setCommentList(newComments) + }, [diary.diaryId]) + + return ( + <> + diary-detail + + + {diary.title} + + 작성 일자 : {diary.createdDate.slice(0, -7)} + 수정 일자 : {diary.modifiedDate.slice(0, -7)} + + + + {diary.content} + + + + + {!!devCommentList.length && devCommentList.map((comment) => + +
+ + {comment.user.name} +
+ + {comment.content} + 댓글작성 + +
)} +
+
+
+ + ) +} + +export default DiaryDetail + +const PageBody = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + font-family: Pretendard; +`; + +const DiaryHeader = styled.div` + display: flex; + justify-content: space-between; + width: 886px; + border-bottom: 1px solid; + font-size: 1.5rem; +`; + +const DateContainer = styled.div``; + +const DateInfo = styled.div` + font-size: 0.8rem; +`; + +const DiaryBody = styled.div` + width: 886px; + min-height: 400px; + padding: 10px; +`; + +const Title = styled.div` +`; + +const DiaryContent = styled.div` +`; + +const DiaryCommentContainer = styled.div` + display: flex; + flex-direction: column; + width: 100vw; + justify-content: center; + align-items: center; +`; + +const CommentInput = styled.textarea` + width: 886px; + height: 100px; + border: none; + resize: none; + outline: none; + background: #f1f1f1; + padding: 10px; + font-family: Pretendard; +`; + +const CommentsContainer = styled.div` +`; + +const Comment = styled.div` + margin-top: 34px; + width: 886px; +`; + +const Header = styled.div` + display: flex; + height: 16px; + align-items: center; +`; +const ProfileImg = styled.div` + width: 18px; + height: 18px; + border-radius: 100px; + background: #d2d2d2; +`; +const Name = styled.div` + height: 16px; + margin-left: 5px; + font-family: Pretendard; + font-style: normal; + font-weight: bold; + font-size: 16px; + line-height: 16px; + color: #313338; +`; +const Body = styled.div` + margin: 5px 0px 0px 23px; +`; +const Content = styled.div` + font-family: Pretendard; + font-style: normal; + font-weight: 500; + font-size: 13px; + line-height: 21px; +`; +const WriteButton = styled(Content)` + color: #8b8b8b; + cursor: pointer; +`; \ No newline at end of file diff --git a/src/utils/axios.js b/src/utils/axios.js index 72b897b..5089966 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -1,8 +1,10 @@ import axios from 'axios'; +import { useNavigate } from 'react-router-dom'; const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; const API_URL = process.env.REACT_APP_API; + export const getDiaryList = (page, sort, setDiaryList) => { let config = { method: 'get', @@ -45,11 +47,11 @@ export const uploadPost = (postData) => { }); } -export const getDiaryDetail = (postId) => { +export const getDiaryDetail = (diaryId, navigate) => { let config = { method: 'get', maxBodyLength: Infinity, - url: API_URL + `/diary/${postId}`, + url: API_URL + `/diary/${diaryId}`, headers: { 'Authorization': `Bearer ${authorizationCode}`, } @@ -58,6 +60,8 @@ export const getDiaryDetail = (postId) => { axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); + const diary = response.data + navigate(`/diary/${diary.diaryId}`, { state : diary }) }) .catch((error) => { console.log(error); From 786683b3a4d8eacbea3a589093111b8b00742996 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Wed, 16 Aug 2023 21:30:52 +0900 Subject: [PATCH 18/23] =?UTF-8?q?[feat]=20:=20=EB=8B=A4=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EB=A6=AC=20=EC=83=81=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?:=20=EB=8C=93=EA=B8=80=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 댓글 작성 : 작성 후 페이지 리로드, 결과 확인 가능, 작성 경과 시간 표기 2. 댓글 수정 : 해당 댓글 위치에 수정 ui 위치, 수정 후 페이지 리로드, 결과 확인 가능 3. 댓글 삭제 : 해당 댓글 삭제 후 페이지 리로드, 결과 확인 가능 4. 댓글 총 개수 표기 --- src/assets/paper_plane.svg | 3 + src/pages/Diary.js | 13 ++- src/pages/DiaryDetail.js | 225 +++++++++++++++++++++++++++++-------- src/utils/DateConverter.js | 25 +++++ src/utils/axios.js | 67 ++++++++++- 5 files changed, 281 insertions(+), 52 deletions(-) create mode 100644 src/assets/paper_plane.svg create mode 100644 src/utils/DateConverter.js diff --git a/src/assets/paper_plane.svg b/src/assets/paper_plane.svg new file mode 100644 index 0000000..7d797e5 --- /dev/null +++ b/src/assets/paper_plane.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/pages/Diary.js b/src/pages/Diary.js index e74884f..f3662d5 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -15,6 +15,7 @@ import SearchBar from '../components/SearchBar' const Diary = () => { const currentURL = useLocation().search const navigate = useNavigate(); + const STATIC_URL = process.env.REACT_APP_API; const [diaryList, setDiaryList] = useState([]) const [currentPage, setcurrentPage] = useState(1) @@ -85,13 +86,13 @@ const Diary = () => { {getDiaryDetail(diary.diaryId, navigate)}}> - + {diary.title} - + {diary.member.name} @@ -189,10 +190,16 @@ const ThumbnailImg = styled.img` const AuthorBlock = styled.div` display: flex; + align-items: center; margin-right: 10px; `; -const AuthorProfileImg = styled.img``; +const AuthorProfileImg = styled.img` + width: 20px; + height: 20px; + margin-right: 5px; + border-radius: 100px; +`; const Author = styled.div``; const DiaryInfoBlock = styled.div` diff --git a/src/pages/DiaryDetail.js b/src/pages/DiaryDetail.js index 5439e1e..442a93b 100644 --- a/src/pages/DiaryDetail.js +++ b/src/pages/DiaryDetail.js @@ -1,46 +1,50 @@ import React, { useEffect, useState } from 'react' import { useLocation } from 'react-router-dom' import styled from 'styled-components' -import { getCommentList } from '../utils/axios'; +import { deleteComment, editComment, getCommentList, postComment } from '../utils/axios'; +import DateConverter from '../utils/DateConverter'; +import { ReactComponent as SendIcon } from "../assets/paper_plane.svg"; +import { ReactComponent as CloseIcon } from "../assets/close_gray.svg"; + const DiaryDetail = () => { const location = useLocation(); const { state } = location; const diary = state; const [commentList, setCommentList] = useState([]); - const devCommentList = [ - { - "commentId": 1, - "content": "리턴 커뮤니티 다이어리 댓글", - "likeCount": 3, - "recommentCount": 1, - "user": { - "userId" : 1, - "profileImgURL": "", - "name": "김수한무", - }, - "isLiked": true, - "createdDate": "2023-08-13" - }, - { - "commentId": 2, - "content": "리턴 커뮤니티 다이어리 댓글", - "likeCount": 3, - "recommentCount": 1, - "user": { - "userId" : 1, - "profileImgURL": "", - "name": "김수한무", - }, - "isLiked": true, - "createdDate": "2023-08-13" - } -]; + const [commentData, setCommentData] = useState({"content" : "", "hashtagList" : []}); + const [editingCommentId, setEditingCommentId] = useState(null); + const [editedComment, setEditedComment] = useState(""); + const INPUT_IS_EMPTY = commentData.content === "" + const STATIC_URL = process.env.REACT_APP_API; + useEffect(() => { - //const newComments = getCommentList(post.postId); - //setCommentList(newComments) + getCommentList(diary.diaryId, setCommentList); }, [diary.diaryId]) - + + const handleInput = (e) => { + const newData = {...commentData, "content" : `${e.currentTarget.value}`}; + setCommentData(newData); + } + + const handleEdit = (e) => { + const newComment = e.currentTarget.value; + setEditedComment(newComment); + } + + const handlePostComment = (diaryId, commentData) => { + !INPUT_IS_EMPTY && postComment(diaryId, commentData) + } + + const handleEditClick = (commentId, initialComment) => { + setEditingCommentId(commentId); + setEditedComment(initialComment); + } + + const handleSaveClick = (diaryId, commentId) => { + editComment(diaryId, commentId, editedComment); + } + return ( <> diary-detail @@ -54,21 +58,45 @@ const DiaryDetail = () => { {diary.content} + {editingCommentId} - + + + + handlePostComment(diary.diaryId, commentData)}/> + + - {!!devCommentList.length && devCommentList.map((comment) => - -
- - {comment.user.name} -
- - {comment.content} - 댓글작성 - -
)} + 댓글 {commentList.length} + {!!commentList.length && commentList.map((comment) => +
+ {comment.commentId === editingCommentId ? ( + + + setEditingCommentId(null)}/> + handleSaveClick(diary.diaryId, comment.commentId)}/> + + ) : ( + +
+ + {comment.user.name} + {DateConverter(comment.createdDate)} +
+ + {comment.content} + + 👍 {comment.likeCount} + 댓글작성 + + + handleEditClick(comment.commentId, comment.content)}>수정 + deleteComment(diary.diaryId, comment.commentId)}>삭제 +
+ )} +
+ )}
@@ -120,31 +148,106 @@ const DiaryCommentContainer = styled.div` align-items: center; `; -const CommentInput = styled.textarea` +const CommentInputContainer = styled.div` + display: flex; + justify-content: space-between; + align-items: center; width: 886px; height: 100px; border: none; + border-radius: 100px; + background: #f1f1f1; + padding: 50px; + font-family: Pretendard; + .input::-webkit-scrollbar { + display: none; +} +`; + +const CommentInput = styled.textarea` + width: 750px; + height: 100px; + border: none; resize: none; outline: none; + align-items: center; background: #f1f1f1; padding: 10px; + font-size: 1rem; font-family: Pretendard; `; +const IconContainer = styled.div` + display: flex; + justify-content: center; + .deactivate { + fill: #8b8b8b; + } + .activate { + fill: #313338; + cursor: pointer; + } +`; + const CommentsContainer = styled.div` `; +const CommentCount = styled.div` + margin: 10px 0px 0px 20px; + font-weight: bold; + font-size: 1.2rem; +`; + +const CommentEditOutlay = styled.div` + width: 886px; + margin: 20px 0px 50px 0px; + border-bottom: 1px solid; + position: relative; + .Icon { + position: absolute; + right: 10px; + bottom: -30px; + cursor: pointer; + } + .close{ + right: 50px; + } + .deactivate { + fill: #8b8b8b; + } + .activate { + fill: #313338; + cursor: pointer; + } + .input::-webkit-scrollbar { + display: none; +} +`; + const Comment = styled.div` + position: relative; margin-top: 34px; width: 886px; `; +const CommentEditInput = styled.textarea` + width: 800px; + min-height: 20px; + overflow-y: scroll; + border: none; + resize: none; + outline: none; + align-items: center; + font-size: 1rem; + font-family: Pretendard; +`; + const Header = styled.div` display: flex; height: 16px; align-items: center; `; -const ProfileImg = styled.div` +const ProfileImg = styled.img` width: 18px; height: 18px; border-radius: 100px; @@ -160,6 +263,13 @@ const Name = styled.div` line-height: 16px; color: #313338; `; + +const WrittenTime = styled.div` + margin-left: 10px; + font-size: 0.8rem; + color: #8b8b8b; +`; + const Body = styled.div` margin: 5px 0px 0px 23px; `; @@ -170,7 +280,30 @@ const Content = styled.div` font-size: 13px; line-height: 21px; `; + +const InfoBox = styled.div` + display: flex; +`; + +const RecommendCount = styled.div` + margin-right: 10px; +`; + const WriteButton = styled(Content)` color: #8b8b8b; cursor: pointer; +`; + +const EditButton = styled.div` + position: absolute; + right: 50px; + top: 0px; + cursor: pointer; +`; + +const DeleteButton = styled.div` + position: absolute; + right: 10px; + top: 0px; + cursor: pointer; `; \ No newline at end of file diff --git a/src/utils/DateConverter.js b/src/utils/DateConverter.js new file mode 100644 index 0000000..70486cc --- /dev/null +++ b/src/utils/DateConverter.js @@ -0,0 +1,25 @@ +const DateConverter = (dateString) => { + const dateTime = new Date(dateString); + const currentTime = new Date(); + const timeDifference = currentTime - dateTime; + + const seconds = Math.floor(timeDifference / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + const years = Math.floor(days / 365); + + if (years > 0) { + return `${years}년 전`; + } else if (days > 0) { + return `${days}일 전`; + } else if (hours > 0) { + return `${hours}시간 전`; + } else if (minutes > 0) { + return`${minutes}분 전`; + } else { + return`${seconds}초 전`; + } +}; + +export default DateConverter; diff --git a/src/utils/axios.js b/src/utils/axios.js index 5089966..f278ce0 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -1,5 +1,4 @@ import axios from 'axios'; -import { useNavigate } from 'react-router-dom'; const authorizationCode = process.env.REACT_APP_AUTHORIZATIONCODE; const API_URL = process.env.REACT_APP_API; @@ -16,6 +15,7 @@ export const getDiaryList = (page, sort, setDiaryList) => { }; axios.request(config) .then((response) => { + console.log(response.data) setDiaryList(response.data) }) .catch((error) => { @@ -69,7 +69,7 @@ export const getDiaryDetail = (diaryId, navigate) => { } -export const getCommentList = (postId) => { +export const getCommentList = (postId, setCommentList) => { let config = { method: 'get', maxBodyLength: Infinity, @@ -81,7 +81,68 @@ export const getCommentList = (postId) => { axios.request(config) .then((response) => { - console.log(JSON.stringify(response.data)); + setCommentList(response.data); + }) + .catch((error) => { + console.log(error); + }); +} + +export const postComment = (postId, data) => { + let config = { + method: 'post', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}/comment`, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authorizationCode}`, + }, + data : JSON.stringify(data) + }; + axios.request(config) + .then(() => { + alert("댓글이 등록되었습니다.") + window.location.reload(); + }) + .catch((error) => { + console.log(error); + }); +} + +export const editComment = (postId, commentId, data) => { + let config = { + method: 'patch', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}/comment/${commentId}`, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authorizationCode}`, + }, + data : JSON.stringify({data}) + }; + axios.request(config) + .then(() => { + alert("댓글이 수정되었습니다.") + window.location.reload(); + }) + .catch((error) => { + console.log(error); + }); +} + +export const deleteComment = (postId, commentId) => { + let config = { + method: 'delete', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}/comment/${commentId}`, + headers: { + 'Authorization': `Bearer ${authorizationCode}`, + } + }; + axios.request(config) + .then(() => { + alert("댓글이 삭제되었습니다.") + window.location.reload(); }) .catch((error) => { console.log(error); From d3b6ced7e98ae8fc0e8d0b95fac0cc502289a54c Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Wed, 6 Sep 2023 21:36:27 +0900 Subject: [PATCH 19/23] =?UTF-8?q?refactor:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EA=B0=9C=EC=88=98=20=ED=91=9C=EA=B8=B0=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RecommentCountIndicator 컴포넌트화, Diary.js 에서 분리 --- .../diarydetail/RecommentCountIndicator.js | 46 +++++++++++++++++++ src/pages/Diary.js | 22 +++++---- 2 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 src/components/diarydetail/RecommentCountIndicator.js diff --git a/src/components/diarydetail/RecommentCountIndicator.js b/src/components/diarydetail/RecommentCountIndicator.js new file mode 100644 index 0000000..c95b94e --- /dev/null +++ b/src/components/diarydetail/RecommentCountIndicator.js @@ -0,0 +1,46 @@ +import React from 'react' +import styled from 'styled-components' +import { ReactComponent as DirectionIcon } from "../../assets/Triangle.svg"; + +const RecommentCountIndicator = ({comment, extendingCommentId, onClick}) => { + return ( + <> + onClick(comment.commentId)}> {/** */} + + + 답글 {comment.recomments.length} 개 + + + + ) +} + +export default RecommentCountIndicator + +const Wrapper = styled.div` + display: flex; + align-items: center; + height: 20px; +`; + +const RecommentCount = styled.div` + text-align: center; + padding-left: 10px; +`; + + +const IconContainer = styled.div` + display: flex; + justify-content: center; + .deactivate { + fill: #8b8b8b; + } + .activate { + fill: #313338; + cursor: pointer; + } + .open { + transform: rotate(180deg); + transition: .5s; + } +`; \ No newline at end of file diff --git a/src/pages/Diary.js b/src/pages/Diary.js index f3662d5..3e3c861 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -75,18 +75,18 @@ const Diary = () => { 페이지 당 게시물 개수 - setPageSize(1)}/> - - setPageSize(5)}/> - - setPageSize(10)}/> - + setPageSize(1)}/> + + setPageSize(5)}/> + + setPageSize(10)}/> + {searchedList ? (searchedList.map((diary) => ( - {getDiaryDetail(diary.diaryId, navigate)}}> + {getDiaryDetail(diary.diaryId, navigate)}}> - + {diary.thumbnailImgURL ? : } {diary.title} @@ -188,6 +188,12 @@ const ThumbnailImg = styled.img` object-fit: cover; `; +const EmptyThumbnailImg = styled.div` + width: 64px; + height: 64px; + background: #f1f1f1 +`; + const AuthorBlock = styled.div` display: flex; align-items: center; From f4eb7aa1d2b83119b61339e5ccc68288876b6b2e Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Wed, 6 Sep 2023 21:37:44 +0900 Subject: [PATCH 20/23] =?UTF-8?q?[feat]:=20=EB=8C=93=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1,=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=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 - 댓글 작성, 수정 기능 서버와 연동 - 수정 시 해당 댓글 위치에 수정 UI 위치하도록 구현 --- src/assets/Triangle.svg | 3 + src/components/diary/PostEditor.js | 2 +- src/pages/DiaryDetail.js | 229 ++++++++++++++++++++++++----- src/utils/axios.js | 50 +++++++ 4 files changed, 245 insertions(+), 39 deletions(-) create mode 100644 src/assets/Triangle.svg diff --git a/src/assets/Triangle.svg b/src/assets/Triangle.svg new file mode 100644 index 0000000..30246d7 --- /dev/null +++ b/src/assets/Triangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/diary/PostEditor.js b/src/components/diary/PostEditor.js index 9146698..2855506 100644 --- a/src/components/diary/PostEditor.js +++ b/src/components/diary/PostEditor.js @@ -15,7 +15,7 @@ const PostEditor = ({editorRef}) => { <> { const location = useLocation(); @@ -15,6 +15,8 @@ const DiaryDetail = () => { const [commentData, setCommentData] = useState({"content" : "", "hashtagList" : []}); const [editingCommentId, setEditingCommentId] = useState(null); const [editedComment, setEditedComment] = useState(""); + const [extendingCommentId, setExtendingCommentId] = useState(null); + const [writingRecommentId, setWritingRecommentId] = useState(); const INPUT_IS_EMPTY = commentData.content === "" const STATIC_URL = process.env.REACT_APP_API; @@ -41,8 +43,27 @@ const DiaryDetail = () => { setEditedComment(initialComment); } - const handleSaveClick = (diaryId, commentId) => { - editComment(diaryId, commentId, editedComment); + const handleRecommentClick = (commentId) => { + extendingCommentId !== commentId ? setExtendingCommentId(commentId) : setExtendingCommentId(null); + } + + const handleSaveClick = (diaryId, commentId, type) => { + switch (type){ + default: + setEditingCommentId(null); + break; + case "editComment": + editComment(diaryId, commentId, editedComment); + break; + case "recomment": + postRecomment(diaryId, commentId, editedComment); + break; + case "editRecomment": + editRecomment(diaryId, commentId.commentId, commentId.recommentId, editedComment); + break; + } + setEditingCommentId(null); + setEditedComment(""); } return ( @@ -50,23 +71,40 @@ const DiaryDetail = () => { diary-detail - {diary.title} - - 작성 일자 : {diary.createdDate.slice(0, -7)} - 수정 일자 : {diary.modifiedDate.slice(0, -7)} - + + {diary.title} + + 작성 일자 : {diary.createdDate.slice(0, -7)} + 수정 일자 : {diary.modifiedDate.slice(0, -7)} + + + + + + {diary.member.name} + + + 수정 + 삭제 + + {diary.content} - {editingCommentId} - - + + - handlePostComment(diary.diaryId, commentData)}/> + handlePostComment(diary.diaryId, commentData)}/> - + 댓글 {commentList.length} {!!commentList.length && commentList.map((comment) => @@ -74,26 +112,78 @@ const DiaryDetail = () => { {comment.commentId === editingCommentId ? ( - setEditingCommentId(null)}/> - handleSaveClick(diary.diaryId, comment.commentId)}/> + setEditingCommentId(null)}/> + handleSaveClick(diary.diaryId, comment.commentId)}/> - ) : ( - -
- - {comment.user.name} - {DateConverter(comment.createdDate)} -
- - {comment.content} - - 👍 {comment.likeCount} - 댓글작성 - - - handleEditClick(comment.commentId, comment.content)}>수정 - deleteComment(diary.diaryId, comment.commentId)}>삭제 -
+ ) : ( + + +
+ + {comment.user.name} + {DateConverter(comment.createdDate)} +
+ + {comment.content} + + 👍 {comment.likeCount} + setWritingRecommentId(comment.commentId)}>댓글작성 + + + handleEditClick(comment.commentId, comment.content)}>수정 + deleteComment(diary.diaryId, comment.commentId)}>삭제 +
+ {writingRecommentId === comment.commentId && ( + + + setWritingRecommentId(null)}/> + handleSaveClick(diary.diaryId, comment.commentId, "recomment")}/> + + )} + {!!comment.recomments.length && ( + + )} + + {comment.recomments.map((recomment) => + (recomment.recommentId === editingCommentId ? ( + + + setEditingCommentId(null)}/> + handleSaveClick(diary.diaryId, {commentId: comment.commentId, recommentId: recomment.recommentId}, "editRecomment")}/> + + ) : ( + +
+ + {recomment.user.name} + {DateConverter(recomment.createdDate)} +
+ + {recomment.content} + + handleEditClick(recomment.recommentId, recomment.content)}>수정 + deleteComment(diary.diaryId, recomment.recommentId)}>삭제 +
+ )) + )} +
+
)} )} @@ -116,12 +206,55 @@ const PageBody = styled.div` const DiaryHeader = styled.div` display: flex; - justify-content: space-between; + flex-direction: column; width: 886px; border-bottom: 1px solid; font-size: 1.5rem; `; +const TitleLine = styled.div` + display: flex; + justify-content: space-between; +`; + +const AuthorLine = styled.div` + display: flex; + justify-content: space-between; + align-items: center; +`; + +const AuthorInfoContaienr = styled.div` + display: flex; + justify-contetn: center; + align-items: center; +`; + +const AuthorProfileImg = styled.img` + width: 20px; + height: 20px; + margin-right: 5px; + border-radius: 100px; +`; + +const Author = styled.div` + font-size: 1rem; +`; + +const EditDeleteConsole = styled.div` + display: flex; + justify-contetn: center; + align-items: center; + font-size: .9rem; +`; + +const EditButton = styled.div` + padding: 6px; + cursor: pointer; +`; + +const DeleteButton = styled(EditButton)` +`; + const DateContainer = styled.div``; const DateInfo = styled.div` @@ -148,7 +281,7 @@ const DiaryCommentContainer = styled.div` align-items: center; `; -const CommentInputContainer = styled.div` +const CommentInputOutlay = styled.div` display: flex; justify-content: space-between; align-items: center; @@ -187,6 +320,10 @@ const IconContainer = styled.div` fill: #313338; cursor: pointer; } + .open { + transform: rotate(180deg); + transition: .5s; + } `; const CommentsContainer = styled.div` @@ -224,6 +361,12 @@ const CommentEditOutlay = styled.div` } `; +const CommentOutlay = styled.div` + .invisible { + display: none; + } +`; + const Comment = styled.div` position: relative; margin-top: 34px; @@ -294,16 +437,26 @@ const WriteButton = styled(Content)` cursor: pointer; `; -const EditButton = styled.div` +const EditCommentButton = styled.div` position: absolute; right: 50px; top: 0px; cursor: pointer; `; -const DeleteButton = styled.div` +const DeleteCommentButton = styled.div` position: absolute; right: 10px; top: 0px; cursor: pointer; -`; \ No newline at end of file +`; + +const RecommentInputOutlay = styled(CommentEditOutlay)``; + +const RecommentInput = styled(CommentEditInput)``; + +const RecommentList = styled.div` + margin-left: 20px; +`; + +const Recomment = styled(Comment)``; \ No newline at end of file diff --git a/src/utils/axios.js b/src/utils/axios.js index f278ce0..23a6f95 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -147,4 +147,54 @@ export const deleteComment = (postId, commentId) => { .catch((error) => { console.log(error); }); +} + +export const postRecomment = (postId, commentId, content) => { + let data = JSON.stringify({ + "content": `${content}` + }); + +let config = { + method: 'post', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}/comment/${commentId}/recomment`, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authorizationCode}`, + }, + data : data +}; + +axios.request(config) +.then((response) => { + alert("댓글이 작성되었습니다.") + window.location.reload(); +}) +.catch((error) => { + console.log(error); +}); +} + +export const editRecomment = (postId, commentId, recommentId, content) => { + let data = JSON.stringify({ + "content": `${content}` + }); + let config = { + method: 'patch', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}/comment/${commentId}/recomment/${recommentId}`, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authorizationCode}`, + }, + data : data, + }; + axios.request(config) + .then(() => { + alert("댓글이 수정되었습니다.") + window.location.reload(); + }) + .catch((error) => { + console.log(error); + }); } \ No newline at end of file From cb9e38223dc48919148e1aa7f0ca47e6149743a4 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Wed, 13 Sep 2023 19:11:38 +0900 Subject: [PATCH 21/23] =?UTF-8?q?[feat]:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/diary/WritePostModal.js | 5 ++--- src/utils/axios.js | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/components/diary/WritePostModal.js b/src/components/diary/WritePostModal.js index c5a706d..ac541f8 100644 --- a/src/components/diary/WritePostModal.js +++ b/src/components/diary/WritePostModal.js @@ -14,7 +14,7 @@ const WritePostModal = ({ setIsModalOpen, name}) => { document.body.style.overflow = "unset"; setIsModalOpen(false); }; - const handleSubmit = async () => { + const handleSubmit = () => { try{ const editorlns = ref?.current?.getInstance(); const content = editorlns.getHTML(); @@ -22,14 +22,13 @@ const WritePostModal = ({ setIsModalOpen, name}) => { "title" : title, "content" : content, "isAnonymous" : true, - "eventDate" : "2023-07-30 19:36:23", "thumbnailIndex": 0, } if (content === POST_IS_EMPTY) { alert('내용을 입력해주세요'); return } - await uploadPost(postData); + uploadPost(postData); } catch (e) { console.log(e); alert('다시 시도해주세요'); diff --git a/src/utils/axios.js b/src/utils/axios.js index 23a6f95..f19a00d 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -26,7 +26,8 @@ export const getDiaryList = (page, sort, setDiaryList) => { export const uploadPost = (postData) => { let data = new FormData(); - data.append(postData); + data.append('data', JSON.stringify(postData)); + data.append('mediaList', null); let config = { method: 'post', maxBodyLength: Infinity, @@ -35,7 +36,7 @@ export const uploadPost = (postData) => { 'Content-Type': 'multipart/form-data', 'Authorization': `Bearer ${authorizationCode}`, }, - data : data + data :data }; axios.request(config) @@ -47,6 +48,25 @@ export const uploadPost = (postData) => { }); } +export const deletePost = (postId) => { + let config = { + method: 'delete', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}`, + headers: { + 'Authorization': `Bearer ${authorizationCode}`, + } + }; + axios.request(config) + .then(() => { + alert("게시글이 삭제되었습니다.") + window.location.href="/diary" + }) + .catch((error) => { + console.log(error); + }); +} + export const getDiaryDetail = (diaryId, navigate) => { let config = { method: 'get', From 5b5e95a53da56d6c23d9bc45dfafd4d2a886644c Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sat, 23 Sep 2023 21:10:05 +0900 Subject: [PATCH 22/23] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 수정, 삭제 api 연동 수정 UI 적용 --- src/pages/DiaryDetail.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pages/DiaryDetail.js b/src/pages/DiaryDetail.js index 71c9d8a..bbad622 100644 --- a/src/pages/DiaryDetail.js +++ b/src/pages/DiaryDetail.js @@ -1,11 +1,12 @@ import React, { useEffect, useState } from 'react' import { useLocation } from 'react-router-dom' import styled from 'styled-components' -import { deleteComment, editComment, editRecomment, getCommentList, postComment, postRecomment } from '../utils/axios'; +import { deleteComment, deletePost, editComment, editRecomment, getCommentList, postComment, postRecomment } from '../utils/axios'; import DateConverter from '../utils/DateConverter'; import { ReactComponent as SendIcon } from "../assets/paper_plane.svg"; import { ReactComponent as CloseIcon } from "../assets/close_gray.svg"; import RecommentCountIndicator from '../components/diarydetail/RecommentCountIndicator'; +import WritePostModal from '../components/diary/WritePostModal'; const DiaryDetail = () => { const location = useLocation(); @@ -17,6 +18,7 @@ const DiaryDetail = () => { const [editedComment, setEditedComment] = useState(""); const [extendingCommentId, setExtendingCommentId] = useState(null); const [writingRecommentId, setWritingRecommentId] = useState(); + const [isEditingPost, setIsEditingPost] = useState(false); const INPUT_IS_EMPTY = commentData.content === "" const STATIC_URL = process.env.REACT_APP_API; @@ -84,8 +86,8 @@ const DiaryDetail = () => { {diary.member.name} - 수정 - 삭제 + setIsEditingPost(true)}>수정 + deletePost(diary.diaryId)}>삭제 @@ -190,6 +192,7 @@ const DiaryDetail = () => {
+ {isEditingPost && } ) } From 466dd2a1d2499ec29407b95fc342e0f15f71a386 Mon Sep 17 00:00:00 2001 From: MrMirror21 <49388937+MrMirror21@users.noreply.github.com> Date: Sat, 23 Sep 2023 21:10:17 +0900 Subject: [PATCH 23/23] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/flag.svg | 3 +++ src/pages/Diary.js | 49 +++++++++++++++++++++++++++------------------ src/utils/axios.js | 20 ++++++++++++++++++ 3 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 src/assets/flag.svg diff --git a/src/assets/flag.svg b/src/assets/flag.svg new file mode 100644 index 0000000..8e1830a --- /dev/null +++ b/src/assets/flag.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/pages/Diary.js b/src/pages/Diary.js index 3e3c861..bd5bb3b 100644 --- a/src/pages/Diary.js +++ b/src/pages/Diary.js @@ -3,14 +3,10 @@ import styled from 'styled-components' import { ReactComponent as WriteIcon } from "../assets/pen.svg" import PaginationBar from '../components/diary/PaginationBar' import { useLocation, useNavigate } from 'react-router-dom' -import { getDiaryDetail, getDiaryList } from '../utils/axios' +import { bookmarkPost, getDiaryDetail, getDiaryList } from '../utils/axios' import WritePostModal from '../components/diary/WritePostModal' import SearchBar from '../components/SearchBar' - -/** - * To do - * 1. PageSizeRegulator, DiaryBlock 컴포넌트 분리, 추상화 요망 - */ +import { ReactComponent as BookmarkIcon } from "../assets/flag.svg"; const Diary = () => { const currentURL = useLocation().search @@ -19,7 +15,7 @@ const Diary = () => { const [diaryList, setDiaryList] = useState([]) const [currentPage, setcurrentPage] = useState(1) - const [pageSize, setPageSize] = useState(3) + const [pageSize, setPageSize] = useState(5) const [numberOfPages, setNumberOfPages] = useState() const [isModalOpen, setIsModalOpen] = useState(false); const [searchContent, setsearchContent] = useState('') @@ -37,11 +33,6 @@ const Diary = () => { setsearchContent(newValue); } - const handlePostClick = async (post) => { - const postDetail = await getDiaryDetail(post.postId); - - } - useEffect(() => { const extractPageNumFromURL = () => { const urlParams = new URLSearchParams(currentURL) @@ -75,22 +66,22 @@ const Diary = () => { 페이지 당 게시물 개수 - setPageSize(1)}/> + setPageSize(1)}/> - setPageSize(5)}/> + setPageSize(5)} checked/> - setPageSize(10)}/> + setPageSize(10)}/> {searchedList ? (searchedList.map((diary) => ( - {getDiaryDetail(diary.diaryId, navigate)}}> - + + {getDiaryDetail(diary.diaryId, navigate)}}> {diary.thumbnailImgURL ? : } {diary.title} - + {getDiaryDetail(diary.diaryId, navigate)}}> {diary.member.name} @@ -101,6 +92,10 @@ const Diary = () => { 댓글 {diary.commentCount}
+ bookmarkPost(diary.diaryId)} + className={diary.isBookmarked ? "Bookmarked Icon" : "Icon"} + />
))): "Loading"} @@ -125,8 +120,10 @@ const PageBody = styled.div` display: flex; flex-direction: column; width: 100vw; + height: 100vh; align-items: center; justify-content: center; + background: #fafafa; `; const WritePostButton = styled.div` @@ -160,7 +157,21 @@ const RegulatorButton = styled.input``; const DiaryBlock = styled.div` width: 800px; margin: auto; - border : 1px solid + border-radius: 5px; + border: 1px solid #8b8b8b; + background: #ffffff; + position: relative; + margin-bottom: 20px; + .Icon { + position: absolute; + top: -5px; + right: 10px; + z-index: 0; + fill: #9b9b9b; + } + .Bookmarked { + fill: #7054ff; + } `; const DiaryHeader = styled.div` diff --git a/src/utils/axios.js b/src/utils/axios.js index f19a00d..5adeb60 100644 --- a/src/utils/axios.js +++ b/src/utils/axios.js @@ -217,4 +217,24 @@ export const editRecomment = (postId, commentId, recommentId, content) => { .catch((error) => { console.log(error); }); +} + +export const bookmarkPost = async (postId) => { + let config = { + method: 'post', + maxBodyLength: Infinity, + url: API_URL + `/diary/${postId}/bookmark`, + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authorizationCode}`, + }, +}; + +axios.request(config) +.then((response) => { + window.location.reload(); +}) +.catch((error) => { + console.log(error); +}); } \ No newline at end of file