Skip to content

Commit

Permalink
feat: integrate user leaderboard page with api
Browse files Browse the repository at this point in the history
  • Loading branch information
teodorus-nathaniel committed Jan 19, 2024
1 parent 46347da commit ff4a155
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 38 deletions.
209 changes: 173 additions & 36 deletions src/components/leaderboard/UserLeaderboardPage.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,206 @@
import { IoPeople } from 'react-icons/io5'
import { Radio, Tooltip } from 'antd'
import { useState } from 'react'
import { SlQuestion } from 'react-icons/sl'
import { ReactNode } from 'react-markdown'
import { useSelectProfile } from 'src/rtk/app/hooks'
import { useFetchUserRewardHistory } from 'src/rtk/features/activeStaking/hooks'
import { useFetchUserStatistics } from 'src/rtk/features/leaderboard/hooks'
import { UserStatistics } from 'src/rtk/features/leaderboard/userStatistics'
import { truncateAddress } from 'src/utils/storage'
import { FormatBalance } from '../common/balances'
import { RewardHistoryPanel } from '../creators/RewardHistoryModal'
import { PageContent } from '../main/PageWrapper'
import AuthorSpaceAvatar from '../profiles/address-views/AuthorSpaceAvatar'
import DfCard from '../utils/cards/DfCard'
import { MutedSpan } from '../utils/MutedText'

const stats: Record<
string,
{ title: string; value: (data: UserStatistics) => ReactNode; tooltip: string }[]
> = {
creator: [
{
title: 'Likes I received this week',
value: data => data.creator.likesCountByPeriod,
tooltip: 'The amount of likes that all of your posts received this week',
},
{
title: 'SUB earned this week',
value: data => (
<FormatBalance
withMutedDecimals={false}
precision={2}
value={data.creator.earnedByPeriod ?? '0'}
currency='SUB'
decimals={10}
/>
),
tooltip: 'The amount of SUB rewards you have earned this week from Active Staking rewards',
},
{
title: 'Stakers that liked me this week',
value: data => data.creator.stakersWhoLiked,
tooltip: 'The amount of individual readers that liked at least one of your posts this week',
},
{
title: 'SUB earned in total',
value: data => (
<FormatBalance
withMutedDecimals={false}
precision={2}
value={data.creator.earnedTotal ?? '0'}
currency='SUB'
decimals={10}
/>
),
tooltip: 'The total amount of SUB rewards you have earned from Active Staking rewards',
},
],
staker: [
{
title: 'Posts I liked this week',
value: data => data.staker.likedPosts,
tooltip: 'The number of individual posts that you liked this week',
},
{
title: 'SUB earned this week',
value: data => (
<FormatBalance
withMutedDecimals={false}
precision={2}
value={data.staker.earnedByPeriod ?? '0'}
currency='SUB'
decimals={10}
/>
),
tooltip: 'The amount of SUB rewards you have earned this week from Active Staking rewards',
},
{
title: 'Creators I liked this week',
value: data => data.staker.likedCreators,
tooltip:
'The number of individual creators that you supported this week by liking at least one of their posts',
},
{
title: 'SUB earned in total',
value: data => (
<FormatBalance
withMutedDecimals={false}
precision={2}
value={data.staker.earnedTotal ?? '0'}
currency='SUB'
decimals={10}
/>
),
tooltip:
'The total amount of SUB rewards you have earned this week from Active Staking rewards',
},
],
}

