Skip to content

Commit 5b7014a

Browse files
authored
[GSW-2407] user positions pagination (#790)
* feat: [GSW-2407] UserPositions pagination * feat: [GSW-2407] Pagination * feat:[GSW-2407] Pagination for portfolio page * feat: [GSW-2407] Pagination KeepPreviousData * fix: [GSW-2407] Pagination count
1 parent 28ada08 commit 5b7014a

File tree

15 files changed

+358
-66
lines changed

15 files changed

+358
-66
lines changed

packages/web/src/common/values/breakpoint.constant.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,17 @@ interface PositionCardListBreakPoint {
33
displayCount: number;
44
}
55

6-
export const positionCardListBreakPoints: PositionCardListBreakPoint[] = [
6+
export const POSITION_CARD_LIST_BREAKPOINTS: PositionCardListBreakPoint[] = [
77
{ width: 1180, displayCount: 4 },
88
{ width: 920, displayCount: 3 },
99
];
10+
11+
export const POSITION_CARD_BREAKPOINTS = {
12+
TABLET_MIN: 768,
13+
DESKTOP_MIN: 1180,
14+
} as const;
15+
16+
export const POSITION_CARD_DISPLAY_COUNT = {
17+
TABLET: 3,
18+
DESKTOP: 4,
19+
} as const;

packages/web/src/components/common/my-position-card-list/MyPositionCardList.tsx

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import LoadMoreButton from "@components/common/load-more-button/LoadMoreButton";
44
import { pulseSkeletonStyle } from "@constants/skeleton.constant";
55
import { PoolPositionModel } from "@models/position/pool-position-model";
66
import { TokenPriceModel } from "@models/token/token-price-model";
7+
import { DEVICE_TYPE } from "@styles/media";
78

89
import MyPositionCard from "./my-position-card/MyPositionCard";
910

1011
import { BlankPositionCard, CardListWrapper } from "./MyPositionCardList.styles";
1112
import { HorizontalScrollWrapper } from "../scroll-wrapper";
13+
import Pagination from "../pagination/Pagination";
1214

1315
interface MyPositionCardListProps {
1416
address?: string | null;
@@ -18,15 +20,20 @@ interface MyPositionCardListProps {
1820
onClickLoadMore?: () => void;
1921
positions: PoolPositionModel[];
2022
currentIndex: number;
23+
maxDisplayCount: number;
2124
movePoolDetail: (poolId: string, positionId: number) => void;
2225
mobile: boolean;
2326
divRef?: React.RefObject<HTMLDivElement>;
2427
onScroll?: () => void;
25-
showPagination: boolean;
28+
showPositionIndicator: boolean;
2629
showLoadMore: boolean;
2730
width: number;
2831
themeKey: "dark" | "light";
2932
tokenPrices: Record<string, TokenPriceModel>;
33+
currentPage?: number;
34+
totalPage?: number;
35+
movePage: (page: number) => void;
36+
limit?: number;
3037
}
3138

3239
const MyPositionCardList: React.FC<MyPositionCardListProps> = ({
@@ -37,31 +44,36 @@ const MyPositionCardList: React.FC<MyPositionCardListProps> = ({
3744
onClickLoadMore,
3845
positions,
3946
currentIndex,
47+
maxDisplayCount,
4048
movePoolDetail,
4149
mobile,
4250
divRef,
4351
onScroll,
44-
showPagination,
52+
showPositionIndicator,
4553
width,
4654
themeKey,
4755
showLoadMore,
4856
tokenPrices,
57+
currentPage,
58+
totalPage,
59+
movePage,
60+
limit,
4961
}) => {
62+
const breakpoint = width >= 920 ? DEVICE_TYPE.WEB : DEVICE_TYPE.MOBILE;
63+
5064
const hasPositions = positions.length > 0;
5165
const shouldShowSkeleton = isLoading || (!isFetched && !hasPositions);
5266
const shouldShowPositions = !isLoading && hasPositions;
53-
const shouldShowBlankCards = isFetched && !isLoading && hasPositions && positions.length < 4;
5467
const shouldShowLoadMoreButton = !mobile && !isLoading && showLoadMore && !!onClickLoadMore;
55-
const shouldShowPagination = showPagination && isFetched && hasPositions && !isLoading;
56-
57-
const maxDisplayCount = useMemo(() => {
58-
return width <= 1180 && width >= 768 ? 3 : 4;
59-
}, [width]);
68+
const shouldShowPositionIndicator = showPositionIndicator && isFetched && hasPositions && !isLoading;
69+
const shouldShowPagination = Boolean(totalPage && totalPage > 1 && !loadMore);
70+
const targetCount = shouldShowPagination && limit ? limit : maxDisplayCount;
71+
const shouldShowBlankCards = isFetched && !isLoading && hasPositions && positions.length < maxDisplayCount;
6072

6173
const blankCardCount = useMemo(() => {
6274
if (!shouldShowBlankCards) return 0;
63-
return maxDisplayCount - positions.length;
64-
}, [shouldShowBlankCards, maxDisplayCount, positions.length]);
75+
return targetCount - positions.length;
76+
}, [shouldShowBlankCards, targetCount, positions.length]);
6577

6678
return (
6779
<CardListWrapper $loading={isLoading}>
@@ -88,9 +100,19 @@ const MyPositionCardList: React.FC<MyPositionCardListProps> = ({
88100
<span key={idx} className="card-skeleton" css={pulseSkeletonStyle({ w: "100%", tone: "600" })} />
89101
))}
90102
</HorizontalScrollWrapper>
91-
{shouldShowLoadMoreButton && <LoadMoreButton show={loadMore} onClick={onClickLoadMore} />}
92103

93104
{shouldShowPagination && (
105+
<Pagination
106+
currentPage={currentPage || 1}
107+
totalPage={totalPage || 1}
108+
onPageChange={movePage}
109+
siblingCount={breakpoint !== DEVICE_TYPE.MOBILE ? 2 : 1}
110+
/>
111+
)}
112+
113+
{shouldShowLoadMoreButton && <LoadMoreButton show={loadMore} onClick={onClickLoadMore} />}
114+
115+
{shouldShowPositionIndicator && (
94116
<div className="box-indicator">
95117
<span className="current-page">{currentIndex}</span>
96118
<span>/</span>

packages/web/src/hooks/pool/data/use-position-data.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export interface UsePositionDataOption {
1010
address?: string;
1111
isClosed?: boolean;
1212
poolPath?: string | null;
13+
page?: number;
14+
limit?: number;
15+
withClosed?: boolean;
1316
queryOption?: UseQueryOptions<PositionModel[], Error, PositionModel[], QueryKey>;
1417
}
1518

@@ -27,20 +30,27 @@ export const usePositionData = (options?: UsePositionDataOption) => {
2730
isError,
2831
isFetched: isFetchedPosition,
2932
isLoading: isLoadingPosition,
33+
isFetching: isFetchingPosition,
34+
isPreviousData,
3035
} = useGetPositionsByAddress({
3136
address: fetchedAddress as string,
3237
isClosed: options?.isClosed,
3338
poolPath: options?.poolPath,
39+
page: options?.page,
40+
limit: options?.limit,
41+
withClosed: options?.withClosed,
3442
});
3543

44+
const { totalCount: totalPositionCount = 0, positions: rawPositions = [] } = data ?? {};
45+
3646
const { isLoading: isCommonLoading } = useLoading();
3747

3848
const {
3949
data: positions = [],
4050
isFetched: isFetchedPoolPositions,
4151
isLoading: isLoadingPoolPositions,
4252
refetch: refetchPooPositions,
43-
} = useMakePoolPositions(data, pools, isFetchedPosition);
53+
} = useMakePoolPositions(rawPositions, pools, isFetchedPosition);
4454

4555
const availableStake = useMemo(() => {
4656
if (!isFetchedPoolPositions) {
@@ -79,17 +89,19 @@ export const usePositionData = (options?: UsePositionDataOption) => {
7989

8090
useEffect(() => {
8191
refetchPooPositions();
82-
}, [data, pools]);
92+
}, [data, pools, refetchPooPositions]);
8393

8494
return {
8595
availableStake,
8696
isError,
8797
positions,
98+
totalPositionCount,
8899
refetch,
89100
checkStakedPool,
90101
getPositions,
91102
isFetchedPosition: isFetchedPosition && isFetchedPoolPositions,
92103
loading,
93104
isLoadingPool,
105+
isPageChanging: isFetchingPosition && isPreviousData,
94106
};
95107
};

packages/web/src/layouts/earn/components/earn-my-positions/EarnMyPositions.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export interface EarnMyPositionsProps {
3030
divRef: React.RefObject<HTMLDivElement>;
3131
onScroll: () => void;
3232
currentIndex: number;
33-
showPagination: boolean;
33+
maxDisplayCount: number;
34+
showPositionIndicator: boolean;
3435
showLoadMore: boolean;
3536
width: number;
3637
loadMore: boolean;
@@ -42,6 +43,10 @@ export interface EarnMyPositionsProps {
4243
tokenPrices: Record<string, TokenPriceModel>;
4344
highestApr: number;
4445
onOpenVideoGuide: (type: "POSITION") => void;
46+
currentPage?: number;
47+
totalPage?: number;
48+
movePage: (page: number) => void;
49+
limit?: number;
4550
}
4651

4752
const EarnMyPositions: React.FC<EarnMyPositionsProps> = ({
@@ -65,7 +70,8 @@ const EarnMyPositions: React.FC<EarnMyPositionsProps> = ({
6570
onScroll,
6671
divRef,
6772
currentIndex,
68-
showPagination,
73+
maxDisplayCount,
74+
showPositionIndicator,
6975
showLoadMore,
7076
width,
7177
loadMore,
@@ -77,6 +83,10 @@ const EarnMyPositions: React.FC<EarnMyPositionsProps> = ({
7783
tokenPrices,
7884
highestApr,
7985
onOpenVideoGuide,
86+
currentPage,
87+
totalPage,
88+
movePage,
89+
limit,
8090
}) => (
8191
<EarnMyPositionswrapper>
8292
<EarnMyPositionsHeader
@@ -110,7 +120,8 @@ const EarnMyPositions: React.FC<EarnMyPositionsProps> = ({
110120
divRef={divRef}
111121
onScroll={onScroll}
112122
currentIndex={currentIndex}
113-
showPagination={showPagination}
123+
maxDisplayCount={maxDisplayCount}
124+
showPositionIndicator={showPositionIndicator}
114125
showLoadMore={showLoadMore}
115126
width={width}
116127
loadMore={loadMore}
@@ -119,6 +130,10 @@ const EarnMyPositions: React.FC<EarnMyPositionsProps> = ({
119130
account={account}
120131
tokenPrices={tokenPrices}
121132
highestApr={highestApr}
133+
currentPage={currentPage}
134+
totalPage={totalPage}
135+
movePage={movePage}
136+
limit={limit}
122137
/>
123138
</EarnMyPositionswrapper>
124139
);

packages/web/src/layouts/earn/components/earn-my-positions/earn-my-positions-content/EarnMyPositionsContent.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React from "react";
22

3-
import MyPositionCardList from "@components/common/my-position-card-list/MyPositionCardList";
43
import { AccountModel } from "@models/account/account-model";
54
import { PoolPositionModel } from "@models/position/pool-position-model";
65
import { TokenPriceModel } from "@models/token/token-price-model";
76

87
import EarnMyPositionNoLiquidity from "./earn-my-positions-no-liquidity/EarnMyPositionNoLiquidity";
98
import EarnMyPositionsUnconnected from "./earn-my-positions-unconnected/EarnMyPositionsUnconnected";
109
import OtherPositionNoLiquidity from "./other-positions-no-liquidity/OtherPositionNoLiquidity";
10+
import MyPositionCardList from "@components/common/my-position-card-list/MyPositionCardList";
1111

1212
export interface EarnMyPositionContentProps {
1313
address?: string | null;
@@ -24,7 +24,8 @@ export interface EarnMyPositionContentProps {
2424
divRef: React.RefObject<HTMLDivElement>;
2525
onScroll: () => void;
2626
currentIndex: number;
27-
showPagination: boolean;
27+
maxDisplayCount: number;
28+
showPositionIndicator: boolean;
2829
showLoadMore: boolean;
2930
width: number;
3031
loadMore: boolean;
@@ -33,6 +34,10 @@ export interface EarnMyPositionContentProps {
3334
account: AccountModel | null;
3435
tokenPrices: Record<string, TokenPriceModel>;
3536
highestApr: number;
37+
currentPage?: number;
38+
totalPage?: number;
39+
movePage: (page: number) => void;
40+
limit?: number;
3641
}
3742

3843
const EarnMyPositionsContent: React.FC<EarnMyPositionContentProps> = ({
@@ -49,7 +54,8 @@ const EarnMyPositionsContent: React.FC<EarnMyPositionContentProps> = ({
4954
divRef,
5055
onScroll,
5156
currentIndex,
52-
showPagination,
57+
maxDisplayCount,
58+
showPositionIndicator,
5359
showLoadMore,
5460
width,
5561
loadMore,
@@ -58,6 +64,10 @@ const EarnMyPositionsContent: React.FC<EarnMyPositionContentProps> = ({
5864
account,
5965
tokenPrices,
6066
highestApr,
67+
currentPage,
68+
totalPage,
69+
movePage,
70+
limit,
6171
}) => {
6272
if (isOtherPosition && positions.length === 0 && !loading) {
6373
return <OtherPositionNoLiquidity account={account} />;
@@ -77,17 +87,22 @@ const EarnMyPositionsContent: React.FC<EarnMyPositionContentProps> = ({
7787
isFetched={fetched}
7888
isLoading={loading}
7989
currentIndex={currentIndex}
90+
maxDisplayCount={maxDisplayCount}
8091
movePoolDetail={movePoolDetail}
8192
mobile={mobile}
8293
divRef={divRef}
8394
onScroll={onScroll}
84-
showPagination={showPagination}
95+
showPositionIndicator={showPositionIndicator}
8596
showLoadMore={showLoadMore}
8697
width={width}
8798
loadMore={loadMore}
8899
onClickLoadMore={onClickLoadMore}
89100
themeKey={themeKey}
90101
tokenPrices={tokenPrices}
102+
currentPage={currentPage}
103+
totalPage={totalPage}
104+
movePage={movePage}
105+
limit={limit}
91106
/>
92107
);
93108
};

packages/web/src/layouts/earn/components/earn-my-positions/earn-my-positions-header/EarnMyPositionsHeader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ const EarnMyPositionsHeader: React.FC<EarnMyPositionsHeaderProps> = ({
7373
</span>
7474
<span>{`${t("Earn:positions.title", {
7575
context: "other",
76-
})} (${positionLength})`}</span>
76+
})} (${positionLength.toLocaleString()})`}</span>
7777
</>
7878
);
7979
}
8080

8181
if (connected) {
82-
return <span>{`${t("Earn:positions.title")} (${positionLength})`}</span>;
82+
return <span>{`${t("Earn:positions.title")} (${positionLength.toLocaleString()})`}</span>;
8383
}
8484

8585
return <span>{t("Earn:positions.title")}</span>;

0 commit comments

Comments
 (0)