<추가/수정 사항>
※페이지네이션 구현
-Math.ceil : 올림 함수 ex) 4.3 -> 5 , 7.8 -> 8
-slice() : 배열의 일부분을 잘라내서, 새로운 배열을 구성
-각 페이지 마다 다이어리 4개씩
※카테고리 분류 함수 <Diary.JSX>에서 <Sidebar.JSX>로 옮겨 정리
-카테고리 버튼 누를 때마다 페이지 1로 설정
component
-Input.JSX
-Button.JSX
-Textarea.JSX
-DiaryWrite.JSX
-DiaryBlock.JSX
-Category.JSX
-CategoryButton.JSX
-Header.JSX
-Sidebar.JSX
-EditDiary.JSX
-Pagination.JSX
module
-Diary.JSX
css
-Diary.css
-Category.css
component - <Pagination.JSX>
import React from 'react'
import '../css/Diary.css'
import Button from './Button'
function Pagination({totalDiaryNum, onePageDiaryNum, setCurrentPage, currentPage}) {
const pageList = [] //페이지 리스트
const totalPages = Math.ceil(totalDiaryNum / onePageDiaryNum)
//총 다이어리 수 / 한 페이지 당 다이어리 수 = 총 페이지 수
const prevPage = () => { //이전 페이지
if (currentPage === 1) { //첫 페이지 일 경우
alert('첫 페이지입니다.')
} else {
setCurrentPage(currentPage - 1)
}
}
const nextPage = () => { //다음 페이지
if (currentPage === pageList.length) { //마지막 페이지 일 경우
alert('마지막 페이지입니다.')
} else {
setCurrentPage(currentPage + 1)
}
}
for (let i = 1; i <= totalPages; i++) { //페이지 마다 다이어리 삽입
pageList.push(i)
}
return (
<div className="pagination">
<Button className={'pageButton'} name={'≪'} onClick={prevPage} />
{pageList.map(page => (
<Button
key={page}
className={currentPage === page ? 'currentPageButton' : 'pageButton'}
name={page}
onClick={() => setCurrentPage(page)}
/>
))}
<Button className={'pageButton'} name={'≫'} onClick={nextPage} />
</div>
)
}
export default Pagination
component - <Sidebar.JSX>
import React from 'react'
import '../css/Diary.css'
import CategoryButton from './CatogoryButton'
function Sidebar({diary, modalBool, setCategoryDiary, setCurrentPage}) {
const allDivDiaryBtn = () => {
setCategoryDiary(diary)
setCurrentPage(1)
}
const routineDivDiaryBtn = () => {
setCategoryDiary(diary.filter(divide => divide.name === 'routine'))
setCurrentPage(1)
}
const studyDivDiaryBtn = () => {
setCategoryDiary(diary.filter(divide => divide.name === 'study'))
setCurrentPage(1)
}
const travelDivDiaryBtn = () => {
setCategoryDiary(diary.filter(divide => divide.name === 'travel'))
setCurrentPage(1)
}
const gameDivDiaryBtn = () => {
setCategoryDiary(diary.filter(divide => divide.name === 'game'))
setCurrentPage(1)
}
return (
<div className="sidebarDiv">
<CategoryButton
allDivDiaryBtn={modalBool ? null : allDivDiaryBtn}
routineDivDiaryBtn={modalBool ? null : routineDivDiaryBtn}
studyDivDiaryBtn={modalBool ? null : studyDivDiaryBtn}
travelDivDiaryBtn={modalBool ? null : travelDivDiaryBtn}
gameDivDiaryBtn={modalBool ? null : gameDivDiaryBtn}
/>
</div>
)
}
export default Sidebar
module - <Diary.JSX>
import React, {useEffect, useRef, useState} from 'react'
import '../css/Diary.css'
import DiaryWrite from '../component/DiaryWrite'
import DiaryBlock from '../component/DiaryBlock'
import Button from '../component/Button'
import Header from '../component/Header'
import Sidebar from '../component/Sidebar'
import Pagination from '../component/Pagination'
function Diary() {
const [diary, setDiary] = useState(JSON.parse(localStorage.getItem('Diary')) || [])
const [categoryDiary, setCategoryDiary] = useState(diary)
const [categoryValue, setCategoryValue] = useState('none')
const [modalBool, setModalBool] = useState(false)
const [currentPage, setCurrentPage] = useState(1) //각 페이지 당 번호 부여
const onePageDiaryNum = 4 //페이지 당 다이어리 개수
const diaryKey = useRef(parseInt(localStorage.getItem('DiaryKey')) || 0)
const firstDiary = (currentPage - 1) * onePageDiaryNum //페이지 당 첫 다이어리
const lastDiary = firstDiary + onePageDiaryNum //페이지 당 마지막 다이어리
const currentDiary = categoryDiary.slice(firstDiary, lastDiary)//다이어리 나누기
const changeCategoryValue = event => {
setCategoryValue(event.target.value)
}
const addDiary = (title, content) => {
if (categoryValue === 'none') {
alert('카테고리를 지정해주세요.')
} else {
const newDiary = {
title,
content,
name: categoryValue,
id: diaryKey.current,
date: new Date().toLocaleString()
}
diaryKey.current += 1
setDiary([newDiary, ...diary])
setCategoryValue('none')
setModalBool(false)
}
}
const deleteDiary = id => {
const remainDiary = diary.filter(remove => remove.id !== id)
setDiary(remainDiary)
}
const editDiary = (id, title, content, name) => {
setDiary(
diary.map(edit =>
edit.id === id ? {...edit, title: title, content: content, name: name} : edit
)
)
}
const openModal = event => {
setModalBool(true)
event.stopPropagation()
}
const closeModal = () => {
setModalBool(false)
setCategoryValue('none')
}
useEffect(() => {
localStorage.setItem('Diary', JSON.stringify(diary))
localStorage.setItem('DiaryKey', parseInt(diaryKey.current))
setCategoryDiary(diary)
}, [diary])
return (
<div className={modalBool ? 'diaryDiv' : null} onClick={closeModal}>
<div>
<Header />
</div>
<div>
<div>
<Sidebar
diary={diary}
modalBool={modalBool}
setCategoryDiary={setCategoryDiary}
setCurrentPage={setCurrentPage}
/>
</div>
<div className="mainDiv">
<div>
<Button
className="openWriteDiary"
name={'글쓰기 +'}
onClick={modalBool ? null : openModal}
/>
</div>
<div onClick={event => event.stopPropagation()}>
{modalBool ? (
<DiaryWrite
addDiary={addDiary}
closeModal={closeModal}
categoryValue={categoryValue}
changeCategory={changeCategoryValue}
/>
) : null}
</div>
<div className="gridDiv">
{currentDiary.map(diaryData => (
<DiaryBlock
key={diaryData.id}
name={diaryData.name}
date={diaryData.date}
{...diaryData}
deleteDiary={deleteDiary}
editDiary={editDiary}
modalBool={modalBool}
/>
))}
</div>
<div>
<Pagination //페이지네이션
totalDiaryNum={categoryDiary.length}
onePageDiaryNum={onePageDiaryNum}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
/>
</div>
</div>
</div>
</div>
)
}
export default Diary
Diary.css
.headerDiv {
display: flex;
border-bottom: 1px solid black;
top: 0;
width: 100%;
background-color: white;
position: fixed;
z-index: 1;
}
.headerTitle {
margin: 20px 0px 20px 70px;
padding: 0;
font-size: 40px;
}
.sidebarDiv {
position: fixed;
border-right: 1px solid black;
height: 100vh;
width: 300px;
padding-top: 100px;
top: 0;
}
.mainDiv {
margin: 120px 0px 20px 300px;
}
.gridDiv {
display: grid;
grid-template-columns: 500px 500px;
justify-content: center;
}
.writeDiv {
border: 1px solid black;
display: inline-block;
padding: 20px;
position: absolute;
background-color: white;
left: 37%;
top: 10%;
box-shadow: rgba(0, 0, 0, 0.7) 0 0 0 9999px;
z-index: 1;
pointer-events: auto;
}
.writeMain {
text-align: center;
margin-left: 30px;
}
.writeTitleDiv {
margin-top: 20px;
}
.writeTitleInput {
width: 400px;
height: 30px;
font-size: 15px;
}
.writeContentDiv {
margin-top: 20px;
}
.writeContentTextarea {
width: 400px;
height: 100px;
resize: none;
font-size: 15px;
}
.blockDiv {
border: 1px solid rgb(211, 211, 211);
background-color: rgb(211, 211, 211);
width: 450px;
padding: 10px;
margin-top: 20px;
}
.blockTitleDiv {
display: flex;
justify-content: flex-start;
align-items: center;
}
.blockTitle {
margin-right: auto;
margin-top: 10px;
margin-bottom: 0;
}
.blockDateDiv {
font-size: 15px;
font-style: italic;
}
.diaryDiv {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.openWriteDiary {
margin: 10px 0px 0px 120px;
padding: 7px 15px 7px 15px;
background-color: black;
color: white;
border: none;
}
.closeWriteDiary {
float: right;
background: none;
border: none;
font-size: 20px;
}
.pagination {
display: flex;
margin: 30px 30px 0px 0px;
justify-content: center;
}
.pageButton {
width: 30px;
height: 30px;
border: 1px solid black;
font-weight: bold;
background-color: white;
}
.currentPageButton {
width: 30px;
height: 30px;
border: 1px solid black;
background-color: black;
color: white;
font-weight: bold;
}
.submitButton {
margin-top: 20px;
width: 400px;
height: 40px;
font-size: 20px;
}
.deleteButton {
font-size: 15px;
padding: 3px 10px 3px 10px;
margin-right: 10px;
margin-top: 10px;
background-color: rgb(211, 211, 211);
}
.editButton {
font-size: 15px;
padding: 3px 10px 3px 10px;
margin-right: 30px;
margin-top: 10px;
background-color: rgb(211, 211, 211);
}
'개인 공부 > 게시판' 카테고리의 다른 글
8. 일기 수정 모달 창 (0) | 2024.02.15 |
---|---|
7. 페이지 구성 (0) | 2024.02.13 |
6. 모달 창 구현 (0) | 2024.02.10 |
5. 카테고리, 작성 날짜 (0) | 2024.01.31 |
4. EditDiary (0) | 2024.01.29 |