Skip to content

Commit

Permalink
[Updated] working scroll behavior, fixed infinite scroll, pool detail…
Browse files Browse the repository at this point in the history
…s show your rank if above top 4
  • Loading branch information
greedyboi committed Aug 24, 2023
1 parent 800efe5 commit 9f45ebe
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 103 deletions.
6 changes: 3 additions & 3 deletions src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ interface IProps extends React.BaseHTMLAttributes<HTMLDivElement> {
onClick?: React.MouseEventHandler<HTMLDivElement>;
}

const Card = ({ children, className, withoutPadding, flat, onClick, ...rest }: IProps) => {
const Card = React.forwardRef<HTMLDivElement, IProps>(function Card({ children, className, withoutPadding, flat, onClick, ...rest }, ref) {
return (
<div {...rest} className={`${withoutPadding ? '' : 'p-4 p-xl-5'} app-card ${flat && 'flat'} ${className} ${onClick && 'scale-hover'}`} onClick={onClick}>
<div {...rest} ref={ref} className={`${withoutPadding ? '' : 'p-4 p-xl-5'} app-card ${flat && 'flat'} ${className} ${onClick && 'scale-hover'}`} onClick={onClick}>
{children}
</div>
);
};
});

export default Card;
13 changes: 4 additions & 9 deletions src/components/Leaderboard/Leaderboard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
}

