From ba49938320a7b7d884bfbd6ef0e3b38e0ffe91c8 Mon Sep 17 00:00:00 2001 From: naraeng Date: Sat, 10 Aug 2024 23:43:07 +0900 Subject: [PATCH] Feat : notice page (#77) --- package-lock.json | 12 +++++ package.json | 1 + src/App.jsx | 3 ++ src/component/main/MainNotice.jsx | 9 ++-- src/component/main/NoticePage.jsx | 77 +++++++++++++++++++++++++++++++ src/component/main/noticePage.css | 76 ++++++++++++++++++++++++++++++ 6 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 src/component/main/NoticePage.jsx create mode 100644 src/component/main/noticePage.css diff --git a/package-lock.json b/package-lock.json index 95a3082..5b57ccb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "react-dom": "^18.2.0", "react-minimal-side-navigation": "^1.9.2", "react-modal": "^3.16.1", + "react-paginate": "^8.2.0", "react-redux": "^9.1.0", "react-responsive": "^10.0.0", "react-router-dom": "^6.22.3", @@ -15350,6 +15351,17 @@ "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" } }, + "node_modules/react-paginate": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/react-paginate/-/react-paginate-8.2.0.tgz", + "integrity": "sha512-sJCz1PW+9PNIjUSn919nlcRVuleN2YPoFBOvL+6TPgrH/3lwphqiSOgdrLafLdyLDxsgK+oSgviqacF4hxsDIw==", + "dependencies": { + "prop-types": "^15" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18" + } + }, "node_modules/react-redux": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.0.tgz", diff --git a/package.json b/package.json index da680ae..a1bed6f 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "react-dom": "^18.2.0", "react-minimal-side-navigation": "^1.9.2", "react-modal": "^3.16.1", + "react-paginate": "^8.2.0", "react-redux": "^9.1.0", "react-responsive": "^10.0.0", "react-router-dom": "^6.22.3", diff --git a/src/App.jsx b/src/App.jsx index e982d04..866f624 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -22,6 +22,7 @@ import EditPage from "./component/admin/EditPage"; import PendingList from "./component/admin/pending/PendingList"; import Layout from "./component/admin/component/Layout"; import ClubReviews from "./component/admin/ClubReviews"; +import NoticePage from "./component/main/NoticePage"; function App() { const isPc = useMediaQuery({ @@ -38,6 +39,7 @@ function App() {
} /> + }> } /> {/* } /> */} } /> @@ -70,6 +72,7 @@ function App() {
} /> + }> } /> } /> } /> diff --git a/src/component/main/MainNotice.jsx b/src/component/main/MainNotice.jsx index 90c610e..be2cb28 100644 --- a/src/component/main/MainNotice.jsx +++ b/src/component/main/MainNotice.jsx @@ -1,13 +1,14 @@ import { useState, useEffect } from "react"; import styles from "./mainNotice.module.css"; import { customAxios } from "../../config/axios-config"; +import { LinkItem } from "../branch/BranchCentral"; export default function MainNotice() { const [noticeData, setNoticeData] = useState([]); const getNoticeData = async () => { try { - const res = await customAxios.get(`/v1/notices`); + const res = await customAxios.get(`/v1/notices/main-page`); if (res.data.success) { setNoticeData(res.data.data); console.log(res.data.data); @@ -32,11 +33,13 @@ export default function MainNotice() { // 메인 페이지에 보여줄 공지사항 return (
-
공지사항
+ +
공지사항
+
{noticeData.map((item) => (
-
{item.content}
+
{item.title}

|

{formatDate(item.createdAt)}

diff --git a/src/component/main/NoticePage.jsx b/src/component/main/NoticePage.jsx new file mode 100644 index 0000000..4dae7f6 --- /dev/null +++ b/src/component/main/NoticePage.jsx @@ -0,0 +1,77 @@ +import React, { useState, useEffect } from "react"; +import ReactPaginate from "react-paginate"; +import { customAxios } from "../../config/axios-config"; +import './noticePage.css'; + +export default function NoticePage() { + const [noticeData, setNoticeData] = useState([]); + const [pageCount, setPageCount] = useState(0); + const [currentPage, setCurrentPage] = useState(0); + const itemsPerPage = 10; + + const getNoticeData = async (page = 0) => { + try { + const res = await customAxios.get(`/v1/notices`, { + params: { page, size: itemsPerPage } + }); + if (res.data.success && res.data.data.content) { + setNoticeData(res.data.data.content); + setPageCount(res.data.data.totalPages); + } else { + setNoticeData([]); + } + } catch (error) { + console.error("Error fetching data: ", error); + setNoticeData([]); + } + }; + + useEffect(() => { + getNoticeData(currentPage); + }, [currentPage]); + + const handlePageClick = ({ selected }) => { + setCurrentPage(selected); + }; + + return ( +
+

공지사항

+
+
+ 번호 + 제목 + 날짜 + 작성자 + 조회수 +
+ {noticeData.length > 0 ? ( + noticeData.map((item, index) => ( +
+ {currentPage * itemsPerPage + index + 1} + {item.title} + {new Date(item.createdAt).toLocaleDateString()} + 관리자 + {item.totalView ? {item.totalView} : 0} +
+ )) + ) : ( +
+ 공지사항이 없습니다. +
+ )} +
+ '} + pageCount={pageCount} + onPageChange={handlePageClick} + containerClassName={'pagination'} + previousLinkClassName={'pagination_link'} + nextLinkClassName={'pagination_link'} + disabledClassName={'pagination_link_disabled'} + activeClassName={'pagination_link_active'} + /> +
+ ); +} diff --git a/src/component/main/noticePage.css b/src/component/main/noticePage.css new file mode 100644 index 0000000..46aa0b5 --- /dev/null +++ b/src/component/main/noticePage.css @@ -0,0 +1,76 @@ +.notice_container { + width: 80%; + margin: 0 auto; + font-family: Arial, sans-serif; + } + + h2 { + text-align: center; + margin-bottom: 20px; + } + + .notice_list { + width: 100%; + border-collapse: collapse; + } + + .notice_header, .notice_item { + display: grid; + grid-template-columns: 1fr 4fr 2fr 2fr 1fr; + border-bottom: 1px solid #ddd; + padding: 10px 0; + } + + .notice_header { + background-color: #f4f4f4; + font-weight: bold; + } + + .notice_item span { + text-align: center; + } + + .notice_item { + color: #666; + transition: background-color 0.3s; + } + + .notice_item:hover { + background-color: #f9f9f9; + } + + .notice_item:nth-child(even) { + background-color: #f4f4f4; + } + + .notice_item:nth-child(odd) { + background-color: #fff; + } + + .pagination { + display: flex; + justify-content: center; + margin-top: 20px; + list-style: none; + padding: 0; + } + + .pagination_link { + margin: 0 5px; + padding: 8px 12px; + border: 1px solid #ddd; + cursor: pointer; + color: #007bff; + } + + .pagination_link_active { + background-color: #007bff; + color: #fff; + border: none; + } + + .pagination_link_disabled { + color: #ccc; + cursor: not-allowed; + } + \ No newline at end of file