Skip to content

Commit

Permalink
♻️ 스크린 크기에 따라 페이지네이션 숫자 개수 변경 (#145)
Browse files Browse the repository at this point in the history
* fix: 공지목록 웹버전 반응형 깨지던 것 수정

* feat: 모바일 크기 페이지네이션 개수 변동

* fix: 소식탭 페이지네이션 숫자 개수 변경
  • Loading branch information
Limchansol authored Mar 5, 2024
1 parent 9a8848c commit c02c9ad
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 16 deletions.
3 changes: 3 additions & 0 deletions app/[locale]/community/news/NewsPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { NEWS_TAGS } from '@/constants/tag';
import { NewsPreviewList } from '@/types/news';

import { useCustomSearchParams } from '@/utils/hooks/useCustomSearchParams';
import useResponsive from '@/utils/hooks/useResponsive';
import { getPath } from '@/utils/page';
import { news } from '@/utils/segmentNode';

Expand All @@ -26,6 +27,7 @@ export default function NewsPageContent({
data: NewsPreviewList;
}) {
const { page, keyword, tags, setSearchParams } = useCustomSearchParams();
const { screenType } = useResponsive();

const setCurrentPage = (pageNum: number) => {
setSearchParams({ purpose: 'navigation', pageNum });
Expand Down Expand Up @@ -60,6 +62,7 @@ export default function NewsPageContent({
<Pagination
totalPostsCount={total}
postsCountPerPage={POST_LIMIT}
pageLimit={screenType == 'desktop' ? 10 : 5}
currentPage={page}
setCurrentPage={setCurrentPage}
/>
Expand Down
10 changes: 7 additions & 3 deletions app/[locale]/community/notice/NoticeListHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ export default function NoticeListHeader({ isEditMode }: { isEditMode: boolean }

return (
<h5
className={`h-11 ${paddingLeft} hidden sm:flex text-[15px] items-center border-b border-neutral-200 text-neutral-800`}
className={`h-11 ${paddingLeft} hidden sm:flex text-[15px] pr-4 items-center border-b border-neutral-200 text-neutral-800`}
>
<span className={`${NOTICE_ROW_CELL_WIDTH.title} pl-3 tracking-wide`}>제목</span>
<span className={`${NOTICE_ROW_CELL_WIDTH.date} pl-8 tracking-wide`}>날짜</span>
<span className={`${NOTICE_ROW_CELL_WIDTH.title} grow pl-3 tracking-wide whitespace-nowrap`}>
제목
</span>
<span className={`${NOTICE_ROW_CELL_WIDTH.date} pl-8 tracking-wide whitespace-nowrap`}>
날짜
</span>
</h5>
);
}
14 changes: 9 additions & 5 deletions app/[locale]/community/notice/NoticeListRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ interface NoticeListRowProps {
export const NOTICE_ROW_CELL_WIDTH = {
check: 'sm:w-[3.125rem]',
pin: 'sm:w-[3.125rem]',
title: 'sm:w-[35.625rem]',
date: 'sm:w-auto',
title: 'sm:max-w-full',
date: 'sm:w-auto sm:min-w-[7.125rem]',
} as const;

export default function NoticeListRow({
Expand Down Expand Up @@ -80,7 +80,11 @@ function CheckboxCell({ isChecked, toggleCheck }: CheckboxCellProps) {

function PrivateOrPinCell({ isPrivate, isPinned }: { isPrivate: boolean; isPinned: boolean }) {
return (
<span className={`${NOTICE_ROW_CELL_WIDTH.pin} sm:px-[0.8125rem] shrink-0`}>
<span
className={`${NOTICE_ROW_CELL_WIDTH.pin} ${
!(isPrivate || isPinned) && 'hidden sm:inline-flex'
} sm:px-[0.8125rem] shrink-0`}
>
{isPrivate ? <LockIcon /> : isPinned && <PinIcon />}
</span>
);
Expand Down Expand Up @@ -108,10 +112,10 @@ function TitleCell({ title, hasAttachment, id, isEditMode, isPinned }: TitleCell
);
} else {
return (
<span className={`${NOTICE_ROW_CELL_WIDTH.title} sm:pl-3`}>
<span className={`${NOTICE_ROW_CELL_WIDTH.title} sm:pl-3 grow min-w-0`}>
<Link
href={`${noticePath}/${id}`}
className="font-semibold sm:font-normal flex max-w-fit items-center gap-1.5 hover:text-main-orange"
className="font-semibold sm:font-normal flex items-center gap-1.5 hover:text-main-orange"
>
<span
className={`${
Expand Down
5 changes: 4 additions & 1 deletion app/[locale]/community/notice/NoticePageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import { NOTICE_TAGS } from '@/constants/tag';
import { NoticePreviewList } from '@/types/notice';

import { useCustomSearchParams } from '@/utils/hooks/useCustomSearchParams';
import useResponsive from '@/utils/hooks/useResponsive';

import AdminFeatures from './AdminFeatures';

const POST_LIMIT = 20;
const POST_LIMIT = 20; // TODO: 모바일 크기에서는 10으로 축소

type ReducerAction =
| {
Expand Down Expand Up @@ -48,6 +49,7 @@ export default function NoticePageContent({
data: NoticePreviewList;
}) {
const { page, keyword, tags, setSearchParams } = useCustomSearchParams();
const { screenType } = useResponsive();
const [selectedPostIds, changeSelectedIds] = useReducer(reducer, new Set<number>());
const [isEditMode, toggleEditMode] = useReducer((editMode) => {
changeSelectedIds({ type: 'RESET' });
Expand Down Expand Up @@ -78,6 +80,7 @@ export default function NoticePageContent({
<Pagination
totalPostsCount={totalPostsCount}
postsCountPerPage={POST_LIMIT}
pageLimit={screenType == 'desktop' ? 10 : 5}
currentPage={page}
setCurrentPage={setCurrentPage}
disabled={isEditMode}
Expand Down
5 changes: 4 additions & 1 deletion app/[locale]/community/seminar/SeminarPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ import SeminarSearchBar from '@/app/[locale]/community/seminar/SearchBar';
import SeminarRow from '@/app/[locale]/community/seminar/SeminarRow';
import SeminarYear from '@/app/[locale]/community/seminar/SeminarYear';

import LoginStaffVisible from '@/components/common/auth/LoginStaffVisible';
import Pagination from '@/components/common/Pagination';
import PageLayout from '@/components/layout/pageLayout/PageLayout';

import { SeminarList } from '@/types/seminar';

import { useCustomSearchParams } from '@/utils/hooks/useCustomSearchParams';
import useResponsive from '@/utils/hooks/useResponsive';

import AdminFeatures from './AdminFeatures';
import LoginStaffVisible from '../../../../components/common/auth/LoginStaffVisible';

const postsCountPerPage = 10;

export default function SeminarContent({ data: { searchList, total } }: { data: SeminarList }) {
const { page, keyword, setSearchParams } = useCustomSearchParams();
const { screenType } = useResponsive();

const setCurrentPage = (pageNum: number) => {
setSearchParams({ purpose: 'navigation', pageNum });
Expand All @@ -43,6 +45,7 @@ export default function SeminarContent({ data: { searchList, total } }: { data:
<Pagination
totalPostsCount={total ?? 0}
postsCountPerPage={postsCountPerPage}
pageLimit={screenType == 'desktop' ? 10 : 5}
currentPage={page}
setCurrentPage={setCurrentPage}
/>
Expand Down
15 changes: 9 additions & 6 deletions components/common/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
interface PaginationProps {
totalPostsCount: number;
postsCountPerPage: number; // 한번에 보여줄 글 개수
/** 한 페이지에 보여줄 글 개수 */
postsCountPerPage: number;
currentPage: number;
/** 페이지네이션 바에 보여줄 페이지 개수 */
pageLimit?: number;
setCurrentPage(pageNum: number): void;
disabled?: boolean;
}

const PAGE_LIMIT = 10; // 페이지네이션 바에 한번에 보여줄 페이지 개수
const MAX_PAGE = 10000; // totalPostsCount 실제값이 아닌 추정치가 왔을 경우 사용할 마지막 페이지 번호

export default function Pagination({
totalPostsCount,
postsCountPerPage,
currentPage,
pageLimit = 10,
setCurrentPage,
disabled = false,
}: PaginationProps) {
const numPages = Math.ceil((totalPostsCount || 1) / postsCountPerPage); // 전체 페이지 개수
const firstNum = currentPage - ((currentPage - 1) % PAGE_LIMIT); // 페이지네이션 시작 번호
const firstNum = currentPage - ((currentPage - 1) % pageLimit); // 페이지네이션 시작 번호

// fetch하는 동안 NUM_PAGES가 1이 되기에 최솟값이 1이도록 처리
const paginationNumberCnt = Math.max(1, Math.min(PAGE_LIMIT, numPages - firstNum + 1));
const paginationNumberCnt = Math.max(1, Math.min(pageLimit, numPages - firstNum + 1));

// 페이지 범위 넘어가면 마지막 페이지로 리다이렉트
if (numPages < currentPage) setCurrentPage(numPages);
Expand Down Expand Up @@ -55,8 +58,8 @@ export default function Pagination({
</div>
<PaginationArrow
iconName="navigate_next"
num={firstNum + PAGE_LIMIT}
disabled={firstNum + PAGE_LIMIT > numPages || disabled}
num={firstNum + pageLimit}
disabled={firstNum + pageLimit > numPages || disabled}
movePageNumber={setCurrentPage}
/>
<PaginationArrow
Expand Down
26 changes: 26 additions & 0 deletions utils/hooks/useResponsive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useCallback, useEffect, useState } from 'react';

const BREAK_POINT = {
sm: 640 /* mobile min-width: 640px */,
};

type ScreenType = 'mobile' | 'desktop';

export default function useResponsive() {
const [screenType, setScreenType] = useState<ScreenType>('desktop');

const handleResize = useCallback(() => {
if (window.innerWidth < BREAK_POINT.sm && screenType !== 'mobile') {
setScreenType('mobile');
} else if (window.innerWidth >= BREAK_POINT.sm && screenType !== 'desktop') {
setScreenType('desktop');
}
}, [screenType]);

useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [handleResize]);

return { screenType };
}

0 comments on commit c02c9ad

Please sign in to comment.