.leaderboard {
overflow: auto;
overflow: visible;
padding: 40px 40px;

@include media-breakpoint-down(md) {
Expand Down Expand Up @@ -65,15 +65,10 @@
margin-bottom: 1rem;

&.animated {
z-index: 2;
position: absolute;
margin-top: 40px;
margin-left: 40px;
margin-bottom: unset;
width: calc(100% - 80px);
@include media-breakpoint-down(md) {
width: 100%;
}
top: 0;
left: 0;
width: 100%;
}
}

Expand Down
68 changes: 61 additions & 7 deletions src/components/Leaderboard/Leaderboard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import React, { useLayoutEffect, useRef } from 'react';
import { isMobile } from 'react-device-detect';
import InfiniteScroll from 'react-infinite-scroller';
import { gsap } from 'gsap';

import { Button, Card, Loading, SmallerDecimal } from 'components';
import { Breakpoints, NavigationConstants } from 'constant';
Expand Down Expand Up @@ -34,6 +35,8 @@ const Leaderboard = (props: Props) => {
const { items, className, limit, lumWallet, price, poolId, totalDeposited, flat, userRank, hasMore, enableAnimation, withSeeMoreBtn, onBottomReached } = props;

const { width: windowWidth } = useWindowSize();
const containerRef = useRef<HTMLDivElement>(null);
const tl = useRef<gsap.core.Timeline>();

const userRankList: LeaderboardItemModel[] = [];

Expand All @@ -54,20 +57,51 @@ const Leaderboard = (props: Props) => {
}
}

useLayoutEffect(() => {
if (enableAnimation) {
const ctx = gsap.context((self) => {
const userCard = self.selector?.('.leaderboard-rank.animated');

if (userCard) {
const scrollTriggerConfig: ScrollTrigger.Vars = {
id: 'user-rank-trigger',
trigger: userCard,
start: 'bottom+=100px bottom',
end: 'bottom+=70px bottom',
endTrigger: containerRef.current,
pin: true,
pinSpacing: false,
};

tl.current = gsap.timeline({
scrollTrigger: scrollTriggerConfig,
});
}
}, containerRef);

return () => ctx.revert();
}
}, [userRank]);

const LeaderboardContainer = ({ children, containerClassName }: { children: React.ReactNode; containerClassName: string }) => {
if (isMobile || windowWidth < Breakpoints.MD) {
return <div className={containerClassName}>{children}</div>;
return (
<div className={containerClassName} ref={containerRef}>
{children}
</div>
);
}

return (
<Card flat={flat} withoutPadding className={containerClassName}>
<Card flat={flat} withoutPadding className={containerClassName} ref={containerRef}>
{children}
</Card>
);
};

const renderRow = (item: LeaderboardItemModel, index: number) => {
const amount = NumbersUtils.convertUnitNumber(item.amount);
const totalUserDeposits = userRank ? NumbersUtils.convertUnitNumber(userRank.amount) : null;

return (
<div
Expand All @@ -90,15 +124,15 @@ const Leaderboard = (props: Props) => {
</div>
) : null}
</div>
{!(lumWallet && item.address === lumWallet.address) && totalDeposited && userRank && userRank.rank > item.rank && NumbersUtils.convertUnitNumber(userRank.amount) === totalDeposited ? (
{!(lumWallet && item.address === lumWallet.address) && userRank && userRank.rank > item.rank && totalUserDeposits ? (
<Button
className='deposit-more-btn'
to={`${NavigationConstants.POOLS}/${DenomsUtils.getNormalDenom(item.nativeDenom)}/${poolId}`}
locationState={{
amountToDeposit: Math.ceil(amount - totalDeposited),
amountToDeposit: Math.ceil(amount - totalUserDeposits),
}}
>
{I18n.t('leaderboard.depositBtn', { amount: Math.ceil(amount - totalDeposited), denom: DenomsUtils.getNormalDenom(item.nativeDenom).toUpperCase() })}
{I18n.t('leaderboard.depositBtn', { amount: Math.ceil(amount - totalUserDeposits), denom: DenomsUtils.getNormalDenom(item.nativeDenom).toUpperCase() })}
</Button>
) : null}
{!(lumWallet && item.address === lumWallet.address) && totalDeposited && userRank && userRank.rank > item.rank && NumbersUtils.convertUnitNumber(userRank.amount) !== totalDeposited ? (
Expand Down Expand Up @@ -129,8 +163,28 @@ const Leaderboard = (props: Props) => {
</div>
)}
{onBottomReached ? (
<InfiniteScroll hasMore={hasMore || false} loadMore={onBottomReached} loader={<Loading key={0} />}>
<InfiniteScroll hasMore={hasMore || false} loadMore={onBottomReached} loader={<Loading key={0} />} className='position-relative'>
{(limit ? items.slice(0, limit) : items).map(renderRow)}
{enableAnimation && userRank ? (
<div className={`user-rank leaderboard-rank animated me d-flex flex-row justify-content-between align-items-center`}>
<div className='d-flex flex-row align-items-center'>
<div className='me-3 rank'>#{userRank.rank}</div>
<div className='address'>{StringsUtils.trunc(userRank.address, windowWidth < Breakpoints.SM ? 3 : 6)}</div>
</div>
<div className='position-relative d-flex flex-row align-items-center justify-content-end'>
<div className='crypto-amount me-3'>
<SmallerDecimal nb={NumbersUtils.formatTo6digit(NumbersUtils.convertUnitNumber(userRank.amount))} />{' '}
{DenomsUtils.getNormalDenom(userRank.nativeDenom).toUpperCase()}
</div>
{price ? (
<div className='usd-amount'>
$
<SmallerDecimal nb={NumbersUtils.formatTo6digit(NumbersUtils.convertUnitNumber(userRank.amount) * price)} />
</div>
) : null}
</div>
</div>
) : null}
</InfiniteScroll>
) : (
(limit ? items.slice(0, limit) : items).map(renderRow)
Expand Down
1 change: 1 addition & 0 deletions src/models/pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface PoolModel extends Pool {
nextDrawAt?: Date;
leaderboard: {
items: LeaderboardItemModel[];
page: number;
fullyLoaded: boolean;
};
currentPrizeToWin: BalanceModel | null;
Expand Down
9 changes: 6 additions & 3 deletions src/pages/MySavings/MySavings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,12 @@
}
}

.leaderboard {
animation: unset;
opacity: 1;
.leaderboard-section {
.leaderboard {
animation: unset;
opacity: 1;
padding-bottom: 100px;
}
}

#withdrawModal {
Expand Down
102 changes: 22 additions & 80 deletions src/pages/MySavings/MySavings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import numeral from 'numeral';
import { Prize } from '@lum-network/sdk-javascript/build/codec/lum/network/millions/prize';
import { DepositState } from '@lum-network/sdk-javascript/build/codec/lum/network/millions/deposit';
import { LumConstants, LumTypes } from '@lum-network/sdk-javascript';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

import Assets from 'assets';
Expand All @@ -17,7 +16,7 @@ import { Button, Card, SmallerDecimal, Lottie, Collapsible, Modal, Leaderboard,
import { Breakpoints, FirebaseConstants, NavigationConstants } from 'constant';
import { useWindowSize } from 'hooks';
import { DepositModel, LeaderboardItemModel } from 'models';
import { DenomsUtils, FontsUtils, I18n, NumbersUtils, WalletUtils, Firebase, /* StringsUtils, */ PoolsUtils } from 'utils';
import { DenomsUtils, FontsUtils, I18n, NumbersUtils, WalletUtils, Firebase, PoolsUtils } from 'utils';
import { Dispatch, RootState } from 'redux/store';
import { confettis } from 'utils/confetti';

Expand Down Expand Up @@ -57,11 +56,8 @@ const MySavings = () => {
const [userRankItems, setUserRankItems] = useState<LeaderboardItemModel[]>();

const transferOutModalRef = useRef<React.ElementRef<typeof Modal>>(null);
const containerRef = useRef<HTMLDivElement>(null);
const leaderboardSectionRef = useRef<HTMLDivElement>(null);

const tl = useRef<gsap.core.Timeline>();

const winSizes = useWindowSize();

const totalDeposited = WalletUtils.getTotalBalanceFromDeposits(deposits, prices);
Expand All @@ -81,12 +77,14 @@ const MySavings = () => {
}
};

getLeaderboardUserRank();
if (!isReloadingInfos) {
getLeaderboardUserRank();
}

if (location.state?.leaderboardPoolId && leaderboardSectionRef.current) {
leaderboardSectionRef.current.scrollIntoView();
}
}, [leaderboardPool]);
}, [isReloadingInfos, leaderboardPool, lumWallet]);

useEffect(() => {
if (pools && pools.length > 0) {
Expand All @@ -95,6 +93,12 @@ const MySavings = () => {
}
}, [pools]);

useEffect(() => {
if (leaderboardPool) {
dispatch.pools.getNextLeaderboardPage({ poolId: leaderboardPool.poolId, page: leaderboardPage, limit: 15 });
}
}, [leaderboardPage]);

useEffect(() => {
const page = activities?.currentPage;

Expand All @@ -117,45 +121,18 @@ const MySavings = () => {
}, [prizesToClaim]);

useLayoutEffect(() => {
ScrollTrigger.normalizeScroll(true);

const refreshST = () => {
ScrollTrigger.refresh();
};

const ctx = gsap.context(() => {
const leaderboardEl = document.querySelector('#my-savings .leaderboard');

const scrollTrigger: ScrollTrigger.Vars = {
trigger: leaderboardEl,
start: 'top+=120px bottom',
end: 'max',
toggleActions: 'play none none reset',
invalidateOnRefresh: true,
//markers: true,
};

tl.current = gsap.timeline().set(leaderboardEl, { position: 'static', scrollTrigger }).to(
'#my-savings .user-rank.animated',
{
position: 'fixed',
bottom: '2rem',
scrollTrigger,
},
'+=0',
);
const myCollapsibles = document.getElementsByClassName('collapsible');

const myCollapsibles = document.getElementsByClassName('collapsible');

for (const el of myCollapsibles) {
el.addEventListener('shown.bs.collapse', refreshST);
el.addEventListener('hidden.bs.collapse', refreshST);
}
}, containerRef);
for (const el of myCollapsibles) {
el.addEventListener('shown.bs.collapse', refreshST);
el.addEventListener('hidden.bs.collapse', refreshST);
}

return () => {
ctx.revert();

const myCollapsibles = document.getElementsByClassName('collapsible');

for (const el of myCollapsibles) {
Expand All @@ -165,16 +142,6 @@ const MySavings = () => {
};
}, []);

useLayoutEffect(() => {
const leaderboardEl = document.querySelector('#my-savings .leaderboard .leaderboard-rank');

if (leaderboardEl) {
gsap.set('#my-savings .user-rank.animated', {
width: leaderboardEl.clientWidth,
});
}
}, [winSizes.width]);

const renderAsset = (asset: LumTypes.Coin) => {
const icon = DenomsUtils.getIconFromDenom(asset.denom);
const normalDenom = DenomsUtils.getNormalDenom(asset.denom);
Expand Down Expand Up @@ -286,7 +253,7 @@ const MySavings = () => {
}

return (
<div id='my-savings' className='my-savings-container mt-3 mt-lg-5' ref={containerRef}>
<div id='my-savings' className='my-savings-container mt-3 mt-lg-5'>
{deposits && deposits.find((deposit) => deposit.state === DepositState.DEPOSIT_STATE_FAILURE) ? (
<Card flat withoutPadding className='d-flex flex-row align-items-center mb-5 p-4'>
<img alt='info' src={Assets.images.info} width='45' />
Expand Down Expand Up @@ -443,8 +410,8 @@ const MySavings = () => {
</Card>
</>
) : null}
{leaderboardPool && leaderboardPool.leaderboard?.items.length > 0 && (
<div ref={leaderboardSectionRef} className='position-relative'>
{leaderboardPool && leaderboardPool.leaderboard?.items.length ? (
<div ref={leaderboardSectionRef} className='leaderboard-section'>
<div className='mt-5 mb-3 d-flex flex-row align-items-center justify-content-between'>
<div className='d-flex align-items-center'>
<h2 className='mb-0'>{I18n.t('mySavings.depositorsRanking')}</h2>
Expand All @@ -467,30 +434,6 @@ const MySavings = () => {
}}
/>
</div>
{/* userRankItems && userRankItems[1] && (
<div className={`user-rank leaderboard-rank animated me d-flex flex-row justify-content-between align-items-center`}>
<div className='d-flex flex-row align-items-center'>
<div className='me-3 rank'>#{userRankItems[1].rank}</div>
<div className='address'>{StringsUtils.trunc(userRankItems[1].address, winSizes.width < Breakpoints.SM ? 3 : 6)}</div>
</div>
<div className='position-relative d-flex flex-row align-items-center justify-content-end'>
<div className='crypto-amount me-3'>
<SmallerDecimal nb={NumbersUtils.formatTo6digit(NumbersUtils.convertUnitNumber(userRankItems[1].amount))} />{' '}
{DenomsUtils.getNormalDenom(userRankItems[1].nativeDenom).toUpperCase()}
</div>
{prices[DenomsUtils.getNormalDenom(userRankItems[1].nativeDenom)] && (
<div className='usd-amount'>
$
<SmallerDecimal
nb={NumbersUtils.formatTo6digit(
NumbersUtils.convertUnitNumber(userRankItems[1].amount) * prices[DenomsUtils.getNormalDenom(userRankItems[1].nativeDenom)],
)}
/>
</div>
)}
</div>
</div>
) */}
<Leaderboard
items={leaderboardPool.leaderboard.items}
enableAnimation
Expand All @@ -505,19 +448,18 @@ const MySavings = () => {
}
poolId={leaderboardPool.poolId.toString()}
price={prices[DenomsUtils.getNormalDenom(leaderboardPool.nativeDenom)]}
hasMore={!isLoadingNextLeaderboardPage && !leaderboardPool.leaderboard.fullyLoaded}
onBottomReached={() => {
hasMore={!leaderboardPool.leaderboard.fullyLoaded}
onBottomReached={async () => {
if (isLoadingNextLeaderboardPage) {
return;
}
dispatch.pools.getNextLeaderboardPage({ poolId: leaderboardPool.poolId, page: leaderboardPage + 1, limit: 15 });
setLeaderboardPage(leaderboardPage + 1);
}}
lumWallet={lumWallet}
totalDeposited={totalDepositedCrypto}
/>
</div>
)}
) : null}
</div>
</div>
<div className='col-12 col-lg-4 col-xxl-3 position-sticky top-0'>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/PoolDetails/PoolDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ const PoolDetails = () => {
price={prices[denom || '']}
totalDeposited={WalletUtils.getTotalBalanceFromDeposits(lumWallet?.deposits)}
userRank={
userRankItems
userRankItems && userRankItems[1].rank > 4
? {
...userRankItems[1],
prev: userRankItems[0],
Expand Down
Loading

0 comments on commit 9f45ebe

Please sign in to comment.