Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 9 additions & 0 deletions packages/web/src/common/values/breakpoint.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
interface PositionCardListBreakPoint {
width: number;
displayCount: number;
}

export const positionCardListBreakPoints: PositionCardListBreakPoint[] = [
{ width: 1180, displayCount: 4 },
{ width: 920, displayCount: 3 },
];
1 change: 1 addition & 0 deletions packages/web/src/common/values/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./storage-constant";
export * from "./style-constant";
export * from "./text-constant";
export * from "./launchpad-constant";
export * from "./breakpoint.constant";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useMemo } from "react";

import LoadMoreButton from "@components/common/load-more-button/LoadMoreButton";
import { pulseSkeletonStyle } from "@constants/skeleton.constant";
Expand Down Expand Up @@ -46,48 +46,59 @@ const MyPositionCardList: React.FC<MyPositionCardListProps> = ({
themeKey,
showLoadMore,
tokenPrices,
}) => (
<CardListWrapper $loading={isLoading}>
<HorizontalScrollWrapper ref={divRef} onScroll={onScroll} loading={isLoading}>
{!isLoading &&
positions.length > 0 &&
positions.map((position, idx) => (
<MyPositionCard
address={address}
tokenPrices={tokenPrices}
currentIndex={idx}
position={position}
key={idx}
movePoolDetail={movePoolDetail}
mobile={mobile}
themeKey={themeKey}
/>
))}
{isFetched &&
!isLoading &&
positions.length > 0 &&
positions.length < 4 &&
Array((width <= 1180 && width >= 768 ? 3 : 4) - positions.length)
.fill(1)
.map((_, index) => <BlankPositionCard key={index} />)}
{(!isFetched && positions.length === 0) || isLoading
? Array.from({ length: width <= 1180 && width >= 768 ? 3 : 4 }).map((_, idx) => (
}) => {
const hasPositions = positions.length > 0;
const shouldShowSkeleton = isLoading || (!isFetched && !hasPositions);
const shouldShowPositions = !isLoading && hasPositions;
const shouldShowBlankCards = isFetched && !isLoading && hasPositions && positions.length < 4;
const shouldShowLoadMoreButton = !mobile && !isLoading && showLoadMore && !!onClickLoadMore;
const shouldShowPagination = showPagination && isFetched && hasPositions && !isLoading;

const maxDisplayCount = useMemo(() => {
return width <= 1180 && width >= 768 ? 3 : 4;
}, [width]);

const blankCardCount = useMemo(() => {
if (!shouldShowBlankCards) return 0;
return maxDisplayCount - positions.length;
}, [shouldShowBlankCards, maxDisplayCount, positions.length]);

return (
<CardListWrapper $loading={isLoading}>
<HorizontalScrollWrapper ref={divRef} onScroll={onScroll} loading={isLoading}>
{shouldShowPositions &&
positions.map((position, idx) => (
<MyPositionCard
address={address}
tokenPrices={tokenPrices}
currentIndex={idx}
position={position}
key={idx}
movePoolDetail={movePoolDetail}
mobile={mobile}
themeKey={themeKey}
/>
))}
{shouldShowBlankCards &&
Array(blankCardCount)
.fill(1)
.map((_, index) => <BlankPositionCard key={index} />)}
{shouldShowSkeleton &&
Array.from({ length: maxDisplayCount }).map((_, idx) => (
<span key={idx} className="card-skeleton" css={pulseSkeletonStyle({ w: "100%", tone: "600" })} />
))
: null}
</HorizontalScrollWrapper>
{!mobile && !isLoading && showLoadMore && onClickLoadMore && (
<LoadMoreButton show={loadMore} onClick={onClickLoadMore} />
)}
))}
</HorizontalScrollWrapper>
{shouldShowLoadMoreButton && <LoadMoreButton show={loadMore} onClick={onClickLoadMore} />}

{showPagination && isFetched && positions.length !== 0 && !isLoading && (
<div className="box-indicator">
<span className="current-page">{currentIndex}</span>
<span>/</span>
<span>{positions.length}</span>
</div>
)}
</CardListWrapper>
);
{shouldShowPagination && (
<div className="box-indicator">
<span className="current-page">{currentIndex}</span>
<span>/</span>
<span>{positions.length}</span>
</div>
)}
</CardListWrapper>
);
};

export default MyPositionCardList;
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useWallet } from "@hooks/wallet/data/use-wallet";
import { useGetUsernameByAddress } from "@query/address";
import { EarnState, ThemeState } from "@states/index";
import { PoolPositionModel } from "@models/position/pool-position-model";
import { positionCardListBreakPoints } from "@common/values";

