Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db6a1f077b |
@@ -26,7 +26,6 @@ NX_ICEBERG_ORDERS=true
|
||||
# NX_PRODUCT_PERPETUALS
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_REFERRALS=true
|
||||
NX_TEAM_COMPETITION=true
|
||||
|
||||
NX_CHARTING_LIBRARY_PATH=https://assets.vega.community/trading-view-bundle/v0.0.1/
|
||||
NX_CHARTING_LIBRARY_HASH=PDjWaqPFndDp+LCvqbKvntWriaqNzNpZ5i9R/BULzCg=
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import {
|
||||
Intent,
|
||||
TextArea,
|
||||
TradingAnchorButton,
|
||||
TradingButton,
|
||||
TradingCheckbox,
|
||||
TradingFormGroup,
|
||||
TradingInput,
|
||||
TradingInputError,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
useVegaWallet,
|
||||
type CreateReferralSet,
|
||||
type Status,
|
||||
useVegaWalletDialogStore,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
isValidVegaPublicKey,
|
||||
URL_REGEX,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { useReferralSetTransaction } from '../../lib/hooks/use-referral-set-transaction';
|
||||
import { useCreateReferralSet } from '../../lib/hooks/use-create-referral-set';
|
||||
import { DApp, TokenStaticLinks, useLinks } from '@vegaprotocol/environment';
|
||||
import { RainbowButton } from '../../components/rainbow-button';
|
||||
import { usePageTitle } from '../../lib/hooks/use-page-title';
|
||||
@@ -11,7 +30,14 @@ import { ErrorBoundary } from '../../components/error-boundary';
|
||||
import { Box } from '../../components/competitions/box';
|
||||
import { LayoutWithGradient } from '../../components/layouts-inner';
|
||||
import { Links } from '../../lib/links';
|
||||
import { TeamForm, TransactionType } from './team-form';
|
||||
|
||||
interface FormFields {
|
||||
name: string;
|
||||
url: string;
|
||||
avatarUrl: string;
|
||||
private: boolean;
|
||||
allowList: string;
|
||||
}
|
||||
|
||||
export const CompetitionsCreateTeam = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
@@ -59,7 +85,7 @@ const CreateTeamFormContainer = ({ isSolo }: { isSolo: boolean }) => {
|
||||
const createLink = useLinks(DApp.Governance);
|
||||
|
||||
const { err, status, code, isEligible, requiredStake, onSubmit } =
|
||||
useReferralSetTransaction({
|
||||
useCreateReferralSet({
|
||||
onSuccess: (code) => {
|
||||
// For some reason team creation takes a long time, too long even to make
|
||||
// polling viable, so its not feasible to navigate to the team page
|
||||
@@ -120,8 +146,7 @@ const CreateTeamFormContainer = ({ isSolo }: { isSolo: boolean }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<TeamForm
|
||||
type={TransactionType.CreateReferralSet}
|
||||
<CreateTeamForm
|
||||
onSubmit={onSubmit}
|
||||
status={status}
|
||||
err={err}
|
||||
@@ -129,3 +154,180 @@ const CreateTeamFormContainer = ({ isSolo }: { isSolo: boolean }) => {
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const CreateTeamForm = ({
|
||||
status,
|
||||
err,
|
||||
isSolo,
|
||||
onSubmit,
|
||||
}: {
|
||||
status: ReturnType<typeof useCreateReferralSet>['status'];
|
||||
err: ReturnType<typeof useCreateReferralSet>['err'];
|
||||
isSolo: boolean;
|
||||
onSubmit: (tx: CreateReferralSet) => void;
|
||||
}) => {
|
||||
const t = useT();
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
control,
|
||||
watch,
|
||||
formState: { errors },
|
||||
} = useForm<FormFields>({
|
||||
defaultValues: {
|
||||
private: isSolo,
|
||||
},
|
||||
});
|
||||
|
||||
const isPrivate = watch('private');
|
||||
|
||||
const createTeam = (fields: FormFields) => {
|
||||
onSubmit({
|
||||
createReferralSet: {
|
||||
isTeam: true,
|
||||
team: {
|
||||
name: fields.name,
|
||||
teamUrl: fields.url,
|
||||
avatarUrl: fields.avatarUrl,
|
||||
closed: fields.private,
|
||||
allowList: fields.private ? parseAllowListText(fields.allowList) : [],
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(createTeam)}>
|
||||
<TradingFormGroup label={t('Team name')} labelFor="name">
|
||||
<TradingInput {...register('name', { required: t('Required') })} />
|
||||
{errors.name?.message && (
|
||||
<TradingInputError forInput="name">
|
||||
{errors.name.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup
|
||||
label={t('URL')}
|
||||
labelFor="url"
|
||||
labelDescription={t(
|
||||
'Provide a link so users can learn more about your team'
|
||||
)}
|
||||
>
|
||||
<TradingInput
|
||||
{...register('url', {
|
||||
pattern: { value: URL_REGEX, message: t('Invalid URL') },
|
||||
})}
|
||||
/>
|
||||
{errors.url?.message && (
|
||||
<TradingInputError forInput="url">
|
||||
{errors.url.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup
|
||||
label={t('Avatar URL')}
|
||||
labelFor="avatarUrl"
|
||||
labelDescription={t('Provide a URL to a hosted image')}
|
||||
>
|
||||
<TradingInput
|
||||
{...register('avatarUrl', {
|
||||
pattern: {
|
||||
value: URL_REGEX,
|
||||
message: t('Invalid image URL'),
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{errors.avatarUrl?.message && (
|
||||
<TradingInputError forInput="avatarUrl">
|
||||
{errors.avatarUrl.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup
|
||||
label={t('Make team private')}
|
||||
labelFor="private"
|
||||
hideLabel={true}
|
||||
>
|
||||
<Controller
|
||||
name="private"
|
||||
control={control}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<TradingCheckbox
|
||||
label={t('Make team private')}
|
||||
checked={field.value}
|
||||
onCheckedChange={(value) => {
|
||||
field.onChange(value);
|
||||
}}
|
||||
disabled={isSolo}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</TradingFormGroup>
|
||||
{isPrivate && (
|
||||
<TradingFormGroup
|
||||
label={t('Public key allow list')}
|
||||
labelFor="allowList"
|
||||
labelDescription={t(
|
||||
'Use a comma separated list to allow only specific public keys to join the team'
|
||||
)}
|
||||
>
|
||||
<TextArea
|
||||
{...register('allowList', {
|
||||
required: t('Required'),
|
||||
disabled: isSolo,
|
||||
validate: {
|
||||
allowList: (value) => {
|
||||
const publicKeys = parseAllowListText(value);
|
||||
if (publicKeys.every((pk) => isValidVegaPublicKey(pk))) {
|
||||
return true;
|
||||
}
|
||||
return t('Invalid public key found in allow list');
|
||||
},
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{errors.allowList?.message && (
|
||||
<TradingInputError forInput="avatarUrl">
|
||||
{errors.allowList.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
)}
|
||||
{err && (
|
||||
<p className="text-danger text-xs mb-4 first-letter:capitalize">
|
||||
{err}
|
||||
</p>
|
||||
)}
|
||||
<SubmitButton status={status} />
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
const SubmitButton = ({ status }: { status: Status }) => {
|
||||
const t = useT();
|
||||
const disabled = status === 'pending' || status === 'requested';
|
||||
|
||||
let text = t('Create');
|
||||
|
||||
if (status === 'requested') {
|
||||
text = t('Confirm in wallet...');
|
||||
} else if (status === 'pending') {
|
||||
text = t('Confirming transaction...');
|
||||
}
|
||||
|
||||
return (
|
||||
<TradingButton type="submit" intent={Intent.Info} disabled={disabled}>
|
||||
{text}
|
||||
</TradingButton>
|
||||
);
|
||||
};
|
||||
|
||||
const parseAllowListText = (str: string) => {
|
||||
return str
|
||||
.split(',')
|
||||
.map((v) => v.trim())
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ErrorBoundary } from '@sentry/react';
|
||||
import { CompetitionsHeader } from '../../components/competitions/competitions-header';
|
||||
import { Intent, Loader, TradingButton } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import { useGames } from '../../lib/hooks/use-games';
|
||||
import { useGames } from './hooks/use-games';
|
||||
import { useCurrentEpochInfoQuery } from '../referrals/hooks/__generated__/Epoch';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '../../components/competitions/competitions-cta';
|
||||
import { GamesContainer } from '../../components/competitions/games-container';
|
||||
import { CompetitionsLeaderboard } from '../../components/competitions/competitions-leaderboard';
|
||||
import { useTeams } from '../../lib/hooks/use-teams';
|
||||
import { useTeams } from './hooks/use-teams';
|
||||
import take from 'lodash/take';
|
||||
import { usePageTitle } from '../../lib/hooks/use-page-title';
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import { ErrorBoundary } from '../../components/error-boundary';
|
||||
import { LayoutWithGradient } from '../../components/layouts-inner';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { JoinTeam } from './join-team';
|
||||
import { UpdateTeamButton } from './update-team-button';
|
||||
|
||||
export const CompetitionsTeam = () => {
|
||||
const t = useT();
|
||||
@@ -94,18 +93,30 @@ const TeamPage = ({
|
||||
<header className="flex gap-3 lg:gap-4 pt-5 lg:pt-10">
|
||||
<TeamAvatar teamId={team.teamId} imgUrl={team.avatarUrl} />
|
||||
<div className="flex flex-col items-start gap-1 lg:gap-3">
|
||||
<h1 className="calt text-2xl lg:text-3xl xl:text-5xl">{team.name}</h1>
|
||||
<h1
|
||||
className="calt text-2xl lg:text-3xl xl:text-5xl"
|
||||
data-testid="team-name"
|
||||
>
|
||||
{team.name}
|
||||
</h1>
|
||||
<JoinTeam team={team} partyTeam={partyTeam} refetch={refetch} />
|
||||
<UpdateTeamButton team={team} />
|
||||
</div>
|
||||
</header>
|
||||
<TeamStats stats={stats} members={members} games={games} />
|
||||
<section>
|
||||
<div className="flex gap-4 lg:gap-8 mb-4 border-b border-default">
|
||||
<ToggleButton active={showGames} onClick={() => setShowGames(true)}>
|
||||
<ToggleButton
|
||||
active={showGames}
|
||||
onClick={() => setShowGames(true)}
|
||||
data-testid="games-toggle"
|
||||
>
|
||||
{t('Games ({{count}})', { count: games ? games.length : 0 })}
|
||||
</ToggleButton>
|
||||
<ToggleButton active={!showGames} onClick={() => setShowGames(false)}>
|
||||
<ToggleButton
|
||||
active={!showGames}
|
||||
onClick={() => setShowGames(false)}
|
||||
data-testid="members-toggle"
|
||||
>
|
||||
{t('Members ({{count}})', {
|
||||
count: members ? members.length : 0,
|
||||
})}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ErrorBoundary } from '@sentry/react';
|
||||
import { CompetitionsHeader } from '../../components/competitions/competitions-header';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { useTeams } from '../../lib/hooks/use-teams';
|
||||
import { useTeams } from './hooks/use-teams';
|
||||
import { CompetitionsLeaderboard } from '../../components/competitions/competitions-leaderboard';
|
||||
import {
|
||||
Input,
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
import { ErrorBoundary } from '../../components/error-boundary';
|
||||
import { usePageTitle } from '../../lib/hooks/use-page-title';
|
||||
import { Box } from '../../components/competitions/box';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { RainbowButton } from '../../components/rainbow-button';
|
||||
import { Link, Navigate, useParams } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
import { useReferralSetTransaction } from '../../lib/hooks/use-referral-set-transaction';
|
||||
import { type FormFields, TeamForm, TransactionType } from './team-form';
|
||||
import { useTeam } from '../../lib/hooks/use-team';
|
||||
import { LayoutWithGradient } from '../../components/layouts-inner';
|
||||
|
||||
export const CompetitionsUpdateTeam = () => {
|
||||
const t = useT();
|
||||
usePageTitle([t('Competitions'), t('Update a team')]);
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const openWalletDialog = useVegaWalletDialogStore(
|
||||
(store) => store.openVegaWalletDialog
|
||||
);
|
||||
const { teamId } = useParams<{ teamId: string }>();
|
||||
if (!teamId) {
|
||||
return <Navigate to={Links.COMPETITIONS()} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<ErrorBoundary feature="update-team">
|
||||
<LayoutWithGradient>
|
||||
<div className="mx-auto md:w-2/3 max-w-xl">
|
||||
<Box className="flex flex-col gap-4">
|
||||
<h1 className="calt text-2xl lg:text-3xl xl:text-5xl">
|
||||
{t('Update a team')}
|
||||
</h1>
|
||||
{pubKey && !isReadOnly ? (
|
||||
<UpdateTeamFormContainer teamId={teamId} pubKey={pubKey} />
|
||||
) : (
|
||||
<>
|
||||
<p>{t('Connect to update the details of your team.')}</p>
|
||||
<RainbowButton variant="border" onClick={openWalletDialog}>
|
||||
{t('Connect wallet')}
|
||||
</RainbowButton>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</div>
|
||||
</LayoutWithGradient>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
const UpdateTeamFormContainer = ({
|
||||
teamId,
|
||||
pubKey,
|
||||
}: {
|
||||
teamId: string;
|
||||
pubKey: string;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const { team, loading, error } = useTeam(teamId, pubKey);
|
||||
|
||||
const { err, status, onSubmit } = useReferralSetTransaction({
|
||||
onSuccess: () => {
|
||||
// NOOP
|
||||
},
|
||||
});
|
||||
|
||||
if (loading) {
|
||||
return <Loader size="small" />;
|
||||
}
|
||||
if (error) {
|
||||
return (
|
||||
<Splash className="gap-1">
|
||||
<span>{t('Something went wrong.')}</span>
|
||||
<Link to={Links.COMPETITIONS_TEAM(teamId)} className="underline">
|
||||
{t("Go back to the team's profile")}
|
||||
</Link>
|
||||
</Splash>
|
||||
);
|
||||
}
|
||||
|
||||
const isMyTeam = team?.referrer === pubKey;
|
||||
if (!isMyTeam) {
|
||||
return <Navigate to={Links.COMPETITIONS_TEAM(teamId)} />;
|
||||
}
|
||||
|
||||
const defaultValues: FormFields = {
|
||||
id: team.teamId,
|
||||
name: team.name,
|
||||
url: team.teamUrl,
|
||||
avatarUrl: team.avatarUrl,
|
||||
private: team.closed,
|
||||
allowList: team.allowList.join(','),
|
||||
};
|
||||
|
||||
return (
|
||||
<TeamForm
|
||||
type={TransactionType.UpdateReferralSet}
|
||||
status={status}
|
||||
err={err}
|
||||
isSolo={team.closed}
|
||||
onSubmit={onSubmit}
|
||||
defaultValues={defaultValues}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import compact from 'lodash/compact';
|
||||
import { useActiveRewardsQuery } from '../../components/rewards-container/__generated__/Rewards';
|
||||
import { isActiveReward } from '../../components/rewards-container/active-rewards';
|
||||
import { useActiveRewardsQuery } from '../../../components/rewards-container/__generated__/Rewards';
|
||||
import { isActiveReward } from '../../../components/rewards-container/active-rewards';
|
||||
import { EntityScope, type TransferNode } from '@vegaprotocol/types';
|
||||
|
||||
const isScopedToTeams = (node: TransferNode) =>
|
||||
@@ -1,254 +0,0 @@
|
||||
import {
|
||||
TradingFormGroup,
|
||||
TradingInput,
|
||||
TradingInputError,
|
||||
TradingCheckbox,
|
||||
TextArea,
|
||||
TradingButton,
|
||||
Intent,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { URL_REGEX, isValidVegaPublicKey } from '@vegaprotocol/utils';
|
||||
|
||||
import { type useReferralSetTransaction } from '../../lib/hooks/use-referral-set-transaction';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import type {
|
||||
CreateReferralSet,
|
||||
UpdateReferralSet,
|
||||
Status,
|
||||
} from '@vegaprotocol/wallet';
|
||||
|
||||
export type FormFields = {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
avatarUrl: string;
|
||||
private: boolean;
|
||||
allowList: string;
|
||||
};
|
||||
|
||||
export enum TransactionType {
|
||||
CreateReferralSet,
|
||||
UpdateReferralSet,
|
||||
}
|
||||
|
||||
const prepareTransaction = (
|
||||
type: TransactionType,
|
||||
fields: FormFields
|
||||
): CreateReferralSet | UpdateReferralSet => {
|
||||
switch (type) {
|
||||
case TransactionType.CreateReferralSet:
|
||||
return {
|
||||
createReferralSet: {
|
||||
isTeam: true,
|
||||
team: {
|
||||
name: fields.name,
|
||||
teamUrl: fields.url,
|
||||
avatarUrl: fields.avatarUrl,
|
||||
closed: fields.private,
|
||||
allowList: fields.private
|
||||
? parseAllowListText(fields.allowList)
|
||||
: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
case TransactionType.UpdateReferralSet:
|
||||
return {
|
||||
updateReferralSet: {
|
||||
id: fields.id,
|
||||
isTeam: true,
|
||||
team: {
|
||||
name: fields.name,
|
||||
teamUrl: fields.url,
|
||||
avatarUrl: fields.avatarUrl,
|
||||
closed: fields.private,
|
||||
allowList: fields.private
|
||||
? parseAllowListText(fields.allowList)
|
||||
: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const TeamForm = ({
|
||||
type,
|
||||
status,
|
||||
err,
|
||||
isSolo,
|
||||
onSubmit,
|
||||
defaultValues,
|
||||
}: {
|
||||
type: TransactionType;
|
||||
status: ReturnType<typeof useReferralSetTransaction>['status'];
|
||||
err: ReturnType<typeof useReferralSetTransaction>['err'];
|
||||
isSolo: boolean;
|
||||
onSubmit: ReturnType<typeof useReferralSetTransaction>['onSubmit'];
|
||||
defaultValues?: FormFields;
|
||||
}) => {
|
||||
const t = useT();
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
control,
|
||||
watch,
|
||||
formState: { errors },
|
||||
} = useForm<FormFields>({
|
||||
defaultValues: {
|
||||
private: isSolo,
|
||||
...defaultValues,
|
||||
},
|
||||
});
|
||||
|
||||
const isPrivate = watch('private');
|
||||
|
||||
const sendTransaction = (fields: FormFields) => {
|
||||
onSubmit(prepareTransaction(type, fields));
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(sendTransaction)}>
|
||||
<input
|
||||
type="hidden"
|
||||
{...register('id', {
|
||||
disabled: true,
|
||||
})}
|
||||
/>
|
||||
<TradingFormGroup label={t('Team name')} labelFor="name">
|
||||
<TradingInput {...register('name', { required: t('Required') })} />
|
||||
{errors.name?.message && (
|
||||
<TradingInputError forInput="name">
|
||||
{errors.name.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup
|
||||
label={t('URL')}
|
||||
labelFor="url"
|
||||
labelDescription={t(
|
||||
'Provide a link so users can learn more about your team'
|
||||
)}
|
||||
>
|
||||
<TradingInput
|
||||
{...register('url', {
|
||||
pattern: { value: URL_REGEX, message: t('Invalid URL') },
|
||||
})}
|
||||
/>
|
||||
{errors.url?.message && (
|
||||
<TradingInputError forInput="url">
|
||||
{errors.url.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup
|
||||
label={t('Avatar URL')}
|
||||
labelFor="avatarUrl"
|
||||
labelDescription={t('Provide a URL to a hosted image')}
|
||||
>
|
||||
<TradingInput
|
||||
{...register('avatarUrl', {
|
||||
pattern: {
|
||||
value: URL_REGEX,
|
||||
message: t('Invalid image URL'),
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{errors.avatarUrl?.message && (
|
||||
<TradingInputError forInput="avatarUrl">
|
||||
{errors.avatarUrl.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
<TradingFormGroup
|
||||
label={t('Make team private')}
|
||||
labelFor="private"
|
||||
hideLabel={true}
|
||||
>
|
||||
<Controller
|
||||
name="private"
|
||||
control={control}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<TradingCheckbox
|
||||
label={t('Make team private')}
|
||||
checked={field.value}
|
||||
onCheckedChange={(value) => {
|
||||
field.onChange(value);
|
||||
}}
|
||||
disabled={isSolo}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</TradingFormGroup>
|
||||
{isPrivate && (
|
||||
<TradingFormGroup
|
||||
label={t('Public key allow list')}
|
||||
labelFor="allowList"
|
||||
labelDescription={t(
|
||||
'Use a comma separated list to allow only specific public keys to join the team'
|
||||
)}
|
||||
>
|
||||
<TextArea
|
||||
{...register('allowList', {
|
||||
required: t('Required'),
|
||||
disabled: isSolo,
|
||||
validate: {
|
||||
allowList: (value) => {
|
||||
const publicKeys = parseAllowListText(value);
|
||||
if (publicKeys.every((pk) => isValidVegaPublicKey(pk))) {
|
||||
return true;
|
||||
}
|
||||
return t('Invalid public key found in allow list');
|
||||
},
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{errors.allowList?.message && (
|
||||
<TradingInputError forInput="avatarUrl">
|
||||
{errors.allowList.message}
|
||||
</TradingInputError>
|
||||
)}
|
||||
</TradingFormGroup>
|
||||
)}
|
||||
{err && <p className="text-danger text-xs mb-4 capitalize">{err}</p>}
|
||||
<SubmitButton type={type} status={status} />
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
const SubmitButton = ({
|
||||
type,
|
||||
status,
|
||||
}: {
|
||||
type?: TransactionType;
|
||||
status: Status;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const disabled = status === 'pending' || status === 'requested';
|
||||
|
||||
let text = t('Create');
|
||||
if (type === TransactionType.UpdateReferralSet) {
|
||||
text = t('Update');
|
||||
}
|
||||
|
||||
if (status === 'requested') {
|
||||
text = t('Confirm in wallet...');
|
||||
} else if (status === 'pending') {
|
||||
text = t('Confirming transaction...');
|
||||
}
|
||||
|
||||
return (
|
||||
<TradingButton type="submit" intent={Intent.Info} disabled={disabled}>
|
||||
{text}
|
||||
</TradingButton>
|
||||
);
|
||||
};
|
||||
|
||||
const parseAllowListText = (str: string) => {
|
||||
return str
|
||||
.split(',')
|
||||
.map((v) => v.trim())
|
||||
.filter(Boolean);
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { type Team } from '../../lib/hooks/use-team';
|
||||
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||
import { Links } from '../../lib/links';
|
||||
|
||||
export const UpdateTeamButton = ({ team }: { team: Team }) => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
|
||||
if (pubKey && !isReadOnly && pubKey === team.referrer) {
|
||||
return (
|
||||
<TradingAnchorButton
|
||||
data-testid="update-team-button"
|
||||
href={Links.COMPETITIONS_UPDATE_TEAM(team.teamId)}
|
||||
intent={Intent.Info}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -21,7 +21,7 @@ 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 { useCreateReferralSet } from '../../lib/hooks/use-create-referral-set';
|
||||
import { Trans } from 'react-i18next';
|
||||
|
||||
export const CreateCodeContainer = () => {
|
||||
@@ -155,7 +155,7 @@ const CreateCodeDialog = ({
|
||||
stakeAvailable: currentStakeAvailable,
|
||||
requiredStake,
|
||||
onSubmit,
|
||||
} = useReferralSetTransaction();
|
||||
} = useCreateReferralSet();
|
||||
|
||||
const { details: programDetails } = useReferralProgram();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { getNumberFormat } from '@vegaprotocol/utils';
|
||||
import { type useTeams } from '../../lib/hooks/use-teams';
|
||||
import { type useTeams } from '../../client-pages/competitions/hooks/use-teams';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { Table } from '../table';
|
||||
import { Rank } from './graphics/rank';
|
||||
|
||||
@@ -30,11 +30,16 @@ export const TeamStats = ({
|
||||
<>
|
||||
<StatSection>
|
||||
<StatList>
|
||||
<Stat value={members ? members.length : 0} label={t('Members')} />
|
||||
<Stat
|
||||
value={members ? members.length : 0}
|
||||
label={t('Members')}
|
||||
valueTestId="members-count-stat"
|
||||
/>
|
||||
<Stat
|
||||
value={stats ? stats.totalGamesPlayed : 0}
|
||||
label={t('Total games')}
|
||||
tooltip={t('Total number of games this team has participated in')}
|
||||
valueTestId="total-games-stat"
|
||||
/>
|
||||
<StatSectionSeparator />
|
||||
<Stat
|
||||
@@ -47,6 +52,7 @@ export const TeamStats = ({
|
||||
: 0
|
||||
}
|
||||
label={t('Total volume')}
|
||||
valueTestId="total-volume-stat"
|
||||
/>
|
||||
<Stat
|
||||
value={
|
||||
@@ -59,6 +65,7 @@ export const TeamStats = ({
|
||||
}
|
||||
label={t('Rewards paid')}
|
||||
tooltip={'Total amount of rewards paid out to this team in qUSD'}
|
||||
valueTestId="rewards-paid-stat"
|
||||
/>
|
||||
</StatList>
|
||||
</StatSection>
|
||||
@@ -159,14 +166,18 @@ const Stat = ({
|
||||
value,
|
||||
label,
|
||||
tooltip,
|
||||
valueTestId,
|
||||
}: {
|
||||
value: ReactNode;
|
||||
label: ReactNode;
|
||||
tooltip?: string;
|
||||
valueTestId?: string;
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
<dd className="text-3xl lg:text-4xl">{value}</dd>
|
||||
<dd className="text-3xl lg:text-4xl" data-testid={valueTestId}>
|
||||
{value}
|
||||
</dd>
|
||||
<dt className="text-sm text-muted">
|
||||
{tooltip ? (
|
||||
<Tooltip description={tooltip} underline={false}>
|
||||
|
||||
@@ -5,6 +5,7 @@ from vega_sim.null_service import VegaServiceNull
|
||||
from conftest import init_vega
|
||||
from actions.utils import next_epoch
|
||||
from fixtures.market import setup_continuous_market
|
||||
from conftest import auth_setup, init_page, init_vega, risk_accepted_setup
|
||||
from wallet_config import PARTY_A, PARTY_B, PARTY_C, PARTY_D, MM_WALLET
|
||||
|
||||
|
||||
@@ -14,6 +15,7 @@ def vega(request):
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def setup_teams_and_games(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
@@ -80,21 +82,17 @@ def setup_teams_and_games(vega: VegaServiceNull):
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id, team_id, team_name
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_teams(vega: VegaServiceNull, page: Page):
|
||||
market_id, asset_id, team_id, team_name = setup_teams_and_games(vega)
|
||||
page.goto(f"/#/competitions/teams/{team_id}")
|
||||
# page.pause()
|
||||
expect(page.get_by_role("heading", level=1)).to_have_text(team_name)
|
||||
expect(page.get_by_text("Members (3)")).to_be_visible()
|
||||
return {
|
||||
"market_id": tDAI_market,
|
||||
"asset_id": tDAI_asset_id,
|
||||
"team_id": team_id,
|
||||
"team_name": team_name,
|
||||
}
|
||||
|
||||
|
||||
def create_team(vega: VegaServiceNull):
|
||||
team_name = "Foobar"
|
||||
|
||||
vega.create_referral_set(
|
||||
key_name=PARTY_A.name,
|
||||
name=team_name,
|
||||
@@ -104,3 +102,67 @@ def create_team(vega: VegaServiceNull):
|
||||
)
|
||||
|
||||
return team_name
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def team_page(vega, browser, request, setup_teams_and_games):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
team_id = setup_teams_and_games["team_id"]
|
||||
page.goto(f"/#/competitions/teams/{team_id}")
|
||||
yield page
|
||||
|
||||
def test_team_page_games_table(team_page: Page):
|
||||
team_page.get_by_test_id("games-toggle").click()
|
||||
expect(team_page.get_by_test_id("games-toggle")).to_have_text("Games (1)")
|
||||
expect(team_page.get_by_test_id("rank-0")).to_have_text("1")
|
||||
expect(team_page.get_by_test_id("epoch-0")).to_have_text("8")
|
||||
expect(team_page.get_by_test_id("type-0")).to_have_text("Price maker fees paid")
|
||||
expect(team_page.get_by_test_id("amount-0")).to_have_text("10,000,000")
|
||||
expect(team_page.get_by_test_id("teams-0")).to_have_text(
|
||||
"2"
|
||||
) # TODO I think this should be 1, confirm with devs
|
||||
|
||||
def test_team_page_members_table(team_page: Page):
|
||||
team_page.get_by_test_id("members-toggle").click()
|
||||
expect(team_page.get_by_test_id("members-toggle")).to_have_text("Members (3)")
|
||||
expect(team_page.get_by_test_id("referee-0")).to_be_visible()
|
||||
expect(team_page.get_by_test_id("joinedAt-0")).to_be_visible()
|
||||
expect(team_page.get_by_test_id("joinedAtEpoch-0")).to_have_text("8")
|
||||
|
||||
def test_team_page_headline(team_page: Page, setup_teams_and_games
|
||||
):
|
||||
team_name = setup_teams_and_games["team_name"]
|
||||
expect(team_page.get_by_test_id("team-name")).to_have_text(team_name)
|
||||
expect(team_page.get_by_test_id("members-count-stat")).to_have_text("3")
|
||||
expect(team_page.get_by_test_id("total-games-stat")).to_have_text(
|
||||
"0"
|
||||
) # TODO this should be 1, confirm with devs
|
||||
expect(team_page.get_by_test_id("total-volume-stat")).to_have_text(
|
||||
"0"
|
||||
) # TODO this should be 10,000,000, confirm with devs
|
||||
expect(team_page.get_by_test_id("rewards-paid-stat")).to_have_text(
|
||||
"0"
|
||||
) # TODO this should be 100, confirm with devs
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def competitions_page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(f"/#/competitions/")
|
||||
yield page
|
||||
|
||||
def test_leaderboard(competitions_page: Page, setup_teams_and_games):
|
||||
team_name = setup_teams_and_games["team_name"]
|
||||
competitions_page.pause()
|
||||
expect(competitions_page.get_by_test_id("rank-0").locator("._text-yellow-300")).to_have_count(1)
|
||||
expect(competitions_page.get_by_test_id("team-0")).to_have_text(team_name)
|
||||
expect(competitions_page.get_by_test_id("earned-0")).to_have_text("-") #TODO I think this should be 100, confirm with dev
|
||||
expect(competitions_page.get_by_test_id("games-0")).to_have_text("-") #TODO I think this should be 1, confirm with dev
|
||||
expect(competitions_page.get_by_test_id("status-0")).to_have_text("Open")
|
||||
expect(competitions_page.get_by_test_id("volume-0")).to_have_text("-") #TODO I think this should be 10,000,000, confirm with dev
|
||||
|
||||
#TODO def test_games(competitions_page: Page):
|
||||
# TODO currently no games appear which i think is a bug
|
||||
@@ -7,7 +7,6 @@ fragment TeamFields on Team {
|
||||
createdAt
|
||||
createdAtEpoch
|
||||
closed
|
||||
allowList
|
||||
}
|
||||
|
||||
fragment TeamStatsFields on TeamStatistics {
|
||||
|
||||
+4
-5
@@ -3,15 +3,15 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type TeamFieldsFragment = { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean, allowList: Array<string> };
|
||||
export type TeamFieldsFragment = { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean };
|
||||
|
||||
export type TeamStatsFieldsFragment = { __typename?: 'TeamStatistics', teamId: string, totalQuantumVolume: string, totalQuantumRewards: string, totalGamesPlayed: number, gamesPlayed: Array<string>, quantumRewards: Array<{ __typename?: 'QuantumRewardsPerEpoch', epoch: number, total_quantum_rewards: string }> };
|
||||
|
||||
export type TeamRefereeFieldsFragment = { __typename?: 'TeamReferee', teamId: string, referee: string, joinedAt: any, joinedAtEpoch: number };
|
||||
|
||||
export type TeamEntityFragment = { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } };
|
||||
export type TeamEntityFragment = { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: string, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } };
|
||||
|
||||
export type TeamGameFieldsFragment = { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } }> };
|
||||
export type TeamGameFieldsFragment = { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: string, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } }> };
|
||||
|
||||
export type TeamQueryVariables = Types.Exact<{
|
||||
teamId: Types.Scalars['ID'];
|
||||
@@ -19,7 +19,7 @@ export type TeamQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type TeamQuery = { __typename?: 'Query', teams?: { __typename?: 'TeamConnection', edges: Array<{ __typename?: 'TeamEdge', node: { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean, allowList: Array<string> } }> } | null, partyTeams?: { __typename?: 'TeamConnection', edges: Array<{ __typename?: 'TeamEdge', node: { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean, allowList: Array<string> } }> } | null, teamsStatistics?: { __typename?: 'TeamsStatisticsConnection', edges: Array<{ __typename?: 'TeamStatisticsEdge', node: { __typename?: 'TeamStatistics', teamId: string, totalQuantumVolume: string, totalQuantumRewards: string, totalGamesPlayed: number, gamesPlayed: Array<string>, quantumRewards: Array<{ __typename?: 'QuantumRewardsPerEpoch', epoch: number, total_quantum_rewards: string }> } }> } | null, teamReferees?: { __typename?: 'TeamRefereeConnection', edges: Array<{ __typename?: 'TeamRefereeEdge', node: { __typename?: 'TeamReferee', teamId: string, referee: string, joinedAt: any, joinedAtEpoch: number } }> } | null, games: { __typename?: 'GamesConnection', edges?: Array<{ __typename?: 'GameEdge', node: { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } }> } } | null> | null } };
|
||||
export type TeamQuery = { __typename?: 'Query', teams?: { __typename?: 'TeamConnection', edges: Array<{ __typename?: 'TeamEdge', node: { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean } }> } | null, partyTeams?: { __typename?: 'TeamConnection', edges: Array<{ __typename?: 'TeamEdge', node: { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean } }> } | null, teamsStatistics?: { __typename?: 'TeamsStatisticsConnection', edges: Array<{ __typename?: 'TeamStatisticsEdge', node: { __typename?: 'TeamStatistics', teamId: string, totalQuantumVolume: string, totalQuantumRewards: string, totalGamesPlayed: number, gamesPlayed: Array<string>, quantumRewards: Array<{ __typename?: 'QuantumRewardsPerEpoch', epoch: number, total_quantum_rewards: string }> } }> } | null, teamReferees?: { __typename?: 'TeamRefereeConnection', edges: Array<{ __typename?: 'TeamRefereeEdge', node: { __typename?: 'TeamReferee', teamId: string, referee: string, joinedAt: any, joinedAtEpoch: number } }> } | null, games: { __typename?: 'GamesConnection', edges?: Array<{ __typename?: 'GameEdge', node: { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: string, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } }> } } | null> | null } };
|
||||
|
||||
export const TeamFieldsFragmentDoc = gql`
|
||||
fragment TeamFields on Team {
|
||||
@@ -31,7 +31,6 @@ export const TeamFieldsFragmentDoc = gql`
|
||||
createdAt
|
||||
createdAtEpoch
|
||||
closed
|
||||
allowList
|
||||
}
|
||||
`;
|
||||
export const TeamStatsFieldsFragmentDoc = gql`
|
||||
|
||||
+3
-4
@@ -1,15 +1,14 @@
|
||||
import {
|
||||
useSimpleTransaction,
|
||||
type Options,
|
||||
type CreateReferralSet,
|
||||
type UpdateReferralSet,
|
||||
type Options,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { useStakeAvailable } from './use-stake-available';
|
||||
|
||||
/**
|
||||
* Manages state for creating a referral set or team
|
||||
*/
|
||||
export const useReferralSetTransaction = (opts?: Options) => {
|
||||
export const useCreateReferralSet = (opts?: Options) => {
|
||||
const { stakeAvailable, requiredStake, isEligible } = useStakeAvailable();
|
||||
|
||||
const { status, result, error, send } = useSimpleTransaction({
|
||||
@@ -17,7 +16,7 @@ export const useReferralSetTransaction = (opts?: Options) => {
|
||||
onError: opts?.onError,
|
||||
});
|
||||
|
||||
const onSubmit = (tx: CreateReferralSet | UpdateReferralSet) => {
|
||||
const onSubmit = (tx: CreateReferralSet) => {
|
||||
send(tx);
|
||||
};
|
||||
|
||||
@@ -18,10 +18,9 @@ export const Routes = {
|
||||
REFERRALS_CREATE_CODE: '/referrals/create-code',
|
||||
COMPETITIONS: '/competitions',
|
||||
COMPETITIONS_TEAMS: '/competitions/teams',
|
||||
COMPETITIONS_TEAM: '/competitions/teams/:teamId',
|
||||
COMPETITIONS_CREATE_TEAM: '/competitions/teams/create',
|
||||
COMPETITIONS_CREATE_TEAM_SOLO: '/competitions/teams/create?solo=true',
|
||||
COMPETITIONS_UPDATE_TEAM: '/competitions/teams/:teamId/update',
|
||||
COMPETITIONS_TEAM: '/competitions/teams/:teamId',
|
||||
FEES: '/fees',
|
||||
REWARDS: '/rewards',
|
||||
} as const;
|
||||
@@ -48,12 +47,10 @@ export const Links: ConsoleLinks = {
|
||||
REFERRALS_CREATE_CODE: () => Routes.REFERRALS_CREATE_CODE,
|
||||
COMPETITIONS: () => Routes.COMPETITIONS,
|
||||
COMPETITIONS_TEAMS: () => Routes.COMPETITIONS_TEAMS,
|
||||
COMPETITIONS_TEAM: (teamId: string) =>
|
||||
Routes.COMPETITIONS_TEAM.replace(':teamId', teamId),
|
||||
COMPETITIONS_CREATE_TEAM: () => Routes.COMPETITIONS_CREATE_TEAM,
|
||||
COMPETITIONS_CREATE_TEAM_SOLO: () => Routes.COMPETITIONS_CREATE_TEAM_SOLO,
|
||||
COMPETITIONS_UPDATE_TEAM: (teamId: string) =>
|
||||
Routes.COMPETITIONS_UPDATE_TEAM.replace(':teamId', teamId),
|
||||
COMPETITIONS_TEAM: (teamId: string) =>
|
||||
Routes.COMPETITIONS_TEAM.replace(':teamId', teamId),
|
||||
FEES: () => Routes.FEES,
|
||||
REWARDS: () => Routes.REWARDS,
|
||||
};
|
||||
|
||||
@@ -32,7 +32,6 @@ import { CompetitionsHome } from '../client-pages/competitions/competitions-home
|
||||
import { CompetitionsTeams } from '../client-pages/competitions/competitions-teams';
|
||||
import { CompetitionsTeam } from '../client-pages/competitions/competitions-team';
|
||||
import { CompetitionsCreateTeam } from '../client-pages/competitions/competitions-create-team';
|
||||
import { CompetitionsUpdateTeam } from '../client-pages/competitions/competitions-update-team';
|
||||
|
||||
// These must remain dynamically imported as pennant cannot be compiled by nextjs due to ESM
|
||||
// Using dynamic imports is a workaround for this until pennant is published as ESM
|
||||
@@ -113,17 +112,13 @@ export const useRouterConfig = (): RouteObject[] => {
|
||||
],
|
||||
},
|
||||
// pages with blurred background
|
||||
{
|
||||
path: AppRoutes.COMPETITIONS_TEAM,
|
||||
element: <CompetitionsTeam />,
|
||||
},
|
||||
{
|
||||
path: AppRoutes.COMPETITIONS_CREATE_TEAM,
|
||||
element: <CompetitionsCreateTeam />,
|
||||
},
|
||||
{
|
||||
path: AppRoutes.COMPETITIONS_UPDATE_TEAM,
|
||||
element: <CompetitionsUpdateTeam />,
|
||||
path: AppRoutes.COMPETITIONS_TEAM,
|
||||
element: <CompetitionsTeam />,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -3,14 +3,12 @@ import type { ReactNode } from 'react';
|
||||
|
||||
export interface SplashProps {
|
||||
children: ReactNode;
|
||||
className?: classNames.Argument;
|
||||
}
|
||||
|
||||
export const Splash = ({ children, className }: SplashProps) => {
|
||||
export const Splash = ({ children }: SplashProps) => {
|
||||
const splashClasses = classNames(
|
||||
'w-full h-full text-xs text-center text-gray-800 dark:text-gray-200',
|
||||
'flex items-center justify-center',
|
||||
className
|
||||
'flex items-center justify-center'
|
||||
);
|
||||
return <div className={splashClasses}>{children}</div>;
|
||||
};
|
||||
|
||||
@@ -458,20 +458,6 @@ export type CreateReferralSet = {
|
||||
};
|
||||
};
|
||||
|
||||
export type UpdateReferralSet = {
|
||||
updateReferralSet: {
|
||||
id: string;
|
||||
isTeam: boolean;
|
||||
team?: {
|
||||
name: string;
|
||||
teamUrl?: string;
|
||||
avatarUrl?: string;
|
||||
closed: boolean;
|
||||
allowList: string[];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export enum MarginMode {
|
||||
MARGIN_MODE_CROSS_MARGIN = 1,
|
||||
MARGIN_MODE_ISOLATED_MARGIN,
|
||||
@@ -503,8 +489,7 @@ export type Transaction =
|
||||
| LiquidityProvisionSubmission
|
||||
| ApplyReferralCode
|
||||
| JoinTeam
|
||||
| CreateReferralSet
|
||||
| UpdateReferralSet;
|
||||
| CreateReferralSet;
|
||||
|
||||
export const isMarginModeUpdateTransaction = (
|
||||
transaction: Transaction
|
||||
|
||||
Reference in New Issue
Block a user