Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leaderboard Page #177

Merged
merged 54 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
49e49a0
feat: add leaderboard page
teodorus-nathaniel Jan 18, 2024
7fda340
refactor: move leaderboard queries and slices to its own folder
teodorus-nathaniel Jan 19, 2024
37b05f5
feat: integrate user statistics data
teodorus-nathaniel Jan 19, 2024
46347da
refactor: extract component for reward history
teodorus-nathaniel Jan 19, 2024
ff4a155
feat: integrate user leaderboard page with api
teodorus-nathaniel Jan 19, 2024
9adb11a
feat: create table for leaderboard
teodorus-nathaniel Jan 19, 2024
c49a4f2
Merge branch 'main' into deploy/leaderboard-page
teodorus-nathaniel Jan 22, 2024
ee06e51
chore: remove logs
teodorus-nathaniel Jan 22, 2024
44009ca
fix: not getting cached data if its in server side
teodorus-nathaniel Jan 22, 2024
e825370
fix: use updated top users query
teodorus-nathaniel Jan 22, 2024
4a565d7
feat: make leaderboard page responsive
teodorus-nathaniel Jan 22, 2024
7a144d8
fix: style issue for loader in leaderboard table
teodorus-nathaniel Jan 22, 2024
084d3b5
refactor: move common components to own files
teodorus-nathaniel Jan 22, 2024
7d306e2
chore: ignore tsconfig buildinfo
teodorus-nathaniel Jan 22, 2024
27bcb45
feat: integrate general leaderboard
teodorus-nathaniel Jan 22, 2024
c7c420a
feat: add back see more button in top users
teodorus-nathaniel Jan 22, 2024
9a1774f
fix: remove unnecessary classname
teodorus-nathaniel Jan 22, 2024
f61f25b
feat: change implementation of leaderboard table to usual rendering
teodorus-nathaniel Jan 22, 2024
daf7ced
feat: integrate leaderboard api
teodorus-nathaniel Jan 23, 2024
b312ee3
Merge branch 'main' of https://github.com/dappforce/polkaverse into d…
teodorus-nathaniel Jan 23, 2024
f428528
fix: overflow of name in table
teodorus-nathaniel Jan 23, 2024
8515e95
Merge branch 'fix/postpage' into deploy/leaderboard-page
teodorus-nathaniel Jan 23, 2024
e7903e2
feat: add leaderboard modal
teodorus-nathaniel Jan 23, 2024
1a8fb9b
feat: add tab state in url
teodorus-nathaniel Jan 23, 2024
b2391fd
feat: show tabs in general leaderboard
teodorus-nathaniel Jan 23, 2024
4df05ef
chore: update wording
teodorus-nathaniel Jan 23, 2024
ebdea8c
chore: make sidebar not collapsible
teodorus-nathaniel Jan 23, 2024
e31b407
feat: add active staking menu in sidebar
teodorus-nathaniel Jan 23, 2024
8988f81
chore: update link in leaderboard table to account instead of space
teodorus-nathaniel Jan 23, 2024
faa8b9f
feat: integrate draftReward
teodorus-nathaniel Jan 23, 2024
77938d6
fix: remove refetching of reward to not have race condition with opti…
teodorus-nathaniel Jan 23, 2024
1922ab5
refactor: use url search params instead of state for tab
teodorus-nathaniel Jan 23, 2024
1fcd207
style: better mode text style
teodorus-nathaniel Jan 23, 2024
3892784
style: better style for link in leaderboard name
teodorus-nathaniel Jan 23, 2024
3e41206
fix: loading skeleton in leaderboard modal
teodorus-nathaniel Jan 24, 2024
ad6130e
style: make color muted for user without name
teodorus-nathaniel Jan 24, 2024
06eca6c
style: add leaderboard row active state
teodorus-nathaniel Jan 24, 2024
bd4723e
refactor: move leaderboard table to common folder
teodorus-nathaniel Jan 24, 2024
2b30677
Merge branch 'main' of https://github.com/dappforce/polkaverse into d…
teodorus-nathaniel Jan 24, 2024
efe0377
feat: add tabs to connect stats with leaderboard
teodorus-nathaniel Jan 24, 2024
ddfa344
feat: adjust position of labels and colors of mode
teodorus-nathaniel Jan 24, 2024
f31a853
refactor: change query name from tab to role
teodorus-nathaniel Jan 24, 2024
1e68d9b
style: always show decimals in table
teodorus-nathaniel Jan 24, 2024
da35216
chore: change table limit to 10
teodorus-nathaniel Jan 24, 2024
b05e5db
fix: race condition for loading state
teodorus-nathaniel Jan 24, 2024
d5490c8
feat: add my stats button
teodorus-nathaniel Jan 24, 2024
00aa876
chore: remove active staking sidebar menu
teodorus-nathaniel Jan 24, 2024
245da88
feat: make avatar and name in leaderboard clickable
teodorus-nathaniel Jan 24, 2024
551fab1
chore: update wording for other account stats
teodorus-nathaniel Jan 24, 2024
7e649bc
style: adjust padding
teodorus-nathaniel Jan 24, 2024
dff170d
refactor: remove unused codes
teodorus-nathaniel Jan 24, 2024
64e8fbb
feat: add write something card in posts tab
teodorus-nathaniel Jan 24, 2024
a8d21b5
fix: skeleton in modal
teodorus-nathaniel Jan 24, 2024
41a2fec
chore: remove excess commas in balance
teodorus-nathaniel Jan 24, 2024
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,5 @@ out
# cypress videos
cypress/videos
cypress/screenshots

