Skip to content

Commit

Permalink
Competition leaderboard (#778)
Browse files Browse the repository at this point in the history
* SOV-3830: Initial setup (#776)

* Initial commit

* Translations + responsive behaviour

* Add padding to the CTA links section

* Points section (#779)

* SOV-3855: Social leaderboard (#781)

* Initial configuration

* Adjust social leaderboard styling

* SOV-3856, SOV-3857: Trading and staking leaderboard (#785)

* Initial configuration

* Fix redash links

* Trading leaderboard mobile styles

* Scroll to social tab

* Add single wallet table

* Refactor trading leaderboard

* Staking leaderboard initial configuration

* Small adjustments

* Parse staking badges

* Unify staking and trading tables

* Adjust badges position on desktop

* Fix review remarks

* Leaderboard adjustments (#790)

* Adjust column titles

* Leaderboard final adjustments (#792)

* Fix the message for inactive wallets

* Do not show +100 points badge

* Update social leaderboard URLs

* feat: copy updates

* Text adjustments

* Social leaderboard adjustments

* Adjustments

---------

Co-authored-by: soulBit <[email protected]>

* Copy adjustment

* chore: add changeset

* chore: remove outdated comment

* feat: add staking subtitle

* chore: add bottom margin to subtitle

---------

Co-authored-by: soulBit <[email protected]>
  • Loading branch information
tiltom and soulBit authored Mar 4, 2024
1 parent 8117d37 commit 50f7724
Show file tree
Hide file tree
Showing 42 changed files with 1,352 additions and 59 deletions.
5 changes: 5 additions & 0 deletions .changeset/smooth-radios-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"frontend": patch
---

SOV-3935: Competition leaderboard
46 changes: 46 additions & 0 deletions apps/frontend/src/app/2_molecules/CTA/CTA.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { FC } from 'react';

import { Button, ButtonStyle, Paragraph } from '@sovryn/ui';

type CTAProps = {
index: number;
backgroundImage: string;
title: string;
description: string;
action: string;
navigateTo: () => void;
};

export const CTA: FC<CTAProps> = ({
index,
backgroundImage,
title,
description,
action,
navigateTo,
}) => (
<div
key={index}
className="relative p-4 md:p-6 bg-gray-70 rounded flex flex-col md:items-start justify-end md:min-h-60 min-h-40"
>
<img
src={backgroundImage}
alt={title}
className="absolute top-0 right-0 md:max-w-none max-w-14"
/>
<Paragraph
className="mb-6 font-medium text-sm xl:max-w-36 xl:pr-0 pr-12"
children={title}
/>
<Paragraph
className="mb-4 md:mb-6 font-medium xl:pr-0 pr-12 text-gray-30"
children={description}
/>
<Button
className="w-full sm:w-auto"
text={action}
onClick={navigateTo}
style={ButtonStyle.secondary}
/>
</div>
);
14 changes: 14 additions & 0 deletions apps/frontend/src/app/3_organisms/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { FC, useCallback, useMemo, useReducer } from 'react';

import { t } from 'i18next';
import { useNavigate } from 'react-router-dom';

import { SupportedTokens } from '@sovryn/contracts';
import {
Expand Down Expand Up @@ -30,6 +31,13 @@ export const Header: FC = () => {
useWalletConnect();
useWrongNetworkCheck();

const navigate = useNavigate();

const handleLeaderboardClick = useCallback(
() => navigate(`/powa`),
[navigate],
);

const { balance } = useAssetBalance(SupportedTokens.rbtc);

const hasRbtcBalance = useMemo(() => Number(balance) !== 0, [balance]);
Expand Down Expand Up @@ -82,6 +90,12 @@ export const Header: FC = () => {
</li>
))}
<ProductLinks />
<Button
text={t(translations.leaderboardPage.headerLink)}
style={ButtonStyle.primary}
className="bg-[#24BFB74D]/[0.3] border-[#24BFB74D]/[0.3] hover:bg-[#24BFB74D]"
onClick={handleLeaderboardClick}
/>
</ol>
}
secondaryContent={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,21 @@ import { useNavigate } from 'react-router-dom';

import { Button, ButtonSize, ButtonStyle } from '@sovryn/ui';

import { WIKI_LINKS } from '../../../../../constants/links';
import { POWA_LINK } from '../../../../../constants/links';
import { translations } from '../../../../../locales/i18n';
import styles from './Banner.module.css';
import { LandingPromoCard } from './components/LandingPromoCard/LandingPromoCard';

export const Banner: FC = () => {
const navigate = useNavigate();

const handleClick = useCallback(
() => navigate('/convert?from=rbtc&to=sov'),
[navigate],
);
const handleClick = useCallback(() => navigate('/powa'), [navigate]);

return (
<div className="w-full relative pb-7">
<Carousel
arrows={false}
draggable
draggable={false} // Needs to be true when we have more than 1 promo
partialVisible={false}
focusOnSelect={false}
responsive={{
Expand All @@ -45,20 +42,24 @@ export const Banner: FC = () => {
infinite
>
<LandingPromoCard
heading={t(translations.landingPage.promotions.sov.title)}
description={t(translations.landingPage.promotions.sov.description)}
heading={t(translations.landingPage.promotions.competition.title)}
description={t(
translations.landingPage.promotions.competition.description,
)}
actions={
<>
<Button
style={ButtonStyle.secondary}
size={ButtonSize.large}
text={t(translations.landingPage.promotions.sov.cta)}
text={t(translations.landingPage.promotions.competition.cta)}
onClick={handleClick}
/>

<Button
text={t(translations.stakePage.stakingRewards.learnMoreLink)}
href={WIKI_LINKS.STAKING}
text={t(
translations.landingPage.promotions.competition.secondaryCta,
)}
href={POWA_LINK} // TODO: Needs to be changed later, the landing page does not exist yet
style={ButtonStyle.ghost}
hrefExternal
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ export const LandingPromoCard: FC<LandingPromoCardProps> = ({
actions,
}) => (
<div className="mx-1">
<div className="select-none border-4 border-sovryn-blue w-full bg-gray-80 h-60 rounded p-4 md:p-6 flex flex-col justify-between">
<div className="select-none border-4 border-primary w-full bg-gray-80 h-60 rounded p-4 md:p-6 flex flex-col justify-between">
<div>
<Heading className="font-medium font-druk text-gray-10 tracking-wide antialiased text-[2rem] xs:text-[2.25rem] md:text-[2.875rem] leading-[3.75rem] uppercase">
{heading}
</Heading>
<Paragraph className="font-medium leading-5 mt-2 text-sm">
<Paragraph className="font-medium leading-5 my-2 text-sm">
{description}
</Paragraph>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { t } from 'i18next';
import { useNavigate } from 'react-router-dom';

import { SupportedTokens } from '@sovryn/contracts';
import { Button, ButtonStyle, Paragraph } from '@sovryn/ui';

import { CTA } from '../../../../2_molecules/CTA/CTA';
import borrowBg from '../../../../../assets/images/QuickLaunch/borrow_bg.svg';
import earnBg from '../../../../../assets/images/QuickLaunch/earn_bg.svg';
import lendBg from '../../../../../assets/images/QuickLaunch/lend_bg.svg';
Expand Down Expand Up @@ -75,30 +75,14 @@ export const QuickLaunch: FC = () => {
return (
<div className="bg-gray-80 rounded min-h-72 md:p-6 p-4 sm:mb-14 mb-10 grid md:grid-cols-2 xl:grid-cols-4 md:gap-6 gap-4">
{options.map((option, index) => (
<div
key={index}
className="relative p-4 md:p-6 bg-gray-70 rounded flex flex-col md:items-start justify-end md:min-h-60 min-h-40"
>
<img
src={option.backgroundImage}
alt={option.title}
className="absolute top-0 right-0 md:max-w-none max-w-14"
/>
<Paragraph
className="mb-6 font-medium text-sm xl:max-w-36 xl:pr-0 pr-12"
children={option.title}
/>
<Paragraph
className="mb-4 md:mb-6 font-medium xl:pr-0 pr-12 text-gray-30"
children={option.description}
/>
<Button
className="w-full sm:w-auto"
text={option.action}
onClick={option.url}
style={ButtonStyle.secondary}
/>
</div>
<CTA
index={index}
backgroundImage={option.backgroundImage}
title={option.title}
description={option.description}
action={option.action}
navigateTo={option.url}
/>
))}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Trans } from 'react-i18next';
import { Button, ButtonStyle } from '@sovryn/ui';

import { translations } from '../../../../../locales/i18n';
import { scrollToElement } from '../../../../../utils/helpers';

const pageTranslations = translations.landingPage.titleSection;

Expand All @@ -15,12 +16,7 @@ type TitleSectionProps = {

export const TitleSection: FC<TitleSectionProps> = ({ ctaRef }) => {
const ctaClickHandler = useCallback(() => {
if (ctaRef.current) {
ctaRef.current.scrollIntoView({
behavior: 'smooth',
block: 'start',
});
}
scrollToElement(ctaRef);
}, [ctaRef]);

return (
Expand Down
27 changes: 27 additions & 0 deletions apps/frontend/src/app/5_pages/LeaderboardPage/LeaderboardPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { FC, useRef, useState } from 'react';

import { CTALinks } from './components/CTALinks/CTALinks';
import { Intro } from './components/Intro/Intro';
import { Leaderboard } from './components/Leaderboard/Leaderboard';
import { PointsSection } from './components/PointsSection/PointsSection';

const LeaderboardPage: FC = () => {
const tableRef = useRef<HTMLDivElement>(null);
const pointsSectionRef = useRef<HTMLDivElement>(null);
const [tabIndex, setTabIndex] = useState(0);

return (
<div className="w-full flex items-center flex-col px-0 md:px-20">
<Intro pointsSectionRef={pointsSectionRef} />
<CTALinks tableRef={tableRef} setTabIndex={setTabIndex} />
<Leaderboard
index={tabIndex}
setIndex={setTabIndex}
tableRef={tableRef}
/>
<PointsSection pointsSectionRef={pointsSectionRef} />
</div>
);
};

export default LeaderboardPage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, {
Dispatch,
FC,
RefObject,
SetStateAction,
useCallback,
useMemo,
} from 'react';

import { t } from 'i18next';
import { useNavigate } from 'react-router-dom';

import { CTA } from '../../../../2_molecules/CTA/CTA';
import socialBg from '../../../../../assets/images/Leaderboard/social.svg';
import stakeBg from '../../../../../assets/images/Leaderboard/stake.svg';
import tradeBg from '../../../../../assets/images/Leaderboard/trade.svg';
import { translations } from '../../../../../locales/i18n';
import { scrollToElement } from '../../../../../utils/helpers';

const baseTranslation = translations.leaderboardPage.ctaLinksSection;

type CTALinksProps = {
tableRef: RefObject<HTMLDivElement>;
setTabIndex: Dispatch<SetStateAction<number>>;
};

export const CTALinks: FC<CTALinksProps> = ({ tableRef, setTabIndex }) => {
const navigate = useNavigate();

const socialClickHandler = useCallback(() => {
if (tableRef.current) {
scrollToElement(tableRef);
setTabIndex(2);
}
}, [setTabIndex, tableRef]);

const options = useMemo(
() => [
{
title: t(baseTranslation.stake.title),
description: t(baseTranslation.stake.description),
action: t(baseTranslation.stake.cta),
onClick: () => navigate('/earn/staking'),
backgroundImage: stakeBg,
},
{
title: t(baseTranslation.trade.title),
description: t(baseTranslation.trade.description),
action: t(baseTranslation.trade.cta),
onClick: () =>
window.open('https://app.babelfish.money/convert', '_blank'),
backgroundImage: tradeBg,
},
{
title: t(baseTranslation.social.title),
description: t(baseTranslation.social.description),
action: t(baseTranslation.social.cta),
onClick: socialClickHandler,
backgroundImage: socialBg,
},
],
[navigate, socialClickHandler],
);

return (
<div className="w-full sm:p-6 p-4 sm:w-3/4 mt-8 bg-gray-80 rounded min-h-64 grid md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 xl:gap-6 gap-4">
{options.map(
({ backgroundImage, title, description, action, onClick }, index) => (
<CTA
index={index}
backgroundImage={backgroundImage}
title={title}
description={description}
action={action}
navigateTo={onClick}
/>
),
)}
</div>
);
};
Loading

0 comments on commit 50f7724

Please sign in to comment.