Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/layout/footer/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ const Footer = () => {
©codeit - 2023
</div>
<div className='order-1 flex gap-[30px] font-normal text-gray-500'>
<Link href={'/'} className='text-body-s hover:text-gray-300 tablet:text-body-m'>
<Link href={'/'} className='text-body-s hover:text-gray-700 tablet:text-body-m'>
Privacy Policy
</Link>
<Link href={'/'} className='text-body-s hover:text-gray-300 tablet:text-body-m'>
<Link href={'/'} className='text-body-s hover:text-gray-700 tablet:text-body-m'>
FAQ
</Link>
</div>
Expand Down
Empty file.
70 changes: 70 additions & 0 deletions src/components/ui/pagination/pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Icon } from '@/components/ui';
import { useState } from 'react';

const PAGE_GROUP_SIZE = 7;
const ITEMS_PER_PAGE = 5;

interface PaginationProps {
totalItems: number;
}
// totalItems 는 API 통신 시 Response 로 받는 """count""" 부모로부터 넘겨주기!

const Pagination = ({ totalItems }: PaginationProps) => {
const [currentPage, setCurrentPage] = useState(totalItems > 0 ? 1 : 0);
// [currentPage, setCurrentPage] 는 부모 페이지에서 받아올 데이터 내용
// - 그래야 페이지 바뀔 때 부모 페이지에 state 영향 줘서 리렌더링해서 화면 다시 보여줌
// - 이후 페이지 작업 시 위의 state 선언은 부모페이지에서 하고 값들 props 로 받기
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그렇다면 prop자체를 {totalItems, currentPage, onPageChange} 로 작성하는건 어떠실까요!? 부모페이지에서 받아올 데이터 내용이면 Prop 에 작성이 되어야 할텐데 props 엔 전체 아이템만 받고 있는것 같아서요!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네! 안그래도 위의 내용은 페이지 작업때 다루어질 것 같아 최대한 설명을 드리고 싶어서 적어놨습니다 :)
부모 컴포넌트에서 onPageChange 로 currentPage 의 state 변경하는 함수 만들어서 props 로 내려주는 형식으로 다같이 가져간다 생각을 하고 말씀하신대로 수정하겠습니다!

추가적으로, 피그마 시안을 다시 봤더니 인화님 페이지는 데이터 5개 / 소현님 페이지는 데이터 6개로 다르더라고요! 그래서 상수 빼고 itemsPerPage 로 페이지 하나하나마다 받아오는 데이터개수도 props 로 내릴 수 있게 변경하겠습니다!

const [pageGroup, setPageGroup] = useState(0);

const totlaPages = Math.ceil(totalItems / ITEMS_PER_PAGE);
if (totlaPages === 0) return null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오타가 발생한것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Props 로 받아오는 totalItems 가 없을때 페이지네이션 보여주지 않고 함수 종료시키려고 설정했는데 값이 0이 아니라 값이 없는 경우를 생각 못했네요!
const totalPages = totalItems ? Math.ceil(totalItems / itemsPerPage) : 0;

if (totalPages < 1) return null;

로 해서 값이 없을 경우 함수 종료하도록 수정하겠습니다!

Pagination 경우에는 받아오는 저 props 들이 무조건 다 필수여야 화면에 페이지 버튼들이 그려지는 것이기 때문에 type정의에 optional 로 설정하면 안되고 모두 다 필수 조건으로 넣은다음 없는 경우 함수 종료 시키는 것이 맞다고 찾아봐서 위처럼 수정해 놓겠습니다.

추가적으로, AI 자문을 구하면서 이전 / 이후 버튼을 누르고 다른 페이지를 눌렀을 때 PageGroup 이 바뀌게 되는데 이 부분을 의존성 배열로 관리해야 한다고 해서 추가하였습니다. React Hook 이라 구조가 if 문 아래에 있으면 문제가 생겨 함수 종료할 경우 위에 선언해서 사용하는 것이 맞다고 해서 추가하였습니다.

const startPage = pageGroup * PAGE_GROUP_SIZE + 1;
const endPage = Math.min(startPage + PAGE_GROUP_SIZE - 1, totlaPages);
const pageNumbers = Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i);
const isPrevDisabled = pageGroup === 0;
const isNextDisabled = (pageGroup + 1) * PAGE_GROUP_SIZE >= totlaPages;

return (
<>
<div className='flex h-14 items-center justify-center bg-white tablet:h-16'>
<div className='flex h-8 items-center justify-center gap-[2px] px-3 py-2 tablet:h-10'>
<Icon
className={`h-5 w-5 ${isPrevDisabled ? 'bg-gray-400' : 'cursor-pointer'}`}
onClick={() => {
if (!isPrevDisabled) {
setPageGroup(prev => Math.max(prev - 1, 0));
}
}}
iconName='chevronLeft'
ariaLabel='이전'
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아이콘에 바로 이벤트 핸들러를 작성하였는데 접근성및 키보드 네비게이션이 보장되려면 버튼 > 아이콘 형태가 조금더 적합할것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

button 태그 안에 Icon 형식으로 수정하겠습니다!

{pageNumbers.map(page => (
<button
key={page}
onClick={() => setCurrentPage(page)}
className={
page === currentPage
? 'h-8 w-8 rounded bg-red-300 text-caption text-white tablet:text-body-s'
: 'h-8 w-8 text-caption tablet:text-body-s'
}
>
{page}
</button>
))}
<Icon
className={`h-5 w-5 ${isNextDisabled ? 'bg-gray-400' : 'cursor-pointer'}`}
onClick={() => {
if (!isNextDisabled) {
setPageGroup(prev => ((prev + 1) * PAGE_GROUP_SIZE < totlaPages ? prev + 1 : prev));
}
}}
iconName='chevronRight'
ariaLabel='이후'
/>
</div>
</div>
</>
);
};

export default Pagination;
Loading