import EarnMyPositions from "../../components/earn-my-positions/EarnMyPositions";
import { PositionConverter } from "@services/converters/position";
Expand Down Expand Up @@ -233,12 +234,7 @@ const EarnMyPositionContainer: React.FC<EarnMyPositionContainerProps> = ({
return showedPosition;
}

const breakpoints = [
{ width: 1180, displayCount: 4 },
{ width: 920, displayCount: 3 },
];

for (const breakpoint of breakpoints) {
for (const breakpoint of positionCardListBreakPoints) {
if (width > breakpoint.width) {
return showedPosition.slice(0, breakpoint.displayCount);
}
Expand Down Expand Up @@ -269,6 +265,10 @@ const EarnMyPositionContainer: React.FC<EarnMyPositionContainerProps> = ({
}, Number(pools?.[0]?.totalApr ?? 0));
}, [pools]);

const showLoadMore = useMemo(() => {
return showedPosition.length > 4;
}, [showedPosition]);

return (
<EarnMyPositions
address={address}
Expand All @@ -292,7 +292,7 @@ const EarnMyPositionContainer: React.FC<EarnMyPositionContainerProps> = ({
divRef={divRef}
currentIndex={currentIndex}
showPagination={showPagination}
showLoadMore={showedPosition.length > 4}
showLoadMore={showLoadMore}
width={width}
loadMore={!isViewMorePositions}
onClickLoadMore={handleClickLoadMore}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { PositionMapper } from "@models/position/mapper/position-mapper";
import { PoolPositionModel } from "@models/position/pool-position-model";
import { ThemeState } from "@states/index";
import { PositionConverter } from "@services/converters/position";
import { positionCardListBreakPoints } from "@common/values";

const WalletPositionCardListContainer: React.FC<{ isClosed: boolean }> = ({ isClosed }) => {
const { getGnotPath } = useGnotToGnot();
Expand All @@ -35,6 +36,14 @@ const WalletPositionCardListContainer: React.FC<{ isClosed: boolean }> = ({ isCl
const divRef = useRef<HTMLDivElement | null>(null);
const { tokenPrices = {} } = useTokenData();

const [isViewMorePositions, setIsViewMorePositions] = useState(false);
const [mappedData, setMappedData] = useState<PoolPositionModel[]>([]);
const [isDataMappingLoading, setIsDataMappingLoading] = useState(true);

const handleClickLoadMore = useCallback(() => {
setIsViewMorePositions(!isViewMorePositions);
}, [isViewMorePositions]);

const handleResize = () => {
if (typeof window !== "undefined") {
if (window.innerWidth < 920) setMobile(true);
Expand Down Expand Up @@ -64,22 +73,8 @@ const WalletPositionCardListContainer: React.FC<{ isClosed: boolean }> = ({ isCl
}
}, [positionsData, width]);

const handleScroll = () => {
if (divRef.current) {
const container = divRef.current;
const currentScrollX = container.scrollLeft;
const maxScroll = container.scrollWidth - container.clientWidth;

if (currentScrollX >= maxScroll - 1) {
setCurrentIndex(positions.length);
} else {
setCurrentIndex(Math.min(Math.floor(currentScrollX / 322) + 1, positions.length));
}
}
};

const positions = useMemo(() => {
const poolPositions: PoolPositionModel[] = [];
const poolPositions = useMemo(() => {
const mappedPositions: PoolPositionModel[] = [];
positionsData.forEach(position => {
const pool = pools.find(pool => pool.poolPath === position.poolPath);
if (pool) {
Expand All @@ -96,43 +91,89 @@ const WalletPositionCardListContainer: React.FC<{ isClosed: boolean }> = ({ isCl
logoURI: getGnotPath(pool.tokenB).logoURI,
},
};
poolPositions.push(PositionMapper.makePoolPosition(position, temp));
mappedPositions.push(PositionMapper.makePoolPosition(position, temp));
}
});

return PositionConverter.convertPositions(poolPositions);
}, [pools, positionsData]);
return mappedPositions;
}, [pools, positionsData, getGnotPath]);

const openPosition = useMemo(() => {
return positions
return poolPositions
.filter(item => !item.closed)
.sort((x, y) => Number(y.positionUsdValue) - Number(x.positionUsdValue));
}, [positions]);
}, [poolPositions]);

const closedPosition = useMemo(() => {
return positions.filter(item => item.closed);
}, [positions]);
return poolPositions.filter(item => item.closed);
}, [poolPositions]);

const showedPosition = useMemo(() => {
return [...openPosition, ...(isClosed ? closedPosition : [])];
}, [closedPosition, isClosed, openPosition]);

const handleScroll = useCallback(() => {
if (divRef.current) {
const container = divRef.current;
const currentScrollX = container.scrollLeft;
const maxScroll = container.scrollWidth - container.clientWidth;

if (currentScrollX >= maxScroll - 1) {
setCurrentIndex(showedPosition.length);
} else {
setCurrentIndex(Math.min(Math.floor(currentScrollX / 322) + 1, showedPosition.length));
}
}
}, [showedPosition.length]);

const getMappedData = (): PoolPositionModel[] => {
if (isViewMorePositions) {
return showedPosition;
}

for (const breakpoint of positionCardListBreakPoints) {
if (width > breakpoint.width) {
return showedPosition.slice(0, breakpoint.displayCount);
}
}

return showedPosition;
};

const updateDataMapping = useCallback(() => {
setIsDataMappingLoading(true);
const newMappedData = getMappedData();
const convertedMappedData = PositionConverter.convertPositions(newMappedData);

setMappedData(convertedMappedData);
setIsDataMappingLoading(false);
}, [isViewMorePositions, width, showedPosition]);

useEffect(() => {
updateDataMapping();
}, [updateDataMapping]);

const showLoadMore = useMemo(() => {
return showedPosition.length > 4;
}, [showedPosition]);

return (
<MyPositionCardList
positions={showedPosition}
loadMore={false}
positions={mappedData}
loadMore={!isViewMorePositions}
isFetched={isFetchedPosition}
isLoading={loading || isLoadingPosition}
isLoading={loading || isLoadingPosition || isDataMappingLoading}
movePoolDetail={movePoolDetail}
currentIndex={currentIndex}
mobile={mobile}
width={width}
showPagination={showPagination}
showLoadMore={true}
showLoadMore={showLoadMore}
themeKey={themeKey}
divRef={divRef}
onScroll={handleScroll}
tokenPrices={tokenPrices}
onClickLoadMore={handleClickLoadMore}
/>
);
};
Expand Down
Loading