diff --git a/app/src/@shared/components/Pagination/index.tsx b/app/src/@shared/components/Pagination/index.tsx index 739d072f..29c9bfaf 100644 --- a/app/src/@shared/components/Pagination/index.tsx +++ b/app/src/@shared/components/Pagination/index.tsx @@ -7,7 +7,7 @@ import { ARIA_LABEL } from '@shared/constants/accessibility'; import { Clickable, HStack } from '@shared/ui-kit'; import { PageButton } from './PageButton'; -type PaginationProps = { +export type PaginationProps = { currPageNumber: number; onPageNumberChange: (pageNumber: number) => void; totalPageNumber: number; diff --git a/app/src/Leaderboard/components/Leaderboard/LeaderboardHeader.tsx b/app/src/Leaderboard/components/Leaderboard/LeaderboardHeader.tsx deleted file mode 100644 index 8a6902b2..00000000 --- a/app/src/Leaderboard/components/Leaderboard/LeaderboardHeader.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import styled from '@emotion/styled'; -import { useAtomValue } from 'jotai'; - -import { leaderboardPromoListAtom } from '@/Leaderboard/atoms/leaderboardPromoListAtom'; -import { LeaderboardDateDescriptor } from '@/Leaderboard/components/Leaderboard/LeaderboardDateDescriptor'; -import { PromoSelectList } from '@/Leaderboard/components/PromoSelect/PromoSelectList'; -import { Select, SelectContent, SelectTrigger } from '@shared/ui-kit'; -import { mq } from '@shared/utils/facepaint/mq'; -import { numberWithUnitFormatter } from '@shared/utils/formatters/numberWithUnitFormatter'; - -type LeaderboardHeaderProps = { - currSegmentedControlIndex?: number; - currPromo: number | null; - onPromoChange: (promo: string | null) => void; - start: Date; - end: Date; -}; - -export function LeaderboardHeader({ - currSegmentedControlIndex, - currPromo, - onPromoChange, - start, - end, -}: LeaderboardHeaderProps) { - const promoList = useAtomValue(leaderboardPromoListAtom); - - if (promoList === null) { - throw new Error('promoList is null'); - } - - const unit = '기'; - - return ( - - - - - ); -} - -const Layout = styled.div` - width: 100%; - display: flex; - align-items: center; - - ${mq({ - flexDirection: ['column', 'row'], - justifyContent: ['center', 'space-between'], - gap: ['2rem', 0], - })} -`; diff --git a/app/src/Leaderboard/components/LeaderboardPagination.tsx b/app/src/Leaderboard/components/LeaderboardPagination.tsx new file mode 100644 index 00000000..b8c83fa3 --- /dev/null +++ b/app/src/Leaderboard/components/LeaderboardPagination.tsx @@ -0,0 +1,14 @@ +import { + Pagination, + type PaginationProps, +} from '@shared/components/Pagination'; +import { useDeviceType } from '@shared/utils/react-responsive/useDeviceType'; + +type LeaderboardPaginationProps = Omit; + +export function LeaderboardPagination(props: LeaderboardPaginationProps) { + const device = useDeviceType(); + const pagePerRow = device === 'mobile' ? 5 : 10; + + return ; +} diff --git a/app/src/Leaderboard/components/PromoSelect/index.tsx b/app/src/Leaderboard/components/PromoSelect/index.tsx new file mode 100644 index 00000000..7a4ba413 --- /dev/null +++ b/app/src/Leaderboard/components/PromoSelect/index.tsx @@ -0,0 +1,31 @@ +import { Promo } from '@shared/__generated__/graphql'; +import { Select, SelectContent, SelectTrigger } from '@shared/ui-kit'; +import { numberWithUnitFormatter } from '@shared/utils/formatters/numberWithUnitFormatter'; + +import { PromoSelectList } from './PromoSelectList'; + +type PromoSelectProps = { + curr: number | null; + list: Promo[]; + onChange: (promo: string | null) => void; +}; + +export function PromoSelect({ curr, list, onChange }: PromoSelectProps) { + const unit = '기'; + + return ( + + ); +} diff --git a/app/src/Leaderboard/components/skeletons/LeaderboardResultSkeleton.tsx b/app/src/Leaderboard/components/skeletons/LeaderboardResultSkeleton.tsx index de9a8b71..0830cd6f 100644 --- a/app/src/Leaderboard/components/skeletons/LeaderboardResultSkeleton.tsx +++ b/app/src/Leaderboard/components/skeletons/LeaderboardResultSkeleton.tsx @@ -3,7 +3,7 @@ import { LeaderboardListItemSkeleteon } from './LeaderboardListItemSkeleton'; export const LeaderboardResultSkeleton = () => { return ( - + {Array.from({ length: 50 }, (x) => x).map((_, idx) => ( diff --git a/app/src/Leaderboard/pages/Comment/components/LeaderboardCommentResult.tsx b/app/src/Leaderboard/pages/Comment/components/LeaderboardCommentResult.tsx new file mode 100644 index 00000000..b40f9be8 --- /dev/null +++ b/app/src/Leaderboard/pages/Comment/components/LeaderboardCommentResult.tsx @@ -0,0 +1,96 @@ +import { QueryResult } from '@apollo/client'; +import { useAtomValue } from 'jotai'; +import { useSearchParams } from 'react-router-dom'; + +import { leaderboardArgsAtom } from '@/Leaderboard/atoms/leaderboardArgsAtom'; +import { Leaderboard } from '@/Leaderboard/components/Leaderboard'; +import { LeaderboardDateDescriptor } from '@/Leaderboard/components/Leaderboard/LeaderboardDateDescriptor'; +import { LeaderboardPagination } from '@/Leaderboard/components/LeaderboardPagination'; +import { LeaderboardResultSkeleton } from '@/Leaderboard/components/skeletons/LeaderboardResultSkeleton'; +import { SIZE_PER_PAGE } from '@/Leaderboard/constants/defaultOptions'; +import { LEADERBOARD_PARAM_KEYS } from '@/Leaderboard/constants/paramKeys'; +import { + DateTemplate, + GetLeaderboardCommentQuery, +} from '@shared/__generated__/graphql'; +import { FullPageApolloErrorView } from '@shared/components/ApolloError/FullPageApolloErrorView'; +import { HStack, Spacer, VStack } from '@shared/ui-kit'; + +type LeaderboardCommentResultProps = { + result: QueryResult< + GetLeaderboardCommentQuery, + { + dateTemplate: DateTemplate; + pageNumber: number; + promo: number | null; + pageSize: number; + } + >; +}; + +export function LeaderboardCommentResult({ + result: { loading, error, data }, +}: LeaderboardCommentResultProps) { + const [_, setSearchParams] = useSearchParams(); + const params = new URLSearchParams(); + + const { PROMO, PAGE } = LEADERBOARD_PARAM_KEYS; + + const leaderboardArgs = useAtomValue(leaderboardArgsAtom); + + if (leaderboardArgs === null) { + throw new Error('leaderboardArgs is null'); + } + + const { promo, pageNumber } = leaderboardArgs; + + function handlePageNumberChange(pageNumber: number) { + if (promo) { + params.set(PROMO, promo.toString()); + } + params.set(PAGE, pageNumber.toString()); + + setSearchParams(params); + } + + if (loading) { + return ; + } + if (error) { + return ; + } + if (!data) { + return ; + } + + const { + data: { + me, + totalRanking: { nodes, totalCount }, + }, + start, + end, + } = data.getLeaderboardComment.byDateTemplate; + + const unit = '자'; + + return ( + + + + + + + + + + + ); +} diff --git a/app/src/Leaderboard/pages/Comment/index.tsx b/app/src/Leaderboard/pages/Comment/index.tsx index 6152ba31..2f22d6e0 100644 --- a/app/src/Leaderboard/pages/Comment/index.tsx +++ b/app/src/Leaderboard/pages/Comment/index.tsx @@ -3,28 +3,21 @@ import { useAtomValue } from 'jotai'; import { useSearchParams } from 'react-router-dom'; import { leaderboardArgsAtom } from '@/Leaderboard/atoms/leaderboardArgsAtom'; -import { Leaderboard } from '@/Leaderboard/components/Leaderboard'; -import { LeaderboardHeader } from '@/Leaderboard/components/Leaderboard/LeaderboardHeader'; -import { LeaderboardResultSkeleton } from '@/Leaderboard/components/skeletons/LeaderboardResultSkeleton'; -import { - LEADERBOARD_DEFAULT_OPTIONS, - SIZE_PER_PAGE, -} from '@/Leaderboard/constants/defaultOptions'; +import { leaderboardPromoListAtom } from '@/Leaderboard/atoms/leaderboardPromoListAtom'; +import { PromoSelect } from '@/Leaderboard/components/PromoSelect'; +import { LEADERBOARD_DEFAULT_OPTIONS } from '@/Leaderboard/constants/defaultOptions'; import { LEADERBOARD_PARAM_KEYS } from '@/Leaderboard/constants/paramKeys'; import { Footer } from '@core/components/Footer'; import { DateTemplate } from '@shared/__generated__/graphql'; -import { FullPageApolloErrorView } from '@shared/components/ApolloError/FullPageApolloErrorView'; -import { Pagination } from '@shared/components/Pagination'; import { Seo } from '@shared/components/Seo'; -import { DeferredComponent, VStack } from '@shared/ui-kit'; -import { useDeviceType } from '@shared/utils/react-responsive/useDeviceType'; +import { HStack, VStack } from '@shared/ui-kit'; +import { LeaderboardCommentResult } from './components/LeaderboardCommentResult'; import { GET_LEADERBOARD_COMMENT } from './queries/getLeaderboardComment'; export default function LeaderboardCommentPage() { - const device = useDeviceType(); const [_, setSearchParams] = useSearchParams(); - const { PAGE, PROMO } = LEADERBOARD_PARAM_KEYS; + const { PROMO } = LEADERBOARD_PARAM_KEYS; const leaderboardArgs = useAtomValue(leaderboardArgsAtom); @@ -32,7 +25,13 @@ export default function LeaderboardCommentPage() { throw new Error('leaderboardArgs is null'); } - const { loading, error, data } = useQuery(GET_LEADERBOARD_COMMENT, { + const promoList = useAtomValue(leaderboardPromoListAtom); + + if (promoList === null) { + throw new Error('promoList is null'); + } + + const result = useQuery(GET_LEADERBOARD_COMMENT, { variables: { ...LEADERBOARD_DEFAULT_OPTIONS, ...leaderboardArgs, @@ -40,7 +39,7 @@ export default function LeaderboardCommentPage() { }, }); - const { promo, pageNumber } = leaderboardArgs; + const { promo } = leaderboardArgs; function handlePromoChange(promo: string | null) { const params = new URLSearchParams(); @@ -52,69 +51,18 @@ export default function LeaderboardCommentPage() { setSearchParams(params); } - function handlePageNumberChange(pageNumber: number) { - const params = new URLSearchParams(); - - if (promo) { - params.set(PROMO, promo.toString()); - } - params.set(PAGE, pageNumber.toString()); - - setSearchParams(params); - } - - if (loading) { - return ( - - - - ); - } - if (error) { - return ( - - - - ); - } - if (!data) { - return ( - - - - ); - } - - const { - data: { - me, - totalRanking: { nodes, totalCount }, - }, - start, - end, - } = data.getLeaderboardComment.byDateTemplate; - - const unit = '자'; - return ( <> - - - + + - - - + +