From 558b6cfd157b301728c3095a2a224bbd999a50e5 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Tue, 30 Jan 2024 23:39:07 +0700 Subject: [PATCH 1/9] feat: add filtering for low value comments --- src/components/comments/CommentTree.tsx | 16 +++++++-- src/components/comments/CommentsSection.tsx | 20 ++++++++--- src/components/comments/ViewComment.tsx | 6 +++- src/components/utils/datahub/posts.ts | 31 ++++++++++++++++ src/rtk/app/rootReducer.ts | 2 ++ src/rtk/features/replies/lowValueIdsSlice.ts | 37 ++++++++++++++++++++ src/rtk/features/replies/repliesHooks.ts | 12 +++++++ src/rtk/features/replies/repliesSlice.ts | 21 ++++++++--- 8 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 src/rtk/features/replies/lowValueIdsSlice.ts diff --git a/src/components/comments/CommentTree.tsx b/src/components/comments/CommentTree.tsx index 99de7254c..93dc11de5 100644 --- a/src/components/comments/CommentTree.tsx +++ b/src/components/comments/CommentTree.tsx @@ -1,5 +1,5 @@ import React, { FC, useMemo, useState } from 'react' -import { useSelectSpace } from 'src/rtk/app/hooks' +import { useFilterOutLowValuePosts, useSelectSpace } from 'src/rtk/app/hooks' import { useAppDispatch } from 'src/rtk/app/store' import { useSelectPost } from 'src/rtk/features/posts/postsHooks' import { fetchPostReplyIds } from 'src/rtk/features/replies/repliesSlice' @@ -13,19 +13,22 @@ import { useRepliesData } from './utils' import ViewComment from './ViewComment' type CommentsTreeProps = { + rootPostId: PostId parentId: PostId eventProps: CommentEventProps directlyExpandReplies?: boolean + showAllReplies: boolean } type CommentByIdProps = { commentId: PostId eventProps: CommentEventProps directlyExpandReplies?: boolean + showAllReplies: boolean } const CommentById = React.memo( - ({ commentId: id, eventProps, directlyExpandReplies }: CommentByIdProps) => { + ({ commentId: id, eventProps, directlyExpandReplies, showAllReplies }: CommentByIdProps) => { const comment = useSelectPost(id) const rootPostId = comment ? asCommentStruct(comment.post.struct).rootPostId : undefined @@ -36,6 +39,7 @@ const CommentById = React.memo( return ( = ({ parentId, eventProps, directlyExpandReplies, + showAllReplies, + rootPostId, }) => { const dispatch = useAppDispatch() const myAddress = useMyAddress() @@ -62,6 +68,9 @@ export const ViewCommentsTree: FC = ({ return replyIds.slice().reverse() }, [replyIds]) + const filteredIds = useFilterOutLowValuePosts(rootPostId, reversedReplyIds) + const usedIds = showAllReplies ? reversedReplyIds : filteredIds + useSubsocialEffect( ({ subsocial }) => { if (!repliesCount) return setLoading(false) @@ -90,13 +99,14 @@ export const ViewCommentsTree: FC = ({ return ( replyId} className='mt-2.5' listClassName='GapSmall d-flex flex-column' renderItem={replyId => ( diff --git a/src/components/comments/CommentsSection.tsx b/src/components/comments/CommentsSection.tsx index b5462965f..7dad4ad27 100644 --- a/src/components/comments/CommentsSection.tsx +++ b/src/components/comments/CommentsSection.tsx @@ -1,5 +1,6 @@ +import { Checkbox } from 'antd' import clsx from 'clsx' -import { FC } from 'react' +import { FC, useState } from 'react' import { PostWithSomeDetails, SpaceStruct } from 'src/types' import { useIsMyAddress } from '../auth/MyAccountsContext' import { Pluralize } from '../utils/Plularize' @@ -27,6 +28,7 @@ export const CommentSection: FC = ({ } = post const { id, repliesCount, ownerId } = struct const isPostAuthor = useIsMyAddress(ownerId) + const [showAllComments, setShowAllComments] = useState(false) return (
= ({ TopBorder: withBorder, })} > -

- -

+
+

+ +

+ setShowAllComments(e.target.checked)} + > + Show all comments + +
) diff --git a/src/components/comments/ViewComment.tsx b/src/components/comments/ViewComment.tsx index 68e4e50ea..c93a80c3d 100644 --- a/src/components/comments/ViewComment.tsx +++ b/src/components/comments/ViewComment.tsx @@ -37,6 +37,7 @@ type Props = { comment: PostWithSomeDetails withShowReplies?: boolean eventProps: CommentEventProps + showAllReplies: boolean } export const InnerViewComment: FC = props => { @@ -46,6 +47,7 @@ export const InnerViewComment: FC = props => { comment: commentDetails, withShowReplies = false, eventProps, + showAllReplies, } = props const { post: comment } = commentDetails @@ -187,8 +189,10 @@ export const InnerViewComment: FC = props => { {hasReplies && (
{!withShowReplies && } - {showReplies && ( + {showReplies && rootPost?.id && ( diff --git a/src/components/utils/datahub/posts.ts b/src/components/utils/datahub/posts.ts index 8a0a3ea3f..4cb769854 100644 --- a/src/components/utils/datahub/posts.ts +++ b/src/components/utils/datahub/posts.ts @@ -1,4 +1,5 @@ import gql from 'graphql-tag' +import { LowValueIds } from 'src/rtk/features/replies/lowValueIdsSlice' import { datahubQueryRequest } from './utils' // QUERIES @@ -36,3 +37,33 @@ export async function getHotPosts(variables: { offset: number; limit: number }) return res.data.activeStakingRankedPostIdsByActiveStakingActivity } + +const GET_LOW_VALUE_IDS = gql` + query GetLowValueIds($rootPostId: String!) { + findPosts(where: { rootPostPersistentId: $rootPostId, lowValue: true }) { + data { + persistentId + } + } + } +` +export async function getLowValueIds(rootPostId: string): Promise { + const res = await datahubQueryRequest< + { + findPosts: { + data: { + persistentId: string + }[] + } + }, + { rootPostId: string } + >({ + query: GET_LOW_VALUE_IDS, + variables: { rootPostId }, + }) + + return { + rootPostId, + lowValueIds: res.data.findPosts.data.map(post => post.persistentId), + } +} diff --git a/src/rtk/app/rootReducer.ts b/src/rtk/app/rootReducer.ts index c6fdff159..c15677575 100644 --- a/src/rtk/app/rootReducer.ts +++ b/src/rtk/app/rootReducer.ts @@ -31,6 +31,7 @@ import posts from '../features/posts/postsSlice' import followedAccountIds from '../features/profiles/followedAccountIdsSlice' import profileSpaces from '../features/profiles/profilesSlice' import myPostReactions from '../features/reactions/myPostReactionsSlice' +import lowValueIds from '../features/replies/lowValueIdsSlice' import replyIds from '../features/replies/repliesSlice' import sellerConfig from '../features/sellerConfig/sellerConfigSlice' import followedSpaceIds from '../features/spaceIds/followedSpaceIdsSlice' @@ -77,6 +78,7 @@ const rootReducer = combineReducers({ generalStatistics, leaderboard, postScores, + lowValueIds, }) export type RootState = ReturnType diff --git a/src/rtk/features/replies/lowValueIdsSlice.ts b/src/rtk/features/replies/lowValueIdsSlice.ts new file mode 100644 index 000000000..b9a14b2d7 --- /dev/null +++ b/src/rtk/features/replies/lowValueIdsSlice.ts @@ -0,0 +1,37 @@ +import { createEntityAdapter, createSlice } from '@reduxjs/toolkit' +import { getLowValueIds } from 'src/components/utils/datahub/posts' +import { RootState } from 'src/rtk/app/rootReducer' +import { createSimpleFetchWrapper } from 'src/rtk/app/wrappers' + +export type LowValueIds = { + rootPostId: string + lowValueIds: string[] +} + +const sliceName = 'lowValueIds' + +const adapter = createEntityAdapter({ + selectId: data => data.rootPostId, +}) +const selectors = adapter.getSelectors(state => state.lowValueIds) + +export const selectLowValueIds = selectors.selectById + +export const fetchLowValueIds = createSimpleFetchWrapper<{ rootPostId: string }, LowValueIds>({ + sliceName, + fetchData: async function ({ rootPostId }) { + return await getLowValueIds(rootPostId) + }, + getCachedData: (state, { rootPostId }) => selectLowValueIds(state, rootPostId), + saveToCacheAction: data => slice.actions.setIsPostLowValue(data), +}) + +const slice = createSlice({ + name: sliceName, + initialState: adapter.getInitialState(), + reducers: { + setIsPostLowValue: adapter.upsertOne, + }, +}) + +export default slice.reducer diff --git a/src/rtk/features/replies/repliesHooks.ts b/src/rtk/features/replies/repliesHooks.ts index 349d7c6b0..d76c3a0d8 100644 --- a/src/rtk/features/replies/repliesHooks.ts +++ b/src/rtk/features/replies/repliesHooks.ts @@ -1,9 +1,11 @@ +import { useMemo } from 'react' import { useActions } from 'src/rtk/app/helpers' import { useAppSelector } from 'src/rtk/app/store' import { PostData, PostId, PostStruct } from 'src/types' import { upsertContent } from '../contents/contentsSlice' import { useCreateReloadPosts } from '../posts/postsHooks' import { removePost, upsertPost } from '../posts/postsSlice' +import { selectLowValueIds } from './lowValueIdsSlice' import { ReplyIdsByPostId, selectReplyIdsEntities, upsertReplyIdsByPostId } from './repliesSlice' type RemoveReplyParams = { @@ -106,3 +108,13 @@ export const useCreateUpsertReply = () => { upsertReply(replyData) } } + +export function useFilterOutLowValuePosts(rootPostId: string, postIds: string[]) { + const lowValueState = useAppSelector(state => selectLowValueIds(state, rootPostId)) + return useMemo(() => { + const lowValueSet = new Set(lowValueState?.lowValueIds ?? []) + return postIds.filter(postId => { + return !lowValueSet.has(postId) + }) + }, [postIds, lowValueState]) +} diff --git a/src/rtk/features/replies/repliesSlice.ts b/src/rtk/features/replies/repliesSlice.ts index 89716ef8b..624b7f984 100644 --- a/src/rtk/features/replies/repliesSlice.ts +++ b/src/rtk/features/replies/repliesSlice.ts @@ -8,8 +8,9 @@ import { ThunkApiConfig, } from 'src/rtk/app/helpers' import { RootState } from 'src/rtk/app/rootReducer' -import { AccountId, PostId, PostWithSomeDetails } from 'src/types' -import { fetchPosts } from '../posts/postsSlice' +import { AccountId, CommentStruct, PostId, PostWithSomeDetails } from 'src/types' +import { fetchPosts, selectPost } from '../posts/postsSlice' +import { fetchLowValueIds } from './lowValueIdsSlice' export type ReplyIdsByPostId = { /** `id` is a parent id of replies. */ @@ -87,11 +88,21 @@ export const fetchPostReplyIds = createAsyncThunk< } } + let rootPostId = parentId + const post = selectPost(getState(), { id: parentId }) + const struct = post?.post.struct as CommentStruct + if (struct.rootPostId) { + rootPostId = struct.rootPostId + } + const replyIds = await api.blockchain.getReplyIdsByPostId(idToBn(parentId)) - await dispatch( - fetchPosts({ api, withReactionByAccount: myAddress, ids: replyIds, withSpace: false }), - ) + await Promise.all([ + dispatch( + fetchPosts({ api, withReactionByAccount: myAddress, ids: replyIds, withSpace: false }), + ), + dispatch(fetchLowValueIds({ rootPostId })), + ]) return [ { From 0c9932e68f2f6899b48fdc303e1a9a1d026578d9 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Wed, 31 Jan 2024 00:56:46 +0700 Subject: [PATCH 2/9] feat: have show all comments subscribe localstorage --- package.json | 1 + src/components/comments/CommentsSection.tsx | 9 +++++++-- yarn.lock | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0a332f497..26d0bf06e 100644 --- a/package.json +++ b/package.json @@ -163,6 +163,7 @@ "store": "^2.0.12", "strip-markdown": "^4.0.0", "url-loader": "^4.1.1", + "use-local-storage": "^3.0.0", "yup": "^0.32.9", "zod": "^3.22.4" } diff --git a/src/components/comments/CommentsSection.tsx b/src/components/comments/CommentsSection.tsx index 7dad4ad27..180d5d866 100644 --- a/src/components/comments/CommentsSection.tsx +++ b/src/components/comments/CommentsSection.tsx @@ -1,7 +1,8 @@ import { Checkbox } from 'antd' import clsx from 'clsx' -import { FC, useState } from 'react' +import { FC } from 'react' import { PostWithSomeDetails, SpaceStruct } from 'src/types' +import useLocalStorage from 'use-local-storage' import { useIsMyAddress } from '../auth/MyAccountsContext' import { Pluralize } from '../utils/Plularize' import Section from '../utils/Section' @@ -28,7 +29,10 @@ export const CommentSection: FC = ({ } = post const { id, repliesCount, ownerId } = struct const isPostAuthor = useIsMyAddress(ownerId) - const [showAllComments, setShowAllComments] = useState(false) + const [showAllComments, setShowAllComments] = useLocalStorage('showAllComments', false, { + parser: str => str === 'true', + serializer: bool => String(bool), + }) return (
= ({ setShowAllComments(e.target.checked)} > diff --git a/yarn.lock b/yarn.lock index b8006c27d..b9df9423f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13784,6 +13784,11 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +use-local-storage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/use-local-storage/-/use-local-storage-3.0.0.tgz#ecf90952374150f0c65baf027eaaf2062a4c20c6" + integrity sha512-wlPNnBCG3ULIJMr5A+dvWqLiPWCfsN1Kwijq+sAhT5yV4ex0u6XmZuNwP+RerIOfzBuz1pwSZuzhZMiluGQHfQ== + use-memo-one@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99" From 40f9cb537e5ac4340bc11fa22803ea7e46a6b1f3 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Wed, 31 Jan 2024 00:57:34 +0700 Subject: [PATCH 3/9] chore: add new addresses for whitelist --- src/config/constants.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config/constants.ts b/src/config/constants.ts index dfed9b49f..aca34b4c2 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -25,6 +25,10 @@ const WHITELISTED_FOR_NEW_FEATURES = [ '3q8uTV4HTCd4M8tP4fTKrGdopfKxAfLGfNdsmLbLP7hYj7JM', '3tPAVaHYAFRfUVpNP1DAq4E3BxTPanzkGN4uukn3b4ZAefkj', '3pjRboNv5rSDoy3thDse1KgaWtfVh3x2rrHqrabxjT7dJQdJ', + // filippo + '3sVFfCTpfWE5aqodJT5tpcK13uY9HMJNMDKDQYNpzPKmqVwA', + // jay TheKus + '3pYyydiZfeTL7iVxcYqw9bVyPbFXdVHSomUNzg4SpdycD5tg', ] export function useIsMyAddressWhitelisted() { const myAddress = useMyAddress() From d30648cac097a0dc80a19a5e5c45a6ea4eab3fe6 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Wed, 31 Jan 2024 00:58:53 +0700 Subject: [PATCH 4/9] chore: only show "show all comments" to whitelisted acc --- src/components/comments/CommentsSection.tsx | 25 ++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/components/comments/CommentsSection.tsx b/src/components/comments/CommentsSection.tsx index 180d5d866..802f91194 100644 --- a/src/components/comments/CommentsSection.tsx +++ b/src/components/comments/CommentsSection.tsx @@ -1,6 +1,7 @@ import { Checkbox } from 'antd' import clsx from 'clsx' import { FC } from 'react' +import { useIsMyAddressWhitelisted } from 'src/config/constants' import { PostWithSomeDetails, SpaceStruct } from 'src/types' import useLocalStorage from 'use-local-storage' import { useIsMyAddress } from '../auth/MyAccountsContext' @@ -29,11 +30,17 @@ export const CommentSection: FC = ({ } = post const { id, repliesCount, ownerId } = struct const isPostAuthor = useIsMyAddress(ownerId) - const [showAllComments, setShowAllComments] = useLocalStorage('showAllComments', false, { + + const isWhitelisted = useIsMyAddressWhitelisted() + let [showAllComments, setShowAllComments] = useLocalStorage('showAllComments', false, { parser: str => str === 'true', serializer: bool => String(bool), }) + if (!isWhitelisted) { + showAllComments = true + } + return (
= ({

- setShowAllComments(e.target.checked)} - > - Show all comments - + {isWhitelisted && ( + setShowAllComments(e.target.checked)} + > + Show all comments + + )}
Date: Wed, 31 Jan 2024 01:06:16 +0700 Subject: [PATCH 5/9] Add emojis to filters --- src/components/main/HomePageFilters.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/main/HomePageFilters.tsx b/src/components/main/HomePageFilters.tsx index 733c45dc2..a6379fd19 100644 --- a/src/components/main/HomePageFilters.tsx +++ b/src/components/main/HomePageFilters.tsx @@ -30,9 +30,9 @@ const commonFilterOption = [{ label: 'Latest', value: 'latest' }] // : [] export const postFilterOpt = [ - { label: 'Featured Posts', value: 'suggested' }, + { label: '✅ Featured Posts', value: 'suggested' }, + { label: '🔥 Hot Posts', value: 'hot' }, { label: 'All Posts', value: 'latest' }, - { label: 'Hot Posts', value: 'hot' }, // removed most liked and commented // ...offchainPostFilterOpt, ] @@ -54,8 +54,8 @@ export const commentFilterOpt = enableGraphQl // : [] export const spaceFilterOpt = [ - { label: 'Featured Creators', value: 'suggested' }, - { label: 'Creators Staking', value: 'creators' }, + { label: '✅ Featured Creators', value: 'suggested' }, + { label: '📝 Creators Staking', value: 'creators' }, // ...offchainSpaceFilterOpt, ] @@ -139,6 +139,9 @@ export const Filters = (props: Props) => { > {filters.map(({ label, value }) => ( + {label === 'All Posts' && ( + + )} {label} ))} From b87e682be80c8fc74f704aadc1d435ea112696ad Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Wed, 31 Jan 2024 01:09:20 +0700 Subject: [PATCH 6/9] chore: change wording --- src/components/creators/TopUsersCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/creators/TopUsersCard.tsx b/src/components/creators/TopUsersCard.tsx index fd613d2b6..737f0288f 100644 --- a/src/components/creators/TopUsersCard.tsx +++ b/src/components/creators/TopUsersCard.tsx @@ -70,7 +70,7 @@ export default function TopUsersCard({ ...props }: TopUsersCardProps) { <>
- Top users (this week) + Weekly Top Users
{isMobile && seeMoreButton}
From 7753e7566a704bbbd30c4ec890acca01eac1b052 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Wed, 31 Jan 2024 01:15:19 +0700 Subject: [PATCH 7/9] feat: add emojis to filters --- src/components/main/HomePageFilters.tsx | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/components/main/HomePageFilters.tsx b/src/components/main/HomePageFilters.tsx index a6379fd19..2bab53fd7 100644 --- a/src/components/main/HomePageFilters.tsx +++ b/src/components/main/HomePageFilters.tsx @@ -29,15 +29,16 @@ const commonFilterOption = [{ label: 'Latest', value: 'latest' }] // ] // : [] -export const postFilterOpt = [ - { label: '✅ Featured Posts', value: 'suggested' }, - { label: '🔥 Hot Posts', value: 'hot' }, +type Filter = { label: string; value: string; icon?: string } +export const postFilterOpt: Filter[] = [ + { label: 'Featured Posts', icon: '✅', value: 'suggested' }, + { label: 'Hot Posts', icon: '🔥', value: 'hot' }, { label: 'All Posts', value: 'latest' }, // removed most liked and commented // ...offchainPostFilterOpt, ] -export const commentFilterOpt = enableGraphQl +export const commentFilterOpt: Filter[] = enableGraphQl ? [ ...commonFilterOption, { label: 'Most liked', value: 'liked' }, @@ -53,13 +54,13 @@ export const commentFilterOpt = enableGraphQl // ] // : [] -export const spaceFilterOpt = [ - { label: '✅ Featured Creators', value: 'suggested' }, - { label: '📝 Creators Staking', value: 'creators' }, +export const spaceFilterOpt: Filter[] = [ + { label: 'Featured Creators', icon: '✅', value: 'suggested' }, + { label: 'Creators Staking', value: 'creators' }, // ...offchainSpaceFilterOpt, ] -export const dateFilterOpt = [ +export const dateFilterOpt: Filter[] = [ { label: '1 day', value: 'day' }, { label: '7 days', value: 'week' }, { label: '30 days', value: 'month' }, @@ -124,7 +125,15 @@ export const Filters = (props: Props) => { {!isMobile ? ( ({ + label: ( + + {icon} + {label} + + ), + value, + }))} onChange={onChangeWrap(onFilterChange)} value={type} optionType={'button'} @@ -137,12 +146,10 @@ export const Filters = (props: Props) => { onChange={onFilterChange} className={clsx('w-100', style.FilterSelect)} > - {filters.map(({ label, value }) => ( + {filters.map(({ label, value, icon }) => ( - {label === 'All Posts' && ( - - )} {label} + {icon && {icon}} ))} From 74ae2e7b4810bd1b2733bd1bbfd368377834d711 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Wed, 31 Jan 2024 01:17:44 +0700 Subject: [PATCH 8/9] refactor: use promise allSettled instead of all --- src/rtk/features/replies/repliesSlice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtk/features/replies/repliesSlice.ts b/src/rtk/features/replies/repliesSlice.ts index 624b7f984..89c4aa5d4 100644 --- a/src/rtk/features/replies/repliesSlice.ts +++ b/src/rtk/features/replies/repliesSlice.ts @@ -97,7 +97,7 @@ export const fetchPostReplyIds = createAsyncThunk< const replyIds = await api.blockchain.getReplyIdsByPostId(idToBn(parentId)) - await Promise.all([ + await Promise.allSettled([ dispatch( fetchPosts({ api, withReactionByAccount: myAddress, ids: replyIds, withSpace: false }), ), From bf70137536ca166bd6bc1bbd433fb27945229792 Mon Sep 17 00:00:00 2001 From: teodorus-nathaniel Date: Wed, 31 Jan 2024 01:20:32 +0700 Subject: [PATCH 9/9] feat: add leaderboard menu --- src/layout/SideMenuItems.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/layout/SideMenuItems.tsx b/src/layout/SideMenuItems.tsx index 47eccf5ec..185bb3ab8 100644 --- a/src/layout/SideMenuItems.tsx +++ b/src/layout/SideMenuItems.tsx @@ -14,6 +14,7 @@ import React from 'react' import { FaDiscord } from 'react-icons/fa' import { FiTwitter } from 'react-icons/fi' import { IoFlashOutline } from 'react-icons/io5' +import { MdOutlineLeaderboard } from 'react-icons/md' import { accountUrl } from 'src/components/urls' import { SubIcon } from 'src/components/utils' import config from 'src/config' @@ -57,8 +58,13 @@ export const DefaultMenu: MenuItem[] = [ // icon: , // }, { - name: 'Statistics', + name: 'Leaderboard', page: ['/leaderboard'], + icon: , + }, + { + name: 'Statistics', + page: ['/stats'], icon: , }, Divider,