vega-frontend-monorepo/apps/trading/client-pages/referrals/create-code-form.tsx

342 lines
9.6 KiB
TypeScript
Raw Normal View History

import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { RainbowButton } from '../../components/rainbow-button';
import { useState } from 'react';
import {
CopyWithTooltip,
Dialog,
ExternalLink,
InputError,
Intent,
Tooltip,
TradingAnchorButton,
TradingButton,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { DApp, TokenStaticLinks, useLinks } from '@vegaprotocol/environment';
import { ABOUT_REFERRAL_DOCS_LINK } from './constants';
import { useIsInReferralSet, useReferral } from './hooks/use-referral';
import { useT } from '../../lib/use-t';
import { Link, Navigate, useNavigate } from 'react-router-dom';
import { Links, Routes } from '../../lib/links';
import { useReferralProgram } from './hooks/use-referral-program';
import { useReferralSetTransaction } from '../../lib/hooks/use-referral-set-transaction';
import { Trans } from 'react-i18next';
export const CreateCodeContainer = () => {
const t = useT();
const { pubKey, isReadOnly } = useVegaWallet();
const isInReferralSet = useIsInReferralSet(pubKey);
const openWalletDialog = useVegaWalletDialogStore(
(store) => store.openVegaWalletDialog
);
// Navigate to the index page when already in the referral set.
if (isInReferralSet) {
return <Navigate to={Routes.REFERRALS} />;
}
return (
<div
data-testid="referral-create-code-form"
className="md: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">
{t('Create a referral code')}
</h3>
<p className="mb-4 text-center text-base">
{t(
'Generate a referral code to share with your friends and access the commission benefits of the current program.'
)}
</p>
<div className="w-full flex flex-col gap-4 items-stretch">
{pubKey ? (
<CreateCodeForm />
) : (
<RainbowButton
variant="border"
disabled={isReadOnly}
onClick={openWalletDialog}
>
{t('Connect wallet')}
</RainbowButton>
)}
</div>
</div>
);
};
export const CreateCodeForm = () => {
const t = useT();
const navigate = useNavigate();
const [dialogOpen, setDialogOpen] = useState(false);
const { isReadOnly } = useVegaWallet();
return (
<>
<Tooltip
description={t(
'Create a simple referral code to enjoy the referrer commission outlined in the current referral program'
)}
>
<span>
<RainbowButton
variant="border"
disabled={isReadOnly}
onClick={() => setDialogOpen(true)}
className="w-full"
>
{t('Create a referral code')}
</RainbowButton>
</span>
</Tooltip>
<Tooltip
description={
<Trans
i18nKey={
'Make your referral code a Team to compete in Competitions with your friends, appear in leaderboards on the <0>Competitions Homepage</0>, and earn rewards'
}
components={[
<Link
key="homepage-link"
to={Links.COMPETITIONS()}
className="underline"
>
Compeitionts Homepage
</Link>,
]}
/>
}
>
<span>
<RainbowButton
role="link"
variant="border"
disabled={isReadOnly}
onClick={() => navigate(Links.COMPETITIONS_CREATE_TEAM())}
className="w-full"
>
{t('Create a team')}
</RainbowButton>
</span>
</Tooltip>
<p className="text-xs">
<Link className="underline" to={Links.COMPETITIONS()}>
{t('Go to competitions')}
</Link>
</p>
<Dialog
title={t('Create a referral code')}
open={dialogOpen}
onChange={() => setDialogOpen(false)}
size="small"
>
<CreateCodeDialog setDialogOpen={setDialogOpen} />
</Dialog>
</>
);
};
const CreateCodeDialog = ({
setDialogOpen,
}: {
setDialogOpen: (open: boolean) => void;
}) => {
const t = useT();
const createLink = useLinks(DApp.Governance);
const { pubKey } = useVegaWallet();
const { refetch } = useReferral({ pubKey, role: 'referrer' });
const {
err,
code,
status,
stakeAvailable: currentStakeAvailable,
requiredStake,
onSubmit,
} = useReferralSetTransaction();
const { details: programDetails } = useReferralProgram();
const getButtonProps = () => {
if (status === 'idle') {
return {
children: t('Generate code'),
onClick: () => onSubmit({ createReferralSet: { isTeam: false } }),
};
}
if (status === 'requested') {
return {
children: t('Confirm in wallet...'),
disabled: true,
};
}
if (status === 'pending') {
return {
children: t('Waiting for transaction...'),
disabled: true,
};
}
if (status === 'confirmed') {
return {
children: t('Close'),
intent: Intent.Success,
onClick: () => {
refetch();
setDialogOpen(false);
},
};
}
};
if (!pubKey || currentStakeAvailable == null || requiredStake == null) {
return (
<div className="flex flex-col gap-4">
<p>{t('You must be connected to the Vega wallet.')}</p>
<TradingButton
intent={Intent.Primary}
onClick={() => setDialogOpen(false)}
>
{t('Close')}
</TradingButton>
</div>
);
}
if (currentStakeAvailable < requiredStake) {
return (
<div className="flex flex-col gap-4">
<p>
{t(
'You need at least {{requiredStake}} VEGA staked to generate a referral code and participate in the referral program.',
{
requiredStake: addDecimalsFormatNumber(
requiredStake.toString(),
18
),
}
)}
</p>
<TradingAnchorButton
href={createLink(TokenStaticLinks.ASSOCIATE)}
intent={Intent.Primary}
target="_blank"
>
{t('Stake some $VEGA now')}
</TradingAnchorButton>
</div>
);
}
if (!programDetails) {
return (
<div className="flex flex-col gap-4">
{(status === 'idle' ||
status === 'requested' ||
status === 'pending' ||
err) && (
<>
{
<p>
{t(
'There is currently no referral program active, are you sure you want to create a code?'
)}
</p>
}
</>
)}
{status === 'confirmed' && code && (
<div className="flex items-center gap-2">
<div className="flex-1 min-w-0 p-2 text-sm rounded bg-vega-clight-700 dark:bg-vega-cdark-700">
<p className="overflow-hidden whitespace-nowrap text-ellipsis">
{code}
</p>
</div>
<CopyWithTooltip text={code}>
<TradingButton
className="text-sm no-underline"
icon={<VegaIcon name={VegaIconNames.COPY} />}
>
<span>{t('Copy')}</span>
</TradingButton>
</CopyWithTooltip>
</div>
)}
<TradingButton
fill={true}
intent={Intent.Primary}
onClick={() => onSubmit({ createReferralSet: { isTeam: false } })}
{...getButtonProps()}
>
{t('Yes')}
</TradingButton>
{status === 'idle' && (
<TradingButton
fill={true}
intent={Intent.Primary}
onClick={() => {
refetch();
setDialogOpen(false);
}}
>
{t('No')}
</TradingButton>
)}
{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}>
{t('About the referral program')}
</ExternalLink>
</div>
</div>
);
}
return (
<div className="flex flex-col gap-4">
{(status === 'idle' ||
status === 'requested' ||
status === 'pending' ||
err) && (
<p>
{t(
'Generate a referral code to share with your friends and access the commission benefits of the current program.'
)}
</p>
)}
{status === 'confirmed' && code && (
<div className="flex items-center gap-2">
<div className="flex-1 min-w-0 p-2 text-sm rounded bg-vega-clight-700 dark:bg-vega-cdark-700">
<p className="overflow-hidden whitespace-nowrap text-ellipsis">
{code}
</p>
</div>
<CopyWithTooltip text={code}>
<TradingButton
className="text-sm no-underline"
icon={<VegaIcon name={VegaIconNames.COPY} />}
>
<span>{t('Copy')}</span>
</TradingButton>
</CopyWithTooltip>
</div>
)}
<TradingButton
fill={true}
intent={Intent.Primary}
{...getButtonProps()}
/>
{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}>
{t('About the referral program')}
</ExternalLink>
</div>
</div>
);
};