-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Integrate Leaderboad Backend (#1858)
- Loading branch information
Showing
27 changed files
with
1,044 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,33 @@ | ||
export default async function Index() { | ||
return <h1 className="text-mono-80 h1">Welcome to testnet leaderboard</h1>; | ||
import cx from 'classnames'; | ||
|
||
import CountdownSection from '../components/CountdownSection'; | ||
import FAQSection from '../components/FAQSection'; | ||
import RankingTableSection from '../components/RankingTableSection'; | ||
|
||
export default function Index() { | ||
return ( | ||
<div | ||
className={cx( | ||
'bg-body bg-repeat-y bg-center', | ||
'py-[60px] md:py-[90px] px-2 lg:px-0' | ||
)} | ||
> | ||
<div className="lg:max-w-[1440px] lg:mx-auto"> | ||
<div | ||
className={cx( | ||
'lg:w-[77.5%] lg:mx-auto py-[48px] px-2 lg:px-[192px]', | ||
'border-2 border-mono-0 rounded-2xl', | ||
'flex flex-col gap-[64px]', | ||
'bg-[linear-gradient(180deg,rgba(255,255,255,0.2)_0%,rgba(255,255,255,0)_100%)]' | ||
)} | ||
> | ||
<CountdownSection /> | ||
<hr className="border-mono-200" /> | ||
<RankingTableSection /> | ||
<hr className="border-mono-200" /> | ||
<FAQSection /> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
70 changes: 70 additions & 0 deletions
70
apps/testnet-leaderboard/components/CountdownSection/Badges.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { Typography } from '@webb-tools/webb-ui-components/typography/Typography'; | ||
import capitalize from 'lodash/capitalize'; | ||
import type { FC } from 'react'; | ||
|
||
import { BADGE_ICON_RECORD } from '../../constants'; | ||
import { BadgeEnum } from '../../types'; | ||
|
||
const BADGE_TO_NAME = { | ||
[BadgeEnum.CREATOR]: 'Content Creator', | ||
[BadgeEnum.GOVERNANCE]: 'Governance Guardian', | ||
[BadgeEnum.SPECIALIST]: 'Tx Specialist', | ||
} as const satisfies Partial<{ | ||
[key in BadgeEnum]: string; | ||
}>; | ||
|
||
const getBadgeName = (badge: string) => { | ||
if (badge in BADGE_TO_NAME) { | ||
return BADGE_TO_NAME[badge as keyof typeof BADGE_TO_NAME]; | ||
} | ||
|
||
return null; | ||
}; | ||
|
||
const Badges = () => { | ||
return ( | ||
<div className="flex flex-wrap justify-center gap-1"> | ||
{Object.entries(BADGE_ICON_RECORD).map(([badge, icon], idx) => { | ||
const name = getBadgeName(badge) ?? badge; | ||
const fmtName = name.split(' ').map(capitalize).join(' '); | ||
|
||
return ( | ||
<Badge | ||
key={`${badge}-${idx}`} | ||
icon={icon} | ||
name={fmtName} | ||
shorthand={capitalize(badge)} | ||
/> | ||
); | ||
})} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Badges; | ||
|
||
/** @internal */ | ||
const Badge: FC<{ icon: string; name: string; shorthand?: string }> = ({ | ||
icon, | ||
name, | ||
shorthand, | ||
}) => { | ||
return ( | ||
<> | ||
<Typography | ||
variant="mkt-body2" | ||
fw="bold" | ||
className="hidden md:block bg-[rgba(31,29,43,0.1)] px-2 py-[2px] rounded-full mt-1" | ||
> | ||
{icon} {name} | ||
</Typography> | ||
<Typography | ||
variant="mkt-body2" | ||
fw="bold" | ||
className="block md:hidden bg-[rgba(31,29,43,0.1)] px-2 py-[2px] rounded-full mt-1" | ||
> | ||
{icon} {shorthand || name} | ||
</Typography> | ||
</> | ||
); | ||
}; |
29 changes: 29 additions & 0 deletions
29
apps/testnet-leaderboard/components/CountdownSection/CTAButtons.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
'use client'; | ||
|
||
import Button from '@webb-tools/webb-ui-components/components/buttons/Button'; | ||
|
||
import { GUIDELINES_URL, REQUEST_POINTS_URL } from '../../constants'; | ||
|
||
const CTAButtons = () => { | ||
return ( | ||
<div className="flex items-center justify-center gap-4"> | ||
<Button | ||
variant="secondary" | ||
href={GUIDELINES_URL} | ||
target="_blank" | ||
className="px-5 md:px-9" | ||
> | ||
View Guidelines | ||
</Button> | ||
<Button | ||
href={REQUEST_POINTS_URL} | ||
target="_blank" | ||
className="px-5 md:px-9" | ||
> | ||
Request Points | ||
</Button> | ||
</div> | ||
); | ||
}; | ||
|
||
export default CTAButtons; |
90 changes: 90 additions & 0 deletions
90
apps/testnet-leaderboard/components/CountdownSection/TimeRemaining.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
'use client'; | ||
|
||
import { Typography } from '@webb-tools/webb-ui-components/typography/Typography'; | ||
import cx from 'classnames'; | ||
import type { FC } from 'react'; | ||
|
||
import { END_DATE } from '../../constants'; | ||
import useTimeRemaining from '../../hooks/useTimeRemaining'; | ||
|
||
const TimeRemaining = () => { | ||
const { days, hours, minutes, seconds } = useTimeRemaining(END_DATE); | ||
|
||
return ( | ||
<div className="space-y-[32px]"> | ||
<Typography | ||
variant="mkt-small-caps" | ||
fw="bold" | ||
className="text-center text-mono-200" | ||
> | ||
Time Remaining | ||
</Typography> | ||
<div className="flex justify-between gap-6 px-4 md:justify-center md:gap-12"> | ||
<CountdownItem | ||
timeUnit="Days" | ||
value={typeof days === 'number' ? days.toString() : null} | ||
/> | ||
<CountdownItem | ||
timeUnit="Hours" | ||
value={typeof hours === 'number' ? hours.toString() : null} | ||
/> | ||
<CountdownItem | ||
timeUnit="Minutes" | ||
value={typeof minutes === 'number' ? minutes.toString() : null} | ||
/> | ||
<CountdownItem | ||
timeUnit="Seconds" | ||
value={typeof seconds === 'number' ? seconds.toString() : null} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default TimeRemaining; | ||
|
||
/** @internal */ | ||
const CountdownItem: FC<{ timeUnit: string; value: string | null }> = ({ | ||
timeUnit, | ||
value, | ||
}) => { | ||
const convertedValue = !value | ||
? '--' | ||
: value.length === 1 | ||
? `0${value}` | ||
: value; | ||
|
||
return ( | ||
<div className="flex flex-col items-center w-full gap-3 md:w-auto"> | ||
<div className="flex w-full gap-3 md:w-auto md:gap-4"> | ||
{convertedValue.split('').map((char, idx) => ( | ||
<div | ||
className={cx( | ||
'w-full aspect-[5/8] md:aspect-auto md:w-[55px] md:h-[92px]', | ||
'border border-mono-0 rounded-xl', | ||
'flex justify-center items-center', | ||
'bg-[linear-gradient(180deg,#FFFFFF_0%,rgba(255,255,255,0.5)_100%)]', | ||
'shadow-[0_4px_4px_rgba(0,0,0,0.25)]' | ||
)} | ||
key={idx} | ||
> | ||
<Typography | ||
variant="mkt-h3" | ||
fw="black" | ||
className="text-center text-mono-200" | ||
> | ||
{char} | ||
</Typography> | ||
</div> | ||
))} | ||
</div> | ||
<Typography | ||
variant="mkt-small-caps" | ||
fw="black" | ||
className="text-center text-mono-200" | ||
> | ||
{timeUnit} | ||
</Typography> | ||
</div> | ||
); | ||
}; |
56 changes: 56 additions & 0 deletions
56
apps/testnet-leaderboard/components/CountdownSection/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { Typography } from '@webb-tools/webb-ui-components/typography/Typography'; | ||
|
||
import Badges from './Badges'; | ||
import CTAButtons from './CTAButtons'; | ||
import TimeRemaining from './TimeRemaining'; | ||
|
||
const CountdownSection = () => { | ||
return ( | ||
<div className="space-y-9"> | ||
<div className="space-y-4"> | ||
<Typography | ||
variant="mkt-small-caps" | ||
fw="black" | ||
className="text-center text-purple-70" | ||
> | ||
NOW LIVE | ||
</Typography> | ||
<Typography | ||
variant="mkt-h3" | ||
fw="black" | ||
className="text-center text-mono-200" | ||
> | ||
Tangle Testnet Leaderboard | ||
</Typography> | ||
<Typography | ||
variant="mkt-body2" | ||
fw="medium" | ||
className="text-center text-mono-140" | ||
> | ||
Our Tangle testnet leaderboard highlights top contributors, ranked by | ||
points earned through activities such as running validators, engaging | ||
in governance, crafting protocol extensions, transacting, and more! | ||
</Typography> | ||
</div> | ||
|
||
<TimeRemaining /> | ||
|
||
<div className="space-y-4"> | ||
<Typography | ||
variant="mkt-body2" | ||
fw="medium" | ||
className="text-center text-mono-140" | ||
> | ||
Unlock points and badges as you engage in the Tangle Network. Explore | ||
the guidelines or request points now! | ||
</Typography> | ||
|
||
<CTAButtons /> | ||
</div> | ||
|
||
<Badges /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default CountdownSection; |
54 changes: 54 additions & 0 deletions
54
apps/testnet-leaderboard/components/FAQSection/FAQAccordion.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
'use client'; | ||
|
||
import { | ||
Accordion, | ||
AccordionButton, | ||
AccordionContent, | ||
AccordionItem, | ||
} from '@webb-tools/webb-ui-components/components/Accordion'; | ||
import { Typography } from '@webb-tools/webb-ui-components/typography/Typography'; | ||
import cx from 'classnames'; | ||
import type { FC, ReactNode } from 'react'; | ||
|
||
interface FAQAccordionProps { | ||
items: Array<{ question: string; answer: string | ReactNode }>; | ||
className?: string; | ||
itemClassName?: string; | ||
} | ||
|
||
const FAQAccordion: FC<FAQAccordionProps> = ({ | ||
items, | ||
className, | ||
itemClassName, | ||
}) => { | ||
return ( | ||
<Accordion collapsible type="single" className={className}> | ||
{items.map((item, index) => ( | ||
<AccordionItem | ||
key={index} | ||
value={item.question} | ||
className={cx('p-0', itemClassName)} | ||
> | ||
<AccordionButton className="gap-2 px-0 py-4"> | ||
<Typography | ||
variant="mkt-body2" | ||
className="font-black text-mono-200" | ||
> | ||
{item.question} | ||
</Typography> | ||
</AccordionButton> | ||
<AccordionContent className="px-0"> | ||
<Typography | ||
variant="mkt-body2" | ||
className="font-medium whitespace-pre-wrap text-mono-160" | ||
> | ||
{item.answer} | ||
</Typography> | ||
</AccordionContent> | ||
</AccordionItem> | ||
))} | ||
</Accordion> | ||
); | ||
}; | ||
|
||
export default FAQAccordion; |
Oops, something went wrong.