본문 바로가기
개인 공부/게시판

9. 페이지네이션

by 갱생angel 2024. 2. 19.

<추가/수정 사항>

※페이지네이션 구현

  -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