Skip to content

Commit

Permalink
Merge pull request #193 from dappforce/deploy/leaderboard-page
Browse files Browse the repository at this point in the history
Leaderboard Fixes
  • Loading branch information
teodorus-nathaniel authored Jan 24, 2024
2 parents d6ac0ef + 573ee54 commit f4c5d09
Show file tree
Hide file tree
Showing 20 changed files with 320 additions and 176 deletions.
20 changes: 10 additions & 10 deletions src/components/creators/MobileStakerRewardDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,15 @@ function StakerRewardDashboard(props: MobileStakerRewardDashboardProps) {
return (
<div {...props} className={clsx(props.className, styles.MobileStakerRewardDashboard)}>
<div className={clsx(styles.Summary)}>
<div className={styles.Content}>
<div
className={clsx(styles.Content, 'cursor-pointer')}
onClick={() => {
sendEvent('astake_dashboard_expanded', {
amountRange: getAmountRange(data.amount),
})
setIsOpen(prev => !prev)
}}
>
<span className={clsx('d-flex GapTiny align-items-center')}>
<span className='FontWeightSemibold'>Extra SUB rewards</span>
<Tooltip title={likesToMaxReward > 0 ? 'Daily Activity Target' : 'Daily Target Hit'}>
Expand All @@ -89,15 +97,7 @@ function StakerRewardDashboard(props: MobileStakerRewardDashboardProps) {
<div className={clsx('FontWeightSemibold', styles.CountProgress, isOpenClassName)}>
<StakerSuperLikeCount />
</div>
<HiChevronRight
onClick={() => {
sendEvent('astake_dashboard_expanded', {
amountRange: getAmountRange(data.amount),
})
setIsOpen(prev => !prev)
}}
className={clsx('ColorMuted FontBig', styles.Arrow, isOpenClassName)}
/>
<HiChevronRight className={clsx('ColorMuted FontBig', styles.Arrow, isOpenClassName)} />
</div>
</div>
<div className={styles.ProgressContainer}>
Expand Down
23 changes: 15 additions & 8 deletions src/components/creators/RewardHistoryModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ 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'
import { MutedSpan } from '../utils/MutedText'

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

Expand All @@ -24,12 +24,14 @@ export default function RewardHistoryModal({ onCancel, visible }: RewardHistoryM
/>

{(creatorRewards?.length ?? 0) > 0 && (
<RewardHistoryPanel
title='Creator Rewards'
rewardHistory={data}
loading={loading}
rewardType='creator'
/>
<div className='mt-3'>
<RewardHistoryPanel
title='Creator Rewards'
rewardHistory={data}
loading={loading}
rewardType='creator'
/>
</div>
)}
</CustomModal>
)
Expand All @@ -39,10 +41,12 @@ export function RewardHistoryPanel({
loading,
rewardHistory,
rewardType,
description,
title,
...props
}: {
title: string
description?: string
rewardHistory: RewardHistory | undefined
loading: boolean | undefined
rewardType: 'staker' | 'creator'
Expand All @@ -54,7 +58,10 @@ export function RewardHistoryPanel({

return (
<div {...props} className={clsx('d-flex flex-column', props.className)}>
<MutedSpan className='mb-1 FontWeightSemibold'>{title}</MutedSpan>
<span className={clsx('FontWeightSemibold', description ? 'FontSemilarge' : 'mb-2')}>
{title}
</span>
{description && <MutedSpan className='mb-2 FontSmall'>{description}</MutedSpan>}
<div className='d-flex flex-column GapTiny'>
{(() => {
if (loading) return <Skeleton />
Expand Down
97 changes: 60 additions & 37 deletions src/components/creators/TopUsersCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,29 @@ 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 { useSendEvent } from 'src/providers/AnalyticContext'
import { useFetchProfileSpaces, useSelectProfile } from 'src/rtk/app/hooks'
import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks'
import { useFetchTopUsers } from 'src/rtk/features/leaderboard/hooks'
import { getAmountRange } from 'src/utils/analytics'
import { truncateAddress } from 'src/utils/storage'
import { useMyAddress } from '../auth/MyAccountsContext'
import { FormatBalance } from '../common/balances'
import Avatar from '../profiles/address-views/Avatar'
import ViewProfileLink from '../profiles/ViewProfileLink'
import { useIsMobileWidthOrDevice } from '../responsive'
import { SpaceAvatar } from '../spaces/helpers'
import ViewSpaceLink from '../spaces/ViewSpaceLink'
import { MutedSpan } from '../utils/MutedText'
import Segment from '../utils/Segment'

export type TopUsersCardProps = ComponentProps<'div'>

export default function TopUsersCard({ ...props }: TopUsersCardProps) {
const myAddress = useMyAddress()
const myAddress = useMyAddress() ?? ''
const { data, loading } = useFetchTopUsers()
const { data: totalStake } = useFetchTotalStake(myAddress)
const isMobile = useIsMobileWidthOrDevice()
const sendEvent = useSendEvent()

const args = useMemo(
() => ({
Expand All @@ -35,6 +43,21 @@ export default function TopUsersCard({ ...props }: TopUsersCardProps) {
className='p-0 GapMini d-flex align-items-center'
href={myAddress ? `/leaderboard/${myAddress}` : '/leaderboard'}
style={{ height: 'auto', border: 'none', boxShadow: 'none' }}
onClick={() => {
if (myAddress) {
sendEvent('leaderboard_my_stats_opened', {
myStats: true,
role: 'staker',
eventSource: 'top_users',
amountRange: getAmountRange(totalStake?.amount),
})
} else {
sendEvent('leaderboard_global_stats_opened', {
eventSource: 'top_users',
amountRange: getAmountRange(totalStake?.amount),
})
}
}}
>
<span>See more</span>
<IoChevronForward />
Expand All @@ -47,7 +70,7 @@ export default function TopUsersCard({ ...props }: TopUsersCardProps) {
<>
<div className='d-flex justify-content-between align-items-center'>
<div className='d-flex align-items-center FontWeightSemibold GapMini'>
<span className='FontSemilarge'>Top users (last 24h)</span>
<span className='FontSemilarge'>Top users (this week)</span>
</div>
{isMobile && seeMoreButton}
</div>
Expand Down Expand Up @@ -98,21 +121,31 @@ export default function TopUsersCard({ ...props }: TopUsersCardProps) {
)
}

function UserInfo({
rank,
user,
}: {
rank: number
user: { address: string; superLikesCount: number }
}) {
const profile = useSelectProfileSpace(user.address)
const space = useSelectSpace(profile?.spaceId)
if (!space) return null
function UserInfo({ rank, user }: { rank: number; user: { address: string; reward: string } }) {
const profile = useSelectProfile(user.address)

const avatar = (
<Avatar asLink={!profile} address={user.address} avatar={profile?.content?.image} size={34} />
)
const name = (
<span
className='FontWeightMedium FontNormal'
style={{
minWidth: 0,
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
position: 'relative',
top: '2px',
}}
>
{profile?.content?.name || truncateAddress(user.address)}
</span>
)
return (
<div className='d-flex align-items-center'>
<div className='position-relative'>
<SpaceAvatar space={space.struct} avatar={space.content?.image} size={34} />
{profile ? <ViewSpaceLink space={profile.struct} title={avatar} /> : avatar}
{[1, 2, 3].includes(rank) && (
<Medal
className='position-absolute FontTiny'
Expand All @@ -122,29 +155,19 @@ function UserInfo({
)}
</div>
<div className='d-flex flex-column' style={{ minWidth: 0 }}>
<ViewSpaceLink
containerClassName='d-flex'
className='d-flex'
style={{ minWidth: 0 }}
title={
<span
className='FontWeightMedium FontNormal'
style={{
minWidth: 0,
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
position: 'relative',
top: '2px',
}}
>
{space.content?.name ?? 'Unnamed'}
</span>
}
space={space.struct}
/>
{profile ? (
<ViewSpaceLink
containerClassName='d-flex'
className='d-flex'
style={{ minWidth: 0 }}
title={name}
space={profile?.struct}
/>
) : (
<ViewProfileLink title={name} account={{ address: user.address }} />
)}
<div className='d-flex align-items-center ColorMuted GapMini'>
<span>{user.superLikesCount} Likes</span>
<FormatBalance value={user.reward} currency='SUB' decimals={10} precision={2} />
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,14 @@ export default function CreatorRewardInfoCard() {
<span className='FontSmall'>History</span>
</div>

<Link href={`/leaderboard/${myAddress}?tab=creator`}>
<Link href={`/leaderboard/${myAddress}?role=creator`} passHref>
<a
className='py-2.5 px-3 d-flex justify-content-center align-items-center ColorPrimary FontWeightMedium GapTiny'
onClick={() => {
sendEvent('astake_my_stats_clicked', {
sendEvent('leaderboard_my_stats_opened', {
myStats: true,
eventSource: 'my_stats_banner',
role: 'creator',
amountRange: getAmountRange(totalStake?.amount),
})
}}
Expand Down
7 changes: 5 additions & 2 deletions src/components/creators/staker-rewards/StakerRewardInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,14 @@ export default function StakerRewardInfo({
<span className='FontSmall'>History</span>
</div>

<Link href={`/leaderboard/${myAddress}?tab=staker`}>
<Link href={`/leaderboard/${myAddress}?role=staker`} passHref>
<a
className='py-2.5 px-3 d-flex justify-content-center align-items-center ColorPrimary FontWeightMedium GapTiny'
onClick={() => {
sendEvent('astake_my_stats_clicked', {
sendEvent('leaderboard_my_stats_opened', {
myStats: true,
eventSource: 'my_stats_banner',
role: 'staker',
amountRange: getAmountRange(totalStake?.amount),
})
}}
Expand Down
17 changes: 2 additions & 15 deletions src/components/leaderboard/GeneralLeaderboardPage.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { Tabs } from 'antd'
import clsx from 'clsx'
import router from 'next/router'
import { ReactNode } from 'react-markdown'
import { GeneralStatistics } from 'src/rtk/features/leaderboard/generalStatisticsSlice'
import { useFetchGeneralStatistics } from 'src/rtk/features/leaderboard/hooks'
import { useMyAddress } from '../auth/MyAccountsContext'
import { FormatBalance } from '../common/balances'
import { PageContent } from '../main/PageWrapper'
import DfCard from '../utils/cards/DfCard'
import { MutedSpan } from '../utils/MutedText'
import LeaderboardTable from './common/LeaderboardTable'
import LeaderboardTabs from './common/LeaderboardTabs'
import ProfileCard from './common/ProfileCard'
import StatisticCard from './common/StatisticCard'
import styles from './GeneralLeaderboardPage.module.sass'
Expand Down Expand Up @@ -57,21 +55,10 @@ const stats: Stat[] = [
export type GeneralLeaderboardPageProps = {}
export default function GeneralLeaderboardPage({}: GeneralLeaderboardPageProps) {
const { data } = useFetchGeneralStatistics()
const myAddress = useMyAddress()

return (
<PageContent withLargerMaxWidth meta={{ title: 'Active Staking Dashboard' }}>
<Tabs
activeKey='general'
onChange={key => {
if (key === 'user') router.push(`/leaderboard/${myAddress}?role=${key}`)
else if (key === 'stats') router.push('/stats')
}}
>
{myAddress && <Tabs.TabPane tab='My Staking Stats' key='user' />}
<Tabs.TabPane tab='Global Staking Stats' key='general' />
<Tabs.TabPane tab='Polkaverse Activity' key='stats' />
</Tabs>
<LeaderboardTabs activeKey='general' />
{data && (
<div className={clsx(styles.Statistics)}>
<ProfileCard
Expand Down
4 changes: 2 additions & 2 deletions src/components/leaderboard/UserLeaderboardPage.module.sass
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@

.Leaderboard
margin-top: $space_big
gap: $space_large
gap: $space_big
display: grid
grid-template-columns: 1fr 2fr
grid-template-columns: 1fr 1fr 1fr
align-items: start

@media screen and (max-width: 768px)
Expand Down
28 changes: 14 additions & 14 deletions src/components/leaderboard/UserLeaderboardPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Radio, Tabs } from 'antd'
import { Radio } from 'antd'
import clsx from 'clsx'
import router, { useRouter } from 'next/router'
import { useState } from 'react'
Expand All @@ -14,6 +14,7 @@ import { useIsMobileWidthOrDevice } from '../responsive'
import DfCard from '../utils/cards/DfCard'
import { MutedSpan } from '../utils/MutedText'
import LeaderboardTable from './common/LeaderboardTable'
import LeaderboardTabs from './common/LeaderboardTabs'
import ProfileCard from './common/ProfileCard'
import StatisticCard from './common/StatisticCard'
import styles from './UserLeaderboardPage.module.sass'
Expand Down Expand Up @@ -151,18 +152,7 @@ export default function UserLeaderboardPage({ address }: UserLeaderboardPageProp

return (
<PageContent withLargerMaxWidth meta={{ title: 'Active Staking Dashboard' }}>
<Tabs
activeKey={isMyAddress ? 'user' : ''}
onChange={key => {
if (key === 'general') router.push('/leaderboard')
else if (key === 'stats') router.push('/stats')
else router.push(`/leaderboard/${myAddress}?role=${tabState}`)
}}
>
{myAddress && <Tabs.TabPane tab='My Staking Stats' key='user' />}
<Tabs.TabPane tab='Global Staking Stats' key='general' />
<Tabs.TabPane tab='Polkaverse Activity' key='stats' />
</Tabs>
<LeaderboardTabs activeKey={isMyAddress ? 'user' : ''} />
{data && (
<div className={clsx(styles.Statistics)}>
<ProfileCard
Expand Down Expand Up @@ -198,12 +188,13 @@ export default function UserLeaderboardPage({ address }: UserLeaderboardPageProp
<DfCard size='small' withShadow={false} className='sm-hidden'>
<RewardHistoryPanel
title={tabState === 'creator' ? 'Creator Rewards' : 'Staker Rewards'}
description='The last 30 days of your Active Staking rewards'
loading={loading}
rewardHistory={rewardHistory}
rewardType={tabState}
/>
</DfCard>
<DfCard size='small' withShadow={false} style={{ overflowX: 'clip' }}>
<DfCard size='small' withShadow={false} style={{ overflowX: 'clip', gridColumn: 'span 2' }}>
<div className='d-flex flex-column'>
<span className='FontSemilarge FontWeightSemibold'>Leaderboard</span>
<MutedSpan className='FontSmall'>
Expand All @@ -215,6 +206,15 @@ export default function UserLeaderboardPage({ address }: UserLeaderboardPageProp
<LeaderboardTable className='mt-3' role={tabState} />
</DfCard>
</div>
<DfCard size='small' withShadow={false} className='lg-hidden mt-4'>
<RewardHistoryPanel
title={tabState === 'creator' ? 'Creator Rewards' : 'Staker Rewards'}
description='The last 30 days of your Active Staking rewards'
loading={loading}
rewardHistory={rewardHistory}
rewardType={tabState}
/>
</DfCard>
{isMobile && (
<RewardHistoryModal
visible={isOpenHistoryModal}
Expand Down
Loading

0 comments on commit f4c5d09

Please sign in to comment.