chore(trading): i18n-friendly referrals (#5113)

This commit is contained in:
Art 2023-10-24 17:43:33 +02:00 committed by GitHub
parent 82fb29d541
commit 6c9272cd53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 115 additions and 83 deletions

View File

@ -81,7 +81,7 @@ export const ApplyCodeForm = () => {
if (!res) {
setError('code', {
type: 'required',
message: 'The transaction could not be sent',
message: t('The transaction could not be sent'),
});
}
if (res) {
@ -98,7 +98,7 @@ export const ApplyCodeForm = () => {
message:
err instanceof Error
? err.message
: 'Your code has been rejected',
: t('Your code has been rejected'),
});
}
});
@ -152,7 +152,7 @@ export const ApplyCodeForm = () => {
<span className="text-vega-green-500">
<VegaIcon name={VegaIconNames.TICK} size={20} />
</span>{' '}
<span className="pt-1">Code applied</span>
<span className="pt-1">{t('Code applied')}</span>
</h3>
</div>
);
@ -162,7 +162,7 @@ export const ApplyCodeForm = () => {
if (!pubKey) {
return {
disabled: false,
children: 'Connect wallet',
children: t('Connect wallet'),
type: 'button' as ButtonHTMLAttributes<HTMLButtonElement>['type'],
onClick: ((event) => {
event.preventDefault();
@ -174,7 +174,7 @@ export const ApplyCodeForm = () => {
if (isReadOnly) {
return {
disabled: true,
children: 'Apply a code',
children: t('Apply a code'),
type: 'submit' as ButtonHTMLAttributes<HTMLButtonElement>['type'],
};
}
@ -182,14 +182,14 @@ export const ApplyCodeForm = () => {
if (status === 'requested') {
return {
disabled: true,
children: 'Confirm in wallet...',
children: t('Confirm in wallet...'),
type: 'submit' as ButtonHTMLAttributes<HTMLButtonElement>['type'],
};
}
return {
disabled: false,
children: 'Apply a code',
children: t('Apply a code'),
type: 'submit' as ButtonHTMLAttributes<HTMLButtonElement>['type'],
};
};
@ -198,10 +198,10 @@ export const ApplyCodeForm = () => {
<>
<div className="w-2/3 max-w-md mx-auto bg-vega-clight-800 dark:bg-vega-cdark-800 p-8 rounded-lg">
<h3 className="mb-4 text-2xl text-center calt">
Apply a referral code
{t('Apply a referral code')}
</h3>
<p className="mb-4 text-center text-base">
Enter a referral code to get trading discounts.
{t('Enter a referral code to get trading discounts.')}
</p>
<form
className={classNames('w-full flex flex-col gap-4', {
@ -210,11 +210,11 @@ export const ApplyCodeForm = () => {
onSubmit={handleSubmit(onSubmit)}
>
<label>
<span className="sr-only">Your referral code</span>
<span className="sr-only">{t('Your referral code')}</span>
<Input
hasError={Boolean(errors.code)}
{...register('code', {
required: 'You have to provide a code to apply it.',
required: t('You have to provide a code to apply it.'),
validate: validateCode,
})}
placeholder="Enter a code"
@ -236,7 +236,7 @@ export const ApplyCodeForm = () => {
) : null}
{previewData ? (
<div className="mt-10">
<h2 className="text-2xl mb-5">You are joining</h2>
<h2 className="text-2xl mb-5">{t('You are joining')}</h2>
<Statistics data={previewData} as="referee" />
</div>
) : null}

View File

@ -24,6 +24,7 @@ import {
DISCLAIMER_REFERRAL_DOCS_LINK,
} from './constants';
import { useReferral } from './hooks/use-referral';
import { t } from '@vegaprotocol/i18n';
export const CreateCodeContainer = () => {
return <CreateCodeForm />;
@ -38,10 +39,13 @@ export const CreateCodeForm = () => {
return (
<div className="w-2/3 max-w-md mx-auto bg-vega-clight-800 dark:bg-vega-cdark-800 p-8 rounded-lg">
<h3 className="mb-4 text-2xl text-center calt">Create a referral code</h3>
<h3 className="mb-4 text-2xl text-center calt">
{t('Create a referral code')}
</h3>
<p className="mb-4 text-center text-base">
Generate a referral code to share with your friends and start earning
commission.
{t(
'Generate a referral code to share with your friends and start earning commission.'
)}
</p>
<div className="w-full flex flex-col">
@ -56,12 +60,12 @@ export const CreateCodeForm = () => {
}
}}
>
{pubKey ? 'Create a referral code' : 'Connect wallet'}
{pubKey ? t('Create a referral code') : t('Connect wallet')}
</RainbowButton>
</div>
<Dialog
title="Create a referral code"
title={t('Create a referral code')}
open={dialogOpen}
onChange={() => setDialogOpen(false)}
size="small"
@ -124,21 +128,21 @@ const CreateCodeDialog = ({
const getButtonProps = () => {
if (status === 'idle' || status === 'error') {
return {
children: 'Generate code',
children: t('Generate code'),
onClick: () => onSubmit(),
};
}
if (status === 'loading') {
return {
children: 'Confirm in wallet...',
children: t('Confirm in wallet...'),
disabled: true,
};
}
if (status === 'success') {
return {
children: 'Close',
children: t('Close'),
intent: Intent.Success,
onClick: () => {
refetch();
@ -151,12 +155,12 @@ const CreateCodeDialog = ({
if (!pubKey || currentStakeAvailable == null || requiredStake == null) {
return (
<div className="flex flex-col gap-4">
<p>You must be connected to the Vega wallet.</p>
<p>{t('You must be connected to the Vega wallet.')}</p>
<TradingButton
intent={Intent.Primary}
onClick={() => setDialogOpen(false)}
>
Close
{t('Close')}
</TradingButton>
</div>
);
@ -166,16 +170,18 @@ const CreateCodeDialog = ({
return (
<div className="flex flex-col gap-4">
<p>
You need at least{' '}
{addDecimalsFormatNumber(requiredStake.toString(), 18)} VEGA staked to
generate a referral code and participate in the referral program.
{t('You need at least')}{' '}
{addDecimalsFormatNumber(requiredStake.toString(), 18)}{' '}
{t(
'VEGA staked to generate a referral code and participate in the referral program.'
)}
</p>
<TradingAnchorButton
href={createLink(TokenStaticLinks.ASSOCIATE)}
intent={Intent.Primary}
target="_blank"
>
Stake some $VEGA now
{t('Stake some $VEGA now')}
</TradingAnchorButton>
</div>
);
@ -185,8 +191,9 @@ const CreateCodeDialog = ({
<div className="flex flex-col gap-4">
{(status === 'idle' || status === 'loading' || status === 'error') && (
<p>
Generate a referral code to share with your friends and start earning
commission.
{t(
'Generate a referral code to share with your friends and start earning commission.'
)}
</p>
)}
{status === 'success' && code && (
@ -201,7 +208,7 @@ const CreateCodeDialog = ({
className="text-sm no-underline"
icon={<VegaIcon name={VegaIconNames.COPY} />}
>
<span>Copy</span>
<span>{t('Copy')}</span>
</TradingButton>
</CopyWithTooltip>
</div>
@ -214,10 +221,10 @@ const CreateCodeDialog = ({
{err && <InputError>{err}</InputError>}
<div className="flex justify-center pt-5 mt-2 text-sm border-t gap-4 text-default border-default">
<ExternalLink href={ABOUT_REFERRAL_DOCS_LINK}>
About the referral program
{t('About the referral program')}
</ExternalLink>
<ExternalLink href={DISCLAIMER_REFERRAL_DOCS_LINK}>
Disclaimer
{t('Disclaimer')}
</ExternalLink>
</div>
</div>

View File

@ -3,6 +3,7 @@ import { RainbowButton } from './buttons';
import { AnimatedDudeWithWire } from './graphics/dude';
import { LayoutWithSky } from './layout';
import { Routes } from '../../lib/links';
import { t } from '@vegaprotocol/i18n';
export const ErrorBoundary = () => {
const error = useRouteError();
@ -39,7 +40,7 @@ export const ErrorBoundary = () => {
variant="border"
className="text-xs"
>
Go back and try again
{t('Go back and try again')}
</RainbowButton>
</p>
</LayoutWithSky>
@ -60,7 +61,7 @@ export const NotFound = () => {
<h1 className="text-6xl font-alpha calt mb-10">{'Not found'}</h1>
<p className="text-lg mb-10">
{"The page you're looking for doesn't exists."}
{t("The page you're looking for doesn't exists.")}
</p>
<p className="text-lg mb-10">
@ -69,7 +70,7 @@ export const NotFound = () => {
variant="border"
className="text-xs"
>
Go back and try again
{t('Go back and try again')}
</RainbowButton>
</p>
</div>

View File

@ -1,3 +1,4 @@
import { t } from '@vegaprotocol/i18n';
import { Table } from './table';
export const HowItWorksTable = () => (
@ -13,7 +14,9 @@ export const HowItWorksTable = () => (
1
</span>
),
step: 'Referrers generate a code assigned to their key via an on chain transaction',
step: t(
'Referrers generate a code assigned to their key via an on chain transaction'
),
},
{
number: (
@ -21,7 +24,9 @@ export const HowItWorksTable = () => (
2
</span>
),
step: 'Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction',
step: t(
'Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction'
),
},
{
number: (
@ -29,7 +34,9 @@ export const HowItWorksTable = () => (
3
</span>
),
step: 'Discounts are applied automatically during trading based on the key(s) used',
step: t(
'Discounts are applied automatically during trading based on the key(s) used'
),
},
{
number: (
@ -37,7 +44,9 @@ export const HowItWorksTable = () => (
4
</span>
),
step: 'Referrers earn commission based on a percentage of the taker fees their referees pay',
step: t(
'Referrers earn commission based on a percentage of the taker fees their referees pay'
),
},
{
number: (
@ -45,7 +54,9 @@ export const HowItWorksTable = () => (
5
</span>
),
step: 'The commission is taken from the infrastructure fee, maker fee, and liquidity provider fee, not from the referee',
step: t(
'The commission is taken from the infrastructure fee, maker fee, and liquidity provider fee, not from the referee'
),
},
]}
></Table>

View File

@ -1,5 +1,6 @@
import classNames from 'classnames';
import { AnimatedDudeWithWire } from './graphics/dude';
import { t } from '@vegaprotocol/i18n';
export const LandingBanner = () => {
return (
@ -13,16 +14,17 @@ export const LandingBanner = () => {
</div>
<div className="pt-32 sm:w-[50%]">
<h1 className="text-6xl font-alpha calt mb-10">
Earn commission & stake rewards
{t('Earn commission & stake rewards')}
</h1>
<p className="text-lg mb-10">
Invite friends and earn commission in the form of Vega rewards from
the trading fees they pay. Stake those rewards to earn multipliers
on future rewards.
{t(
'Invite friends and earn commission in the form of Vega rewards from the trading fees they pay. Stake those rewards to earn multipliers on future rewards.'
)}
</p>
<p className="text-lg">
Any friends that join using the code will receive discounts off
trading fees.
{t(
'Any friends that join using the code will receive discounts off trading fees.'
)}
</p>
</div>
</div>

View File

@ -26,6 +26,7 @@ import sortBy from 'lodash/sortBy';
import { useLayoutEffect, useRef, useState } from 'react';
import { useCurrentEpochInfoQuery } from './hooks/__generated__/Epoch';
import BigNumber from 'bignumber.js';
import { t } from '@vegaprotocol/i18n';
export const ReferralStatistics = () => {
const { pubKey } = useVegaWallet();
@ -116,34 +117,34 @@ export const Statistics = ({
: 0;
const baseCommissionTile = (
<StatTile title="Base commission rate">
<StatTile title={t('Base commission rate')}>
{baseCommissionValue * 100}%
</StatTile>
);
const stakingMultiplierTile = (
<StatTile
title="Staking multiplier"
title={t('Staking multiplier')}
description={`(${addDecimalsFormatNumber(
stakeAvailable?.toString() || 0,
18
)} $VEGA staked)`}
>
{multiplier || 'None'}
{multiplier || t('None')}
</StatTile>
);
const finalCommissionTile = (
<StatTile title="Final commission rate">
<StatTile title={t('Final commission rate')}>
{finalCommissionValue * 100}%
</StatTile>
);
const numberOfTradersValue = data.referees.length;
const numberOfTradersTile = (
<StatTile title="Number of traders">{numberOfTradersValue}</StatTile>
<StatTile title={t('Number of traders')}>{numberOfTradersValue}</StatTile>
);
const codeTile = <CodeTile code={data?.code} />;
const createdAtTile = (
<StatTile title="Created at">
<StatTile title={t('Created at')}>
<span className="text-3xl">
{getDateFormat().format(new Date(data.createdAt))}
</span>
@ -154,7 +155,10 @@ export const Statistics = ({
.map((r) => new BigNumber(r.totalRefereeGeneratedRewards))
.reduce((all, r) => all.plus(r), new BigNumber(0));
const totalCommissionTile = (
<StatTile title="Total commission (last 30 days)" description="(Quantum)">
<StatTile
title={t('Total commission (last 30 days)')}
description={t('(qUSD)')}
>
{getNumberFormat(0).format(Number(totalCommissionValue))}
</StatTile>
);
@ -184,29 +188,31 @@ export const Statistics = ({
});
const currentBenefitTierTile = (
<StatTile title="Current tier">
<StatTile title={t('Current tier')}>
{currentBenefitTierValue?.tier || '-'}
</StatTile>
);
const discountFactorTile = (
<StatTile title="Discount">{discountFactorValue * 100}%</StatTile>
<StatTile title={t('Discount')}>{discountFactorValue * 100}%</StatTile>
);
const runningVolumeTile = (
<StatTile title="Combined volume">
<StatTile title={t('Combined volume')}>
{compactNumFormat.format(runningVolumeValue)}
</StatTile>
);
const epochsTile = <StatTile title="Epochs in set">{epochsValue}</StatTile>;
const epochsTile = (
<StatTile title={t('Epochs in set')}>{epochsValue}</StatTile>
);
const nextTierVolumeTile = (
<StatTile title="Volume to next tier">
<StatTile title={t('Volume to next tier')}>
{nextBenefitTierVolumeValue <= 0
? '-'
? '0'
: compactNumFormat.format(nextBenefitTierVolumeValue)}
</StatTile>
);
const nextTierEpochsTile = (
<StatTile title="Epochs to next tier">
{nextBenefitTierEpochsValue <= 0 ? '-' : nextBenefitTierEpochsValue}
<StatTile title={t('Epochs to next tier')}>
{nextBenefitTierEpochsValue <= 0 ? '0' : nextBenefitTierEpochsValue}
</StatTile>
);
@ -249,7 +255,7 @@ export const Statistics = ({
{/* Referees (only for referrer view) */}
{as === 'referrer' && data.referees.length > 0 && (
<div className="mt-20 mb-20">
<h2 className="text-2xl mb-5">Referees</h2>
<h2 className="text-2xl mb-5">{t('Referees')}</h2>
<div
className={classNames(
collapsed && [
@ -273,12 +279,12 @@ export const Statistics = ({
<Table
ref={tableRef}
columns={[
{ name: 'party', displayName: 'Trader' },
{ name: 'joined', displayName: 'Date Joined' },
{ name: 'volume', displayName: 'Volume (last 30 days)' },
{ name: 'party', displayName: t('Trader') },
{ name: 'joined', displayName: t('Date Joined') },
{ name: 'volume', displayName: t('Volume (last 30 days)') },
{
name: 'commission',
displayName: 'Commission earned (last 30 days)',
displayName: t('Commission earned (last 30 days)'),
},
]}
data={sortBy(

View File

@ -22,9 +22,9 @@ import { t } from '@vegaprotocol/i18n';
const Nav = () => (
<div className="flex justify-center border-b border-vega-cdark-500">
<TabLink end to={Routes.REFERRALS}>
I want a code
{t('I want a code')}
</TabLink>
<TabLink to={Routes.REFERRALS_APPLY_CODE}>I have a code</TabLink>
<TabLink to={Routes.REFERRALS_APPLY_CODE}>{t('I have a code')}</TabLink>
</div>
);
@ -77,7 +77,7 @@ export const Referrals = () => {
</div>
) : error ? (
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center">
<p>Something went wrong</p>
<p>{t('Something went wrong')}</p>
<span className="text-xs">{error.message}</span>
</div>
) : (
@ -88,7 +88,7 @@ export const Referrals = () => {
<TiersContainer />
<div className="mt-10 mb-5 text-center">
<h2 className="text-2xl">How it works</h2>
<h2 className="text-2xl">{t('How it works')}</h2>
</div>
<div className="md:w-[60%] mx-auto">
<HowItWorksTable />
@ -98,7 +98,8 @@ export const Referrals = () => {
href={REFERRAL_DOCS_LINK}
target="_blank"
>
Read the terms <VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
{t('Read the terms')}{' '}
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
</TradingAnchorButton>
</div>
</div>

View File

@ -7,6 +7,7 @@ import { Tag } from './tag';
import type { ComponentProps, ReactNode } from 'react';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { DApp, TOKEN_PROPOSALS, useLinks } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
const Loading = ({ variant }: { variant: 'large' | 'inline' }) => (
<div
@ -61,7 +62,7 @@ const StakingTier = ({
<Tag color={color[tier]}>Multiplier {referralRewardMultiplier}x</Tag>
<h3 className="mt-1 mb-1 text-base">{label}</h3>
<p className="text-sm text-vega-clight-100 dark:text-vega-cdark-100">
Stake a minimum of {minimumStakedTokens} $VEGA tokens
{t('Stake a minimum of')} {minimumStakedTokens} {t('$VEGA tokens')}
</p>
</div>
</div>
@ -81,9 +82,12 @@ export const TiersContainer = () => {
if ((!loading && !details) || error) {
return (
<div className="text-base px-5 py-10 text-center">
We&apos;re sorry but we don&apos;t have an active referral programme
currently running. You can propose a new programme{' '}
<ExternalLink href={governanceLink(TOKEN_PROPOSALS)}>here</ExternalLink>
{t(
"We're sorry but we don't have an active referral programme currently running. You can propose a new programme"
)}{' '}
<ExternalLink href={governanceLink(TOKEN_PROPOSALS)}>
{t('here')}
</ExternalLink>
.
</div>
);
@ -93,10 +97,10 @@ export const TiersContainer = () => {
<>
{/* Benefit tiers */}
<div className="flex flex-col items-baseline justify-between mt-10 mb-5">
<h2 className="text-2xl">Referral tiers</h2>
<h2 className="text-2xl">{t('Referral tiers')}</h2>
{ends && (
<span className="text-sm text-vega-clight-200 dark:text-vega-cdark-200">
Program ends: {ends}
{t('Program ends:')} {ends}
</span>
)}
</div>
@ -119,7 +123,7 @@ export const TiersContainer = () => {
{/* Staking tiers */}
<div className="flex flex-row items-baseline justify-between mb-5">
<h2 className="text-2xl">Staking multipliers</h2>
<h2 className="text-2xl">{t('Staking multipliers')}</h2>
</div>
<div className="mb-20 flex flex-col justify-items-stretch lg:flex-row gap-5">
{loading || !stakingTiers || stakingTiers.length === 0 ? (
@ -170,15 +174,15 @@ const TiersTable = ({
return (
<Table
columns={[
{ name: 'tierElement', displayName: 'Tier' },
{ name: 'tierElement', displayName: t('Tier') },
{
name: 'commission',
displayName: 'Referrer commission',
tooltip: 'A percentage of commission earned by the referrer',
displayName: t('Referrer commission'),
tooltip: t('A percentage of commission earned by the referrer'),
},
{ name: 'discount', displayName: 'Referrer trading discount' },
{ name: 'volume', displayName: 'Min. trading volume' },
{ name: 'epochs', displayName: 'Min. epochs' },
{ name: 'discount', displayName: t('Referrer trading discount') },
{ name: 'volume', displayName: t('Min. trading volume') },
{ name: 'epochs', displayName: t('Min. epochs') },
]}
data={data.map((d) => ({
...d,