export default function UserLeaderboardPage({ address }: { address: string }) {
const [tabState, setTabState] = useState<'staker' | 'creator'>('staker')
const { data } = useFetchUserStatistics(address)
const profile = useSelectProfile(address)

const { data: rewardHistory, loading } = useFetchUserRewardHistory(address)

return (
<PageContent withLargerMaxWidth meta={{ title: 'Active Staking Dashboard' }}>
<div className='d-flex align-items-end justify-content-between'>
<div className='d-flex align-items-baseline justify-content-between'>
<h1 className='DfUnboundedTitle ColorNormal mb-0'>Active Staking Dashboard</h1>
<span>Role:</span>
<div className='d-flex align-items-center GapTiny'>
<span>Role:</span>

<Radio.Group
className='DfRadioGroup'
options={[
{ label: 'Staker', value: 'staker' },
{ label: 'Creator', value: 'creator' },
]}
onChange={e => setTabState(e.target.value)}
value={tabState}
optionType='button'
/>
</div>
</div>
<div className='mt-4 GapBig' style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr' }}>
<DfCard
className='d-flex flex-column GapSmall align-items-center'
variant='info'
withShadow={false}
style={{ gridRow: 'span 2' }}
{data && (
<div
className='mt-4 GapBig'
style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr' }}
>
<div
<DfCard
className='d-flex flex-column GapSmall align-items-center'
variant='info'
withShadow={false}
style={{ gridRow: 'span 2' }}
>
{/* <div
className='rounded-circle d-flex align-items-center justify-content-center'
style={{ background: 'white', width: '88px', height: '88px' }}
>
<IoPeople style={{ fontSize: '42px', color: '#5089F8' }} />
</div> */}
<AuthorSpaceAvatar size={88} authorAddress={address} />
<div className='d-flex flex-column align-items-center'>
<span className='FontBig FontWeightSemibold'>
{profile?.content?.name ?? truncateAddress(address)}
</span>
<MutedSpan>as a {tabState === 'creator' ? 'Creator' : 'Staker'}</MutedSpan>
</div>
</DfCard>
{stats[tabState].map(stat => (
<StatisticCard
tooltip={stat.tooltip}
title={stat.title}
value={stat.value(data)}
key={stat.title}
/>
))}
</div>
)}
<div
className='mt-4 GapLarge'
style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', alignItems: 'start' }}
>
<DfCard size='small' withShadow={false}>
<RewardHistoryPanel
title={tabState === 'creator' ? 'My Creator Rewards' : 'My Staker Rewards'}
loading={loading}
rewardHistory={rewardHistory}
rewardType={tabState}
/>
</DfCard>
<DfCard size='small' withShadow={false}>
<div className='d-flex flex-column'>
<span className='FontSemilarge FontWeightSemibold'>Leaderboard</span>
<MutedSpan className='FontSmall'>
Stakers ranked based on the amount of SUB earned with Active Staking.
</MutedSpan>
</div>
<div className='d-flex flex-column align-items-center'>
<span className='FontBig FontWeightSemibold'>Total Activity</span>
<MutedSpan>this week</MutedSpan>
</div>
<div className='mt-3'>asdfasdfsdf</div>
</DfCard>
<StatisticCard title='Posts I liked this week' value={data?.staker.likedPosts} />
<StatisticCard title='SUB earned this week' value={data?.staker.earnedByPeriod} />
<StatisticCard title='Creators I liked this week' value={data?.staker.likedCreators} />
<StatisticCard title='SUB earned in total' value={data?.staker.earnedTotal} />
</div>
<div className='mt-4 GapLarge' style={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
<TopUsersTable />
<TopUsersTable />
</div>
</PageContent>
)
}

function TopUsersTable() {
return (
<DfCard withShadow={false} className='d-flex flex-column'>
<span className='FontWeightSemibold FontSemilarge'>Top Stakers this week</span>
<MutedSpan className='FontSmall mt-1'>
Stakers ranked based on the amount of SUB earned with Active Staking.
</MutedSpan>
<div className='mt-3'>asdfasdfdf</div>
</DfCard>
)
}

function StatisticCard({ title, value }: { title: string; value: ReactNode }) {
function StatisticCard({
title,
value,
tooltip,
}: {
title: string
value: ReactNode
tooltip: string
}) {
return (
<DfCard size='small' className='d-flex flex-column GapMini' withShadow={false}>
<div className='d-flex align-items-center ColorMuted GapTiny'>
<span className='FontSmall'>{title}</span>
<SlQuestion className='FontTiny' />
<Tooltip title={tooltip}>
<SlQuestion className='FontTiny' />
</Tooltip>
</div>
<div className='d-flex align-items-center justify-content-between GapSmall mt-auto'>
<span className='FontWeightMedium FontBig'>{value}</span>
Expand Down
10 changes: 8 additions & 2 deletions src/pages/leaderboard/[address].tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import UserLeaderboardPage from 'src/components/leaderboard/UserLeaderboardPage'
import { return404 } from 'src/components/utils/next'
import { getInitialPropsWithRedux } from 'src/rtk/app'
import { fetchRewardHistory } from 'src/rtk/features/activeStaking/rewardHistorySlice'
import { fetchUserStatistics } from 'src/rtk/features/leaderboard/userStatistics'
import { fetchProfileSpace } from 'src/rtk/features/profiles/profilesSlice'

getInitialPropsWithRedux(UserLeaderboardPage, async ({ dispatch, context }) => {
getInitialPropsWithRedux(UserLeaderboardPage, async ({ dispatch, context, subsocial }) => {
const { query } = context
const address = query.address as string
if (!address || typeof address !== 'string') return return404(context)

await dispatch(fetchUserStatistics({ address }))
await Promise.all([
dispatch(fetchUserStatistics({ address })),
dispatch(fetchRewardHistory({ address })),
dispatch(fetchProfileSpace({ id: address, api: subsocial })),
])
return { address }
// await dispatch()
})
Expand Down
28 changes: 28 additions & 0 deletions src/styles/subsocial.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2273,3 +2273,31 @@ hr {
.\!BreakWord {
word-break: break-word !important;
}

.DfRadioGroup {
background: white;
border-radius: $border_radius_normal;
padding: 0.125rem;

.ant-radio-button-wrapper {
border-radius: $border_radius_normal;
border: none;
font-weight: $font_weight_medium;
color: $color_muted;
height: auto;
padding: 0 $space_small;

&::before {
display: none;
}

&.ant-radio-button-wrapper-checked {
background-color: #e7f0ff;
color: $color_font_normal;
}

&:not(.ant-radio-button-wrapper-disabled):focus-within {
box-shadow: 0 0 0 2px rgba(0, 94, 255, 0.12);
}
}
}

0 comments on commit ff4a155

Please sign in to comment.