Skip to content

Commit

Permalink
Merge pull request #209 from okp4/feat/results-page
Browse files Browse the repository at this point in the history
Feat/results page
  • Loading branch information
houssemmimoun27 authored Jun 30, 2023
2 parents c5b65cd + 70db6e1 commit 4ed4ea2
Show file tree
Hide file tree
Showing 14 changed files with 689 additions and 8 deletions.
11 changes: 9 additions & 2 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ const Accordion = dynamic(async () => await import('@/components/accordion/Accor

const Podium = dynamic(async () => await import('@/components/podium/Podium'))

const LeaderboardTable = dynamic(async () => await import('@/components/table/LeaderboardTable'))
const ValidatorsLeaderboardTable = dynamic(
async () => await import('@/components/table/validators/LeaderboardTable')
)

const BuildersLeaderboardTable = dynamic(
async () => await import('@/components/table/builders/LeaderboardTable')
)

const Countdown = dynamic(async () => await import('@/components/countdown/Countdown'))

Expand All @@ -36,7 +42,8 @@ export {
Accordion,
BaseCard,
Podium,
LeaderboardTable,
ValidatorsLeaderboardTable,
BuildersLeaderboardTable,
Countdown,
Snackbar,
GoBackButton,
Expand Down
142 changes: 142 additions & 0 deletions src/components/table/builders/LeaderboardTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, { useCallback, useState, useMemo } from 'react'
import classNames from 'classnames'
import Snackbar from '@/components/snackbar/Snackbar'
import { Search } from '@/components/search/Search'
import { Copy } from '@/components/copy/Copy'
import { useMediaType } from '@/hook/useMediaType'
import type { Column } from '@/components/table/table.type'
import type { BuilderDescriptor, BuildersDescriptor } from '@/entity/builder'

export type LeaderboardTable = {
data: BuildersDescriptor
onSearchChange: (value: string) => void
}

const LeaderboardTable: React.FC<LeaderboardTable> = ({ data, onSearchChange }) => {
const [address, setAddress] = useState<string>('')
const isMobileScreen = useMediaType('(max-width: 580px)')

const handleCopyAddress = useCallback(
(address: string) => {
setAddress(address)
},
[setAddress]
)

const columns: Column<BuilderDescriptor>[] = useMemo(
() =>
[
{
label: 'Rank',
renderCell: (druid: BuilderDescriptor) => <span>{druid.rank.toLocaleString()}</span>,
width: isMobileScreen ? '18%' : '10%'
},
{
label: 'Address',
renderCell: (druid: BuilderDescriptor) => (
<div className="flex-cell">
<span>{druid.valoper}</span>
<Copy item={druid.valoper} onCopied={handleCopyAddress} />
</div>
),
width: isMobileScreen ? '50%' : '25%'
},
{
label: 'Awarded POAP',
renderCell: (druid: BuilderDescriptor) => (
<ul>
{druid.earnings.poap.map(item => (
<li key={item}>{item}</li>
))}
</ul>
),
width: '35%',
hidden: isMobileScreen
},
{
label: 'Awarded know',
renderCell: (druid: BuilderDescriptor) => (
<span>{druid.earnings.know.toLocaleString()}</span>
),
width: isMobileScreen ? '32%' : '30%'
}
].filter(column => !column.hidden),
[handleCopyAddress, isMobileScreen]
)

const handleSearchChange = useCallback(
(value: string) => {
onSearchChange(value)
},
[onSearchChange]
)

const handleSnackbarClose = useCallback(() => {
setAddress('')
}, [setAddress])

return (
<>
<div className="okp4-nemeton-web-results-table-main ">
<div className="okp4-nemeton-web-results-table-header-container">
<h2>RANKING</h2>
<Search onChange={handleSearchChange} />
</div>
<div className="okp4-nemeton-web-results-table-content-container">
<table>
<thead>
<tr>
{columns.map(({ label, width }, index) => (
<th key={index} {...(width && { style: { width } })}>
<span>{label}</span>
</th>
))}
</tr>
</thead>
<tbody>
{data.length > 0 && (
<React.Fragment>
{data.map((row, index) => {
const podiumClassname = classNames({
gold: row.rank === 1,
silver: row.rank === 2,
bronze: row.rank === 3
})
return (
<tr className={podiumClassname} key={index}>
{columns.map((column, index) => {
const { renderCell } = column
return <td key={index}>{renderCell(row)}</td>
})}
{!isMobileScreen && (
<td
className={`okp4-nemeton-web-results-table-podium-logo ${podiumClassname}`}
/>
)}
</tr>
)
})}
</React.Fragment>
)}
{!data.length && (
<tr>
<td colSpan={4} style={{ textAlign: 'center' }}>
No results found...
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
<Snackbar
isOpen={!!address}
message="Address copied to clipboard!"
onClose={handleSnackbarClose}
severityLevel="success"
/>
</>
)
}

export default LeaderboardTable
171 changes: 171 additions & 0 deletions src/components/table/builders/leaderboardTable.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
$podium-colors: ('gold', 'silver', 'bronze');

.okp4-nemeton-web-results-table-main {
display: flex;
align-items: center;
flex-direction: column;
align-items: baseline;

.okp4-nemeton-web-results-table-header-container {
display: flex;
align-items: center;
width: 100%;

@media screen and (max-width: 1000px) {
flex-direction: column;
gap: 28px;
}
}

.okp4-nemeton-web-results-table-content-container {
width: 100%;
margin-top: 20px;
min-height: 400px;
padding-left: 17px;

table {
width: 100%;
border-spacing: 0 12px;
table-layout: fixed;

tr {
height: 48px;
}

th {
font-family: Gotham bold, sans-serif;
line-height: 24px;
font-size: 14px;
color: rgba(255, 255, 255, 0.6);
text-transform: uppercase;
text-align: start;

&:first-child {
padding-left: 41px;

@media screen and (max-width: 1000px) {
padding-left: unset;
}
}
}

tbody {
tr {
font-family: Gotham light, sans-serif;
background: none;
border-radius: 6px;
position: relative;
transform: scale(1);
height: 48px;

&.gold {
background: linear-gradient(90deg, $choco-100 0%, rgba(209, 193, 147, 0) 100%);
}

&.silver {
background: linear-gradient(90deg, $white-200 0%, rgba(180, 184, 187, 0) 100%);
}

&.bronze {
background: linear-gradient(90deg, $choco 0%, rgba(180, 150, 137, 0) 100%);
}

&.gold,
&.silver,
&.bronze {
font-family: Gotham, sans-serif;
font-weight: 700;
background-attachment: fixed;
}

.okp4-nemeton-web-results-table-podium-logo {
position: absolute;
width: 39px;
height: 39px;
background-repeat: no-repeat;
background-position: 0;
left: -14px;
top: -6px;
bottom: 0;

@each $podium-color in $podium-colors {
&.#{$podium-color} {
background-image: url('/icons/#{$podium-color}-druid.svg');
}
}
}

.flex-cell,
a {
@include flex-rows-with-gap(8px);
align-items: center;
max-width: 95%;

> img:first-of-type {
border-radius: 4px;
}

.okp4-nemeton-web-copy-logo {
width: 100%;
}
}

td {
font-size: 16px;
color: $white;
border: unset;
padding: 11px 0;
vertical-align: top;

&:nth-child(2) {
font-family: Gotham light, sans-serif;
}

&:nth-child(3) {
li {
font-family: 'Gotham light', sans-serif;
}
}

&:first-child {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
padding-left: 41px;

@media screen and (max-width: 1000px) {
padding-left: 15px;
}
}

&:last-child {
border-bottom-right-radius: 6px;
border-top-right-radius: 6px;
}

span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

ul {
list-style: none;
padding: 0;
margin: 0;

li {
color: $white;
font-size: 16px;
font-family: Gotham;
line-height: 24px;
margin: 0;
padding: 0;
}
}
}
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { Skeleton } from '@mui/material'
import classNames from 'classnames'
import Image from 'next/image'
import Link from 'next/link'
import hatDruidAnimationData from '../../../public/json/hat-druid.json'
import hatDruidAnimationData from '../../../../public/json/hat-druid.json'
import React, { useCallback, useMemo, useState } from 'react'
import { useMediaType } from '@/hook/useMediaType'
import type { DruidDescriptor } from '@/entity/druid'
import { Search } from '@/components/search/Search'
import Snackbar from '@/components/snackbar/Snackbar'
import LottieLoader from '@/components/loader/LottieLoader'
import { Copy } from '@/components/copy/Copy'
import type { Column } from './table.type'
import type { Column } from '../table.type'

export type LeaderboardTableProps = {
data: DruidDescriptor[]
Expand Down
2 changes: 1 addition & 1 deletion src/components/taskContentIcon/TaskContentIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ArticleIcon from '@mui/icons-material/Article'
import GavelIcon from '@mui/icons-material/Gavel'
import HelpIcon from '@mui/icons-material/Help'
import MoneyIcon from '@mui/icons-material/Money'
import type { TaskContentId,ChallengeTaskContentId } from '@/data/phase/dto.type'
import type { TaskContentId, ChallengeTaskContentId } from '@/data/phase/dto.type'

type TaskContentIconProps = {
id: TaskContentId | ChallengeTaskContentId
Expand Down
Loading

0 comments on commit 4ed4ea2

Please sign in to comment.