tsconfig.tsbuildinfo
15 changes: 11 additions & 4 deletions src/components/common/balances/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,21 @@ function format(
_isShort?: boolean,
precision?: number,
withMutedDecimals = true,
alwaysShowDecimals = false,
): React.ReactNode {
const [prefix, postfix] = formatBalance(value, {
// Remove any excess decimals, because this expects big integers
const balanceValue = value.toString().split('.')[0]

const [prefix, postfix] = formatBalance(balanceValue, {
forceUnit: '-',
decimals,
withSi: false,
withZero: true,
}).split('.')
const isShort = _isShort || (withSi && prefix.length >= K_LENGTH)
const isShort = _isShort || (withSi && prefix.length >= K_LENGTH && !alwaysShowDecimals)

if (prefix.length > M_LENGTH) {
const balance = formatBalance(value, { decimals, withUnit: false })
if (prefix.length > M_LENGTH && !alwaysShowDecimals) {
const balance = formatBalance(balanceValue, { decimals, withUnit: false })
return (
<>
{balance}&nbsp;{currency}
Expand Down Expand Up @@ -70,6 +74,7 @@ type FormatBalanceProps = BareProps & {
isShort?: boolean
precision?: number
withMutedDecimals?: boolean
alwaysShowDecimals?: boolean
}

export const FormatBalance = ({
Expand All @@ -80,6 +85,7 @@ export const FormatBalance = ({
className,
precision,
withMutedDecimals = true,
alwaysShowDecimals,
...bareProps
}: FormatBalanceProps) => {
if (!value) return null
Expand All @@ -94,6 +100,7 @@ export const FormatBalance = ({
isShort,
precision,
withMutedDecimals,
alwaysShowDecimals,
)

return (
Expand Down
7 changes: 6 additions & 1 deletion src/components/creators/MobileStakerRewardDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ function StakerRewardDashboard(props: MobileStakerRewardDashboardProps) {
<div className={clsx(styles.Gradient, isOpenClassName)} />
</div>
<div className={clsx(styles.RewardInfo, isOpenClassName)}>
<StakerRewardInfo size='small' className='pt-1 position-relative' style={{ zIndex: 1 }} />
<StakerRewardInfo
withOffsetForFooterButton
size='small'
className='pt-1 position-relative'
style={{ zIndex: 1 }}
/>
<div className={clsx(styles.GradientOuter, isOpenClassName)} />
</div>
</div>
Expand Down
90 changes: 90 additions & 0 deletions src/components/creators/RewardHistoryModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { ModalProps, Skeleton } from 'antd'
import clsx from 'clsx'
import { ComponentProps, useMemo } from 'react'
import { FormatBalance } from 'src/components/common/balances'
import { formatDate } from 'src/components/utils'
import CustomModal from 'src/components/utils/CustomModal'
import { MutedSpan } from 'src/components/utils/MutedText'
import { useFetchUserRewardHistory } from 'src/rtk/features/activeStaking/hooks'
import { RewardHistory } from 'src/rtk/features/activeStaking/rewardHistorySlice'

export type RewardHistoryModalProps = Pick<ModalProps, 'visible' | 'onCancel'>

export default function RewardHistoryModal({ onCancel, visible }: RewardHistoryModalProps) {
const { data, loading } = useFetchUserRewardHistory(undefined, { enabled: visible })
const creatorRewards = data?.rewards.filter(reward => BigInt(reward.creatorReward) > 0)

return (
<CustomModal title='Active Staking History' visible={visible} onCancel={onCancel}>
<RewardHistoryPanel
title='Staker Rewards'
loading={loading}
rewardHistory={data}
rewardType='staker'
/>

{(creatorRewards?.length ?? 0) > 0 && (
<RewardHistoryPanel
title='Creator Rewards'
rewardHistory={data}
loading={loading}
rewardType='creator'
/>
)}
</CustomModal>
)
}

export function RewardHistoryPanel({
loading,
rewardHistory,
rewardType,
title,
...props
}: {
title: string
rewardHistory: RewardHistory | undefined
loading: boolean | undefined
rewardType: 'staker' | 'creator'
} & ComponentProps<'div'>) {
const rewards = useMemo(() => {
if (rewardType === 'staker') return rewardHistory?.rewards ?? []
return rewardHistory?.rewards.filter(reward => BigInt(reward.creatorReward) > 0) ?? []
}, [rewardHistory, rewardType])

return (
<div {...props} className={clsx('d-flex flex-column', props.className)}>
<MutedSpan className='mb-1 FontWeightSemibold'>{title}</MutedSpan>
<div className='d-flex flex-column GapTiny'>
{(() => {
if (loading) return <Skeleton />
if (rewards.length === 0) return <span className='ColorMuted'>No rewards yet</span>

return rewards.map(reward => {
const usedRewardValue = rewardType === 'creator' ? reward.creatorReward : reward.reward
return (
<div
className='d-flex align-items-center justify-content-between GapSmall'
key={reward.week}
>
<span className='ColorMuted FontSmall'>
{formatDate(reward.startDate, 'DD.MM.YY')} -{' '}
{formatDate(reward.endDate, 'DD.MM.YY')}
</span>
<span className='FontWeightSemibold' style={{ whiteSpace: 'nowrap' }}>
+{' '}
<FormatBalance
currency='SUB'
decimals={10}
value={usedRewardValue}
precision={2}
/>
</span>
</div>
)
})
})()}
</div>
</div>
)
}
34 changes: 19 additions & 15 deletions src/components/creators/TopUsersCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Skeleton } from 'antd'
import { Button, Skeleton } from 'antd'
import clsx from 'clsx'
import { ComponentProps, CSSProperties, useMemo } from 'react'
import { IoChevronForward } from 'react-icons/io5'
import { useFetchProfileSpaces, useSelectProfileSpace, useSelectSpace } from 'src/rtk/app/hooks'
import { useFetchTopUsers } from 'src/rtk/features/activeStaking/hooks'
import { useFetchTopUsers } from 'src/rtk/features/leaderboard/hooks'
import { useMyAddress } from '../auth/MyAccountsContext'
import { useIsMobileWidthOrDevice } from '../responsive'
import { SpaceAvatar } from '../spaces/helpers'
import ViewSpaceLink from '../spaces/ViewSpaceLink'
Expand All @@ -12,6 +14,7 @@ import Segment from '../utils/Segment'
export type TopUsersCardProps = ComponentProps<'div'>

export default function TopUsersCard({ ...props }: TopUsersCardProps) {
const myAddress = useMyAddress()
const { data, loading } = useFetchTopUsers()
const isMobile = useIsMobileWidthOrDevice()

Expand All @@ -25,17 +28,18 @@ export default function TopUsersCard({ ...props }: TopUsersCardProps) {

const isLoading = loading || !data || loadingSpaces

// const seeMoreButton = (
// <Button
// type='primary'
// ghost
// className='p-0 GapMini d-flex align-items-center'
// style={{ height: 'auto', border: 'none', boxShadow: 'none' }}
// >
// <span>See more</span>
// <IoChevronForward />
// </Button>
// )
const seeMoreButton = (
<Button
type='primary'
ghost
className='p-0 GapMini d-flex align-items-center'
href={myAddress ? `/leaderboard/${myAddress}` : '/leaderboard'}
style={{ height: 'auto', border: 'none', boxShadow: 'none' }}
>
<span>See more</span>
<IoChevronForward />
</Button>
)

const content = isLoading ? (
<Skeleton />
Expand All @@ -45,7 +49,7 @@ export default function TopUsersCard({ ...props }: TopUsersCardProps) {
<div className='d-flex align-items-center FontWeightSemibold GapMini'>
<span className='FontSemilarge'>Top users (last 24h)</span>
</div>
{/* {isMobile && seeMoreButton} */}
{isMobile && seeMoreButton}
</div>
<div
className={clsx('mt-2', isMobile && 'GapNormal')}
Expand All @@ -71,7 +75,7 @@ export default function TopUsersCard({ ...props }: TopUsersCardProps) {
</div>
</div>
</div>
{/* {!isMobile && <div className='d-flex justify-content-center mt-2'>{seeMoreButton}</div>} */}
{!isMobile && <div className='d-flex justify-content-center mt-2'>{seeMoreButton}</div>}
</>
)

Expand Down
18 changes: 2 additions & 16 deletions src/components/creators/common/NumberSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
import { Skeleton } from 'antd'
import SpanSkeleton from 'src/components/utils/SpanSkeleton'

export default function NumberSkeleton() {
return (
<div className='d-flex align-items-center'>
<Skeleton.Input
style={{
height: '1em',
width: '3ch',
marginRight: '4px',
borderRadius: '20px',
position: 'relative',
top: '1px',
display: 'block',
}}
/>
</div>
)
return <SpanSkeleton style={{ width: '3ch' }} />
}
50 changes: 39 additions & 11 deletions src/components/creators/creator-rewards/CreatorRewardInfoCard.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { LineChartOutlined } from '@ant-design/icons'
import { Tooltip } from 'antd'
import clsx from 'clsx'
import Link from 'next/link'
Expand All @@ -17,7 +18,7 @@ import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks'
import { getAmountRange } from 'src/utils/analytics'
import { activeStakingLinks } from 'src/utils/links'
import NumberSkeleton from '../common/NumberSkeleton'
import StakerRewardHistoryModal from '../staker-rewards/StakerRewardHistoryModal'
import RewardHistoryModal from '../RewardHistoryModal'
import styles from './CreatorRewardInfoCard.module.sass'

export default function CreatorRewardInfoCard() {
Expand Down Expand Up @@ -100,23 +101,50 @@ export default function CreatorRewardInfoCard() {
</span>
</div>
<div
className='pt-2 px-3 d-flex justify-content-center align-items-center ColorPrimary FontWeightMedium GapMini'
onClick={() => {
sendEvent('astake_reward_history_opened', {
amountRange: getAmountRange(totalStake?.amount),
})
setIsOpenRewardHistoryModal(true)
className='mt-2'
style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr',
borderTop: '1px solid #dddddd',
marginLeft: '-1rem',
marginBottom: '-1rem',
width: 'calc(100% + 2rem)',
}}
style={{ cursor: 'pointer' }}
>
<RiHistoryFill />
<span className='FontSmall'>Rewards History</span>
<div
className='py-2.5 px-3 d-flex justify-content-center align-items-center ColorPrimary FontWeightMedium GapTiny'
onClick={() => {
sendEvent('astake_reward_history_opened', {
amountRange: getAmountRange(totalStake?.amount),
})
setIsOpenRewardHistoryModal(true)
}}
style={{ cursor: 'pointer', flex: 1, borderRight: '1px solid #dddddd' }}
>
<RiHistoryFill />
<span className='FontSmall'>History</span>
</div>

<Link href={`/leaderboard/${myAddress}?tab=creator`}>
<a
className='py-2.5 px-3 d-flex justify-content-center align-items-center ColorPrimary FontWeightMedium GapTiny'
onClick={() => {
sendEvent('astake_my_stats_clicked', {
amountRange: getAmountRange(totalStake?.amount),
})
}}
style={{ cursor: 'pointer', flex: 1 }}
>
<LineChartOutlined />
<span className='FontSmall'>My Stats</span>
</a>
</Link>
</div>
</div>
</div>
</Segment>

<StakerRewardHistoryModal
<RewardHistoryModal
visible={isOpenRewardHistoryModal}
onCancel={() => setIsOpenRewardHistoryModal(false)}
/>
Expand Down
Loading