조회조건 레이아웃 수정
엑셀다운버튼 수정 progress 추가 front pagenation 추가
This commit is contained in:
151
src/components/common/Pagination/FrontPagination.js
Normal file
151
src/components/common/Pagination/FrontPagination.js
Normal file
@@ -0,0 +1,151 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import PaginationIcon from '../../../assets/img/icon/icon-pagination.png';
|
||||
|
||||
const FrontPagination = ({
|
||||
data, // 전체 데이터 배열
|
||||
itemsPerPage, // 페이지당 표시할 항목 수
|
||||
currentPage, // 현재 페이지
|
||||
setCurrentPage, // 현재 페이지 설정 함수
|
||||
pageLimit = 10, // 페이지 네비게이션에 표시할 페이지 수
|
||||
onPageChange // 페이지 변경 시 호출될 콜백 함수 (선택 사항)
|
||||
}) => {
|
||||
const [blockNum, setBlockNum] = useState(0);
|
||||
|
||||
// 전체 페이지 수 계산
|
||||
const totalItems = data?.length || 0;
|
||||
const maxPage = Math.ceil(totalItems / itemsPerPage);
|
||||
|
||||
// 페이지 번호 배열 생성
|
||||
const pageNumbers = [];
|
||||
for (let i = 1; i <= maxPage; i++) {
|
||||
pageNumbers.push(i);
|
||||
}
|
||||
|
||||
// 현재 블록에 표시할 페이지 번호
|
||||
const v = blockNum * pageLimit;
|
||||
const pArr = pageNumbers.slice(v, pageLimit + v);
|
||||
|
||||
const processPageData = useCallback(() => {
|
||||
if (!data || !Array.isArray(data) || data.length === 0) return [];
|
||||
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
const endIndex = startIndex + itemsPerPage;
|
||||
return data.slice(startIndex, endIndex);
|
||||
}, [data, currentPage, itemsPerPage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (onPageChange) {
|
||||
const pageData = processPageData();
|
||||
onPageChange(pageData);
|
||||
}
|
||||
}, [processPageData, onPageChange]);
|
||||
|
||||
// itemsPerPage나 데이터가 변경되면 블록 초기화
|
||||
useEffect(() => {
|
||||
setBlockNum(0);
|
||||
}, [itemsPerPage, totalItems]);
|
||||
|
||||
// 첫 페이지로 이동
|
||||
const firstPage = () => {
|
||||
setBlockNum(0);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
// 마지막 페이지로 이동
|
||||
const lastPage = () => {
|
||||
setBlockNum(Math.ceil(maxPage / pageLimit) - 1);
|
||||
setCurrentPage(maxPage);
|
||||
};
|
||||
|
||||
// 이전 페이지로 이동
|
||||
const prePage = () => {
|
||||
if (currentPage <= 1) return;
|
||||
|
||||
if (currentPage - 1 <= pageLimit * blockNum) {
|
||||
setBlockNum(n => n - 1);
|
||||
}
|
||||
|
||||
setCurrentPage(n => n - 1);
|
||||
};
|
||||
|
||||
// 다음 페이지로 이동
|
||||
const nextPage = () => {
|
||||
if (currentPage >= maxPage) return;
|
||||
|
||||
if (pageLimit * (blockNum + 1) <= currentPage) {
|
||||
setBlockNum(n => n + 1);
|
||||
}
|
||||
|
||||
setCurrentPage(n => n + 1);
|
||||
};
|
||||
|
||||
// 특정 페이지로 이동
|
||||
const clickPage = number => {
|
||||
setCurrentPage(number);
|
||||
};
|
||||
|
||||
// 현재 표시 중인 항목 범위 계산 (예: "1-10 / 총 100개")
|
||||
const startItem = totalItems === 0 ? 0 : (currentPage - 1) * itemsPerPage + 1;
|
||||
const endItem = Math.min(currentPage * itemsPerPage, totalItems);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PaginationWrapper>
|
||||
<Button $position="0" onClick={firstPage} disabled={currentPage === 1} />
|
||||
<Button $position="-20px" onClick={prePage} disabled={currentPage === 1} />
|
||||
|
||||
{pArr.map(number => (
|
||||
<PageNum
|
||||
$state={currentPage === number ? 'on' : ''}
|
||||
key={number}
|
||||
onClick={() => clickPage(number)}
|
||||
>
|
||||
{number}
|
||||
</PageNum>
|
||||
))}
|
||||
|
||||
<Button $position="-40px" onClick={nextPage} disabled={currentPage === maxPage} />
|
||||
<Button $position="-60px" onClick={lastPage} disabled={currentPage === maxPage} />
|
||||
</PaginationWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default FrontPagination;
|
||||
|
||||
const PaginationWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
`;
|
||||
|
||||
const Button = styled.button`
|
||||
background: url('${PaginationIcon}') no-repeat;
|
||||
background-position: ${props => props.$position} 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
opacity: ${props => props.disabled ? 0.5 : 1};
|
||||
cursor: ${props => props.disabled ? 'default' : 'pointer'};
|
||||
|
||||
&:hover {
|
||||
background-position: ${props => props.$position} ${props => props.disabled ? '0' : '-20px'};
|
||||
}
|
||||
`;
|
||||
|
||||
const PageNum = styled.div`
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: ${props => (props.$state === 'on' ? '#2c2c2c' : '#CECECE')};
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #2c2c2c;
|
||||
}
|
||||
`;
|
||||
Reference in New Issue
Block a user