diff --git a/src/components/molecules/leaderboard/index.tsx b/src/components/molecules/leaderboard/index.tsx index 1b96cb51..247445c6 100644 --- a/src/components/molecules/leaderboard/index.tsx +++ b/src/components/molecules/leaderboard/index.tsx @@ -9,33 +9,64 @@ import styles from "./style.module.css"; type Props = { userId?: string; list: LeaderboardI[]; - onColumnClick: (params: LeaderboardParams) => void; + isLoading: boolean; + onLoad: (params: LeaderboardParams) => void; }; +const PAGE_SIZE = 10; + const arrowDown = ; const arrowUp = ; -const Leaderboard: React.FC = ({ userId, list, onColumnClick }) => { +const Leaderboard: React.FC = ({ userId, list, isLoading, onLoad }) => { const [col, setCol] = useState(null); - const [asc, setAsc] = useState(true); + const [isAsc, setIsAsc] = useState(false); + + const [pageNumber, setPageNumber] = useState(1); + + const maxUsers = list[0]?.ranking.total; + const maxPage = maxUsers / PAGE_SIZE; - const onClick = (val: LeaderboardColumn) => { - const nextAsc = col === val ? !asc : false; - setAsc(col === val ? !asc : false); - onColumnClick({ + const onSort = (val: LeaderboardColumn) => { + // if click on current column ? change direction : set default direction + const nextAsc = col === val ? !isAsc : false; + setIsAsc(nextAsc); + onLoad({ colName: val, - direction: nextAsc ? "desc" : "asc", + direction: nextAsc ? "asc" : "desc", }); setCol(val); + setPageNumber(1); }; const onReset = () => { - setAsc(true); + setIsAsc(true); setCol(null); - onColumnClick({}); + onLoad({}); + setPageNumber(1); + }; + + const onNext = () => { + const nextPageNumber = pageNumber + 1; + setPageNumber(nextPageNumber); + onLoad({ + pageNumber: nextPageNumber, + ...(col ? { colName: col } : {}), + direction: isAsc ? "asc" : "desc", + }); + }; + + const onPrev = () => { + const nextPageNumber = pageNumber - 1; + setPageNumber(nextPageNumber); + onLoad({ + pageNumber: nextPageNumber, + ...(col ? { colName: col } : {}), + direction: isAsc ? "asc" : "desc", + }); }; - const arrow = asc ? arrowDown : arrowUp; + const arrow = !isAsc ? arrowDown : arrowUp; return (
@@ -47,63 +78,90 @@ const Leaderboard: React.FC = ({ userId, list, onColumnClick }) => { onClick(LeaderboardColumn.TotalValueLocked)} + onClick={() => onSort(LeaderboardColumn.TotalValueLocked)} > TVL, $ {col === LeaderboardColumn.TotalValueLocked ? arrow : null} + Address onClick(LeaderboardColumn.ChallengesCompleted)} + onClick={() => onSort(LeaderboardColumn.ChallengesCompleted)} > Number of challenges{" "} {col === LeaderboardColumn.ChallengesCompleted ? arrow : null} onClick(LeaderboardColumn.MinutesSpent)} + onClick={() => onSort(LeaderboardColumn.MinutesSpent)} > Minutes spent{" "} {col === LeaderboardColumn.MinutesSpent ? arrow : null} - - {list.map((item) => { - const isCurrent = userId === item.userId; - return ( - - + {list.map((item) => { + const isCurrent = userId === item.userId; + return ( + -
- {item.ranking.current} -
- {isCurrent ? ( - <> - you are here! - Star icon - - ) : null} - - {item.totalValueLocked} - {item.challengesCompleted} - {item.minutesSpent} - - ); - })} - +
+ {item.ranking.current} +
+ {isCurrent ? ( + <> + you are here! + Star icon + + ) : null} + + {item.totalValueLocked} + {`${item.userId.slice( + 0, + 4, + )}...${item.userId.slice(-4)}`} + {item.challengesCompleted} + {item.minutesSpent} + + ); + })} + + )} + {isLoading ?
Loading
: null} +
+ + +
); }; diff --git a/src/components/molecules/leaderboard/style.module.css b/src/components/molecules/leaderboard/style.module.css index 7e9daa62..5a136967 100644 --- a/src/components/molecules/leaderboard/style.module.css +++ b/src/components/molecules/leaderboard/style.module.css @@ -71,9 +71,7 @@ th { .userRankingCellNum { border: none; - padding: 5px; - width: 37px; - height: 37px; + padding: 5px 10px; background-color: #ffd748; margin-right: 5px; } @@ -95,3 +93,26 @@ th { color: #585858; font-size: 22px; } + +.paginationBlock { + display: flex; + gap: 10px; + align-self: flex-end; +} + +.paginationButton { + padding: 10px; + font-size: 14px; + font-weight: 500; + font-family: var(--ifm-font-family-base); + border-radius: 4px; + border: none; + cursor: pointer; +} + +.loading { + height: 536px; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 8e43fa7b..0ac7fe16 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -35,6 +35,8 @@ export default function Dashboard() { const [totalCompleted, setTotalCompleted] = useState(0); const [ranking, setRanking] = useState(null); const [isLoading, setIsLoading] = useState(true); + const [isLeaderboardLoading, setIsLeaderboardLoading] = + useState(false); const fetchUserChallenges = async () => { setIsLoading(true); @@ -57,6 +59,7 @@ export default function Dashboard() { const fetchOnlyLeaderboard = async (params: LeaderboardParams) => { try { + setIsLeaderboardLoading(true); const result = await fetchLeaderboard(params); setLeaderboard(result?.data); } catch (e) { @@ -66,6 +69,8 @@ export default function Dashboard() { position: "top-center", autoClose: 2000, }); + } finally { + setIsLeaderboardLoading(false); } }; @@ -153,7 +158,8 @@ export default function Dashboard() { diff --git a/src/services/leaderboard.ts b/src/services/leaderboard.ts index 60513497..5a70adcd 100644 --- a/src/services/leaderboard.ts +++ b/src/services/leaderboard.ts @@ -10,11 +10,13 @@ export enum LeaderboardColumn { export type LeaderboardParams = { colName?: LeaderboardColumn; direction?: "asc" | "desc"; + pageNumber?: number; }; export const fetchLeaderboard = async ({ colName, direction = "asc", + pageNumber, }: LeaderboardParams) => { return await httpClient.get("/leaderboard", { params: { @@ -23,6 +25,7 @@ export const fetchLeaderboard = async ({ sort: `${colName},${direction}`, } : {}), + ...(pageNumber ? { pageNumber } : {}), }, }); };