조회조건 레이아웃 수정

엑셀다운버튼 수정
progress 추가
front pagenation 추가
This commit is contained in:
2025-04-09 15:44:51 +09:00
parent 80a3c0ab8a
commit a74376108a
11 changed files with 962 additions and 193 deletions

View 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;
}
`;