Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Commit

Permalink
Add pagination and wallet address to leaderboard
Browse files Browse the repository at this point in the history
  • Loading branch information
illiassmalashchuk committed Oct 9, 2023
1 parent 31aa286 commit 3901004
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 50 deletions.
150 changes: 104 additions & 46 deletions src/components/molecules/leaderboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <span style={{ fontSize: "10px" }}>&#9660;</span>;
const arrowUp = <span style={{ fontSize: "10px" }}>&#9650;</span>;

const Leaderboard: React.FC<Props> = ({ userId, list, onColumnClick }) => {
const Leaderboard: React.FC<Props> = ({ userId, list, isLoading, onLoad }) => {
const [col, setCol] = useState<LeaderboardColumn | null>(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 (
<div className={styles.leaderboard}>
Expand All @@ -47,63 +78,90 @@ const Leaderboard: React.FC<Props> = ({ userId, list, onColumnClick }) => {
</th>
<th
className={styles.leadTableHeadColumn}
onClick={() => onClick(LeaderboardColumn.TotalValueLocked)}
onClick={() => onSort(LeaderboardColumn.TotalValueLocked)}
>
TVL, $ {col === LeaderboardColumn.TotalValueLocked ? arrow : null}
</th>
<th className={styles.leadTableHeadColumn}>Address</th>
<th
className={styles.leadTableHeadColumn}
onClick={() => onClick(LeaderboardColumn.ChallengesCompleted)}
onClick={() => onSort(LeaderboardColumn.ChallengesCompleted)}
>
Number of challenges{" "}
{col === LeaderboardColumn.ChallengesCompleted ? arrow : null}
</th>
<th
className={styles.leadTableHeadColumn}
onClick={() => onClick(LeaderboardColumn.MinutesSpent)}
onClick={() => onSort(LeaderboardColumn.MinutesSpent)}
>
Minutes spent{" "}
{col === LeaderboardColumn.MinutesSpent ? arrow : null}
</th>
</tr>
</thead>
<tbody className={styles.leadTableBody}>
{list.map((item) => {
const isCurrent = userId === item.userId;
return (
<tr
key={item.userId}
className={`${styles.leadTableBodyRow} ${
isCurrent ? styles.userRow : ""
}`}
>
<td
className={`${styles.rankingCell} ${
isCurrent ? styles.userRankingCell : ""
{isLoading ? null : (
<tbody className={styles.leadTableBody}>
{list.map((item) => {
const isCurrent = userId === item.userId;
return (
<tr
key={item.userId}
className={`${styles.leadTableBodyRow} ${
isCurrent ? styles.userRow : ""
}`}
>
<div
className={`${styles.rankingCellNum} ${
isCurrent ? styles.userRankingCellNum : ""
<td
className={`${styles.rankingCell} ${
isCurrent ? styles.userRankingCell : ""
}`}
>
{item.ranking.current}
</div>
{isCurrent ? (
<>
you are here!
<img src="/icons/icon-star-yellow.svg" alt="Star icon" />
</>
) : null}
</td>
<td>{item.totalValueLocked}</td>
<td>{item.challengesCompleted}</td>
<td>{item.minutesSpent}</td>
</tr>
);
})}
</tbody>
<div
className={`${styles.rankingCellNum} ${
isCurrent ? styles.userRankingCellNum : ""
}`}
>
{item.ranking.current}
</div>
{isCurrent ? (
<>
you are here!
<img
src="/icons/icon-star-yellow.svg"
alt="Star icon"
/>
</>
) : null}
</td>
<td>{item.totalValueLocked}</td>
<td title={item.userId}>{`${item.userId.slice(
0,
4,
)}...${item.userId.slice(-4)}`}</td>
<td>{item.challengesCompleted}</td>
<td>{item.minutesSpent}</td>
</tr>
);
})}
</tbody>
)}
</table>
{isLoading ? <div className={styles.loading}>Loading</div> : null}
<div className={styles.paginationBlock}>
<button
className={styles.paginationButton}
disabled={pageNumber === 1 || isLoading}
onClick={onPrev}
>
Prev
</button>
<button
className={styles.paginationButton}
disabled={pageNumber === maxPage || isLoading}
onClick={onNext}
>
Next
</button>
</div>
</div>
);
};
Expand Down
27 changes: 24 additions & 3 deletions src/components/molecules/leaderboard/style.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@ th {

.userRankingCellNum {
border: none;
padding: 5px;
width: 37px;
height: 37px;
padding: 5px 10px;
background-color: #ffd748;
margin-right: 5px;
}
Expand All @@ -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;
}
8 changes: 7 additions & 1 deletion src/pages/dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export default function Dashboard() {
const [totalCompleted, setTotalCompleted] = useState<number>(0);
const [ranking, setRanking] = useState<Ranking | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isLeaderboardLoading, setIsLeaderboardLoading] =
useState<boolean>(false);

const fetchUserChallenges = async () => {
setIsLoading(true);
Expand All @@ -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) {
Expand All @@ -66,6 +69,8 @@ export default function Dashboard() {
position: "top-center",
autoClose: 2000,
});
} finally {
setIsLeaderboardLoading(false);
}
};

Expand Down Expand Up @@ -153,7 +158,8 @@ export default function Dashboard() {
<Leaderboard
userId={address}
list={leaderboard}
onColumnClick={fetchOnlyLeaderboard}
onLoad={fetchOnlyLeaderboard}
isLoading={isLeaderboardLoading}
/>
</TabItem>
</Tabs>
Expand Down
3 changes: 3 additions & 0 deletions src/services/leaderboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]>("/leaderboard", {
params: {
Expand All @@ -23,6 +25,7 @@ export const fetchLeaderboard = async ({
sort: `${colName},${direction}`,
}
: {}),
...(pageNumber ? { pageNumber } : {}),
},
});
};

0 comments on commit 3901004

Please sign in to comment.