Skip to content

Commit

Permalink
feat(Feed): Pagination Component 추가
Browse files Browse the repository at this point in the history
- Common: paging model 수정
- Feed: MSW Mock에 error 대응 추가
Ref #54
  • Loading branch information
akariyan committed Feb 18, 2022
1 parent c03b2d3 commit 3cd7e73
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 24 deletions.
81 changes: 81 additions & 0 deletions components/common/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { styled } from '@nolmungshemung/ui-kits';

type PaginationProps = {
totalPages: number;
displayAmount: number;
currentPage: number;
setPage: (page: number) => void;
};

const StyledPageButton = styled('button', {
'&.currentPage': {
fontWeight: 'bold',
},
});

export function Pagination({
totalPages,
displayAmount,
currentPage,
setPage,
}: PaginationProps) {
const pagesStart =
Math.floor((currentPage - 1) / displayAmount) * displayAmount + 1;

const pagesArray = () => {
if (
Math.floor(totalPages / displayAmount) ===
Math.floor((currentPage - 1) / displayAmount)
) {
const lastArraySize = Math.floor(totalPages % displayAmount);
return [
...Array(lastArraySize)
.fill(0)
.map((_, i) => pagesStart + i),
];
} else {
return [
...Array(displayAmount)
.fill(0)
.map((_, i) => pagesStart + i),
];
}
};

return (
<>
<nav>
<button onClick={() => setPage(1)} disabled={currentPage === 1}>
&lt;&lt;
</button>
<button
onClick={() => setPage(currentPage - 1)}
disabled={currentPage === 1}
>
&lt;
</button>
{pagesArray().map((targetPage) => (
<StyledPageButton
key={targetPage}
onClick={() => setPage(targetPage)}
className={targetPage === currentPage ? 'currentPage' : ''}
>
{targetPage}
</StyledPageButton>
))}
<button
onClick={() => setPage(currentPage + 1)}
disabled={currentPage === totalPages}
>
&gt;
</button>
<button
onClick={() => setPage(totalPages)}
disabled={currentPage === totalPages}
>
&gt;&gt;
</button>
</nav>
</>
);
}
1 change: 1 addition & 0 deletions components/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Pagination';
18 changes: 9 additions & 9 deletions data/services/services.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@ export interface Contents {
transitionNum: number;
}

export interface MainPagingInfo {
export interface PagingInfo {
isLast: boolean;
start: number;
totalPages: number;
}

export interface MainContentsResponse {
mainContentsList: Contents[];
paging: MainPagingInfo;
paging: PagingInfo;
}

export interface MainWritersResponse {
mainWriterList: Writer[];
paging: MainPagingInfo;
paging: PagingInfo;
}

export interface ContentsSearchParams {
Expand All @@ -50,20 +51,19 @@ export interface TranslatingContentsData extends Contents {
contents: string;
}

export interface FeedParams {
writerId: string;
count: number;
export interface PagingParams {
page: number;
}

export interface FeedPagingInfo extends MainPagingInfo {
totalPages: number;
export interface FeedParams extends PagingParams {
writerId: string;
count: number;
}

export interface FeedContentsData {
writer: Writer;
feedContentsList: Contents[];
paging: FeedPagingInfo;
paging: PagingInfo;
}

export interface WritingContentsRequest {
Expand Down
15 changes: 15 additions & 0 deletions hooks/usePagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useState } from 'react';
import { PagingParams } from '~/data/services/services.model';

export function usePagination<T extends PagingParams>(initialState: T) {
const [page, setPage] = useState<T>(initialState);
const handleSetPage = (_page: number) => {
if (_page !== page.page) {
setPage((prev) => ({ ...prev, page: _page }));
}
};
return {
page,
handleSetPage,
};
}
5 changes: 0 additions & 5 deletions mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import {
WriterFactory,
} from './factories';
import { camelizeKeys } from 'humps';
import {
DEFAULT_FEED_COUNT,
DEFAULT_START_PAGE,
} from '~/shared/constants/pagination';

export const handlers = [
rest.get(`${API_URL}/services/main_contents`, (req, res, ctx) => {
Expand Down Expand Up @@ -124,7 +120,6 @@ export const handlers = [
`${API_URL}/user/name_registration`,
(req: RestRequest<UserData>, res, ctx) => {
const userData = camelizeKeys(req.body) as UserData;
console.log(userData);

if (userData.userId === '') {
const errorResponse = ErrorResponseFactory.build();
Expand Down
106 changes: 98 additions & 8 deletions pages/myfeed.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,121 @@
import { Box, Button } from '@nolmungshemung/ui-kits';
import { GetServerSidePropsContext, PreviewData } from 'next';
import { NextSeo } from 'next-seo';
import Router from 'next/router';
import { ParsedUrlQuery } from 'querystring';
import { useState } from 'react';
import { dehydrate, QueryClient } from 'react-query';
import { Pagination } from '~/components/common';
import Card from '~/components/Main/Card';
import { SkeletonCard } from '~/components/Skeleton';
import { getFeedContents } from '~/data/services/services.api';
import { useFeedContents } from '~/data/services/services.hooks';
import { FeedParams } from '~/data/services/services.model';
import {
DEFAULT_FEED_COUNT,
DEFAULT_START_PAGE,
} from '~/shared/constants/pagination';
import { usePagination } from '~/hooks/usePagination';
import { DEFAULT_START_PAGE } from '~/shared/constants/pagination';

interface MyFeedProps {
feedParams: FeedParams;
dehydratedState: any;
}

const MyFeed = function ({ feedParams: initFeedParams }: MyFeedProps) {
const [feedParams, setFeedParams] = useState(initFeedParams);
const DEFAULT_SHOW_FEED_COUNT = 8;
const DEFAULT_SHOW_PAGENATION_COUNT = 10;

const MyFeed = function ({ feedParams }: MyFeedProps) {
const { page, handleSetPage } = usePagination<FeedParams>(feedParams);
const { data, isLoading } = useFeedContents(feedParams);

const onCardClick = (contentsId: number) => {
Router.push({
pathname: '/contents',
query: { contentsId },
});
};

const onWritingClick = () => {
Router.push({
pathname: '/writing',
});
};

return (
<>
<NextSeo
title="WritingHub: 내 피드"
description="라이팅허브 내 피드 화면"
/>
<Box
css={{
display: 'grid',
gridTemplateAreas: `
"top"
"contents"
"pagination"
`,
justifyItems: 'center',
}}
>
<Box
css={{
gridArea: 'top',
position: 'relative',
display: 'flex',
justifyContent: 'center',
width: '100%',
height: '5.375rem',
paddingTop: '$sp-50',
}}
>
<span>
{data?.data.writer.writerName ?? 'XXX'} 작가님의 피드입니다
</span>
<Button
color="primary"
outline="none"
css={{
cursor: 'pointer',
}}
onClick={onWritingClick}
>
글쓰기
</Button>
</Box>
<Box
css={{
gridArea: 'contents',
display: 'grid',
gridTemplateColumns: 'repeat(4, 1fr)',
gridTemplateRows: 'repeat(5, 1fr)',
columnGap: '$sp-24',
rowGap: '$sp-16',
marginTop: '$sp-32',
}}
>
{isLoading ? (
<SkeletonCard count={DEFAULT_SHOW_FEED_COUNT} />
) : (
data?.data.feedContentsList.map((contents) => (
<Card
key={contents.contentsId}
{...contents}
onCardClick={() => onCardClick(contents.contentsId)}
/>
))
)}
</Box>
<Box
css={{
gridArea: 'pagination',
}}
>
<Pagination
totalPages={data?.data.paging.totalPages ?? 1}
displayAmount={DEFAULT_SHOW_PAGENATION_COUNT}
currentPage={page.page}
setPage={handleSetPage}
/>
</Box>
</Box>
</>
);
};
Expand All @@ -42,7 +132,7 @@ export async function getServerSideProps(
const writerId = context.query.writerId as string;
const feedParams: FeedParams = {
writerId: writerId,
count: DEFAULT_FEED_COUNT,
count: DEFAULT_SHOW_FEED_COUNT,
page: DEFAULT_START_PAGE,
};
const queryClient = new QueryClient();
Expand Down
2 changes: 0 additions & 2 deletions shared/constants/pagination.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
export const DEFAULT_SEARCH_RANGE = 20;
export const DEFAULT_FEED_COUNT = 8;
export const GRID_COLUMN_COUNT = 4;
export const DEFAULT_START_PAGE = 1;

0 comments on commit 3cd7e73

Please sign in to comment.