feat(trading): team profile improvements (#6054)
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
This commit is contained in:
parent
204871b81c
commit
62ecaaa9ce
@ -9,6 +9,10 @@ import {
|
||||
Button,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
Tooltip,
|
||||
TradingAnchorButton,
|
||||
Intent,
|
||||
CopyWithTooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { TransferStatus, type Asset } from '@vegaprotocol/types';
|
||||
import classNames from 'classnames';
|
||||
@ -18,6 +22,7 @@ import {
|
||||
addDecimalsFormatNumberQuantum,
|
||||
formatNumber,
|
||||
getDateTimeFormat,
|
||||
removePaginationWrapper,
|
||||
} from '@vegaprotocol/utils';
|
||||
import {
|
||||
useTeam,
|
||||
@ -52,6 +57,7 @@ import {
|
||||
ActiveRewardCard,
|
||||
DispatchMetricInfo,
|
||||
} from '../../components/rewards-container/reward-card';
|
||||
import { usePartyProfilesQuery } from '../../components/vega-wallet-connect-button/__generated__/PartyProfiles';
|
||||
|
||||
export const CompetitionsTeam = () => {
|
||||
const t = useT();
|
||||
@ -140,11 +146,25 @@ const TeamPage = ({
|
||||
const t = useT();
|
||||
const [showGames, setShowGames] = useState(true);
|
||||
|
||||
const createdAt = new Date(team.createdAt);
|
||||
|
||||
const closedIndicator = team.closed ? (
|
||||
<div className="border rounded border-vega-clight-300 dark:border-vega-cdark-300 px-1 pt-[1px] flex items-baseline gap-1">
|
||||
<VegaIcon name={VegaIconNames.LOCK} size={10} />
|
||||
<span>{t('Private')}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="border rounded border-vega-clight-300 dark:border-vega-cdark-300 px-1 pt-[1px] flex items-baseline gap-1">
|
||||
<VegaIcon name={VegaIconNames.GLOBE} size={10} />
|
||||
<span>{t('Public')}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<LayoutWithGradient>
|
||||
<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">
|
||||
<div className="flex flex-col items-start gap-1 lg:gap-2">
|
||||
<h1
|
||||
className="calt text-2xl lg:text-3xl xl:text-5xl"
|
||||
data-testid="team-name"
|
||||
@ -154,6 +174,38 @@ const TeamPage = ({
|
||||
<div className="flex gap-2">
|
||||
<JoinTeam team={team} partyTeam={partyTeam} refetch={refetch} />
|
||||
<UpdateTeamButton team={team} />
|
||||
{team.teamUrl && team.teamUrl.length > 0 && (
|
||||
<Tooltip description={t("Visit the team's page.")}>
|
||||
<span>
|
||||
<TradingAnchorButton
|
||||
intent={Intent.Info}
|
||||
target="_blank"
|
||||
referrerPolicy="no-referrer"
|
||||
href={team.teamUrl}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
|
||||
</TradingAnchorButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
<CopyWithTooltip
|
||||
description={t('Copy this page url.')}
|
||||
text={globalThis.location.href}
|
||||
>
|
||||
<button className="h-10 w-7">
|
||||
<VegaIcon name={VegaIconNames.COPY} size={16} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</div>
|
||||
<div className="flex gap-2 items-baseline text-xs text-muted font-alpha calt">
|
||||
{closedIndicator}
|
||||
<div className="">
|
||||
{t('Created at')}:{' '}
|
||||
<span className="text-vega-cdark-600 dark:text-vega-clight-600 ">
|
||||
{getDateTimeFormat().format(createdAt)}
|
||||
</span>{' '}
|
||||
({t('epoch')}: {team.createdAtEpoch})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@ -331,13 +383,30 @@ const Games = ({
|
||||
const Members = ({ members }: { members?: Member[] }) => {
|
||||
const t = useT();
|
||||
|
||||
const partyIds = members?.map((m) => m.referee) || [];
|
||||
const { data: profilesData } = usePartyProfilesQuery({
|
||||
variables: {
|
||||
partyIds,
|
||||
},
|
||||
skip: partyIds.length === 0,
|
||||
});
|
||||
const profiles = removePaginationWrapper(
|
||||
profilesData?.partiesProfilesConnection?.edges
|
||||
);
|
||||
|
||||
if (!members?.length) {
|
||||
return <p>{t('No members')}</p>;
|
||||
}
|
||||
|
||||
const data = orderBy(
|
||||
members.map((m) => ({
|
||||
referee: <RefereeLink pubkey={m.referee} isCreator={m.isCreator} />,
|
||||
referee: (
|
||||
<RefereeLink
|
||||
pubkey={m.referee}
|
||||
isCreator={m.isCreator}
|
||||
profiles={profiles}
|
||||
/>
|
||||
),
|
||||
rewards: formatNumber(m.totalQuantumRewards),
|
||||
volume: formatNumber(m.totalQuantumVolume),
|
||||
gamesPlayed: formatNumber(m.totalGamesPlayed),
|
||||
@ -351,7 +420,7 @@ const Members = ({ members }: { members?: Member[] }) => {
|
||||
return (
|
||||
<Table
|
||||
columns={[
|
||||
{ name: 'referee', displayName: t('Member ID') },
|
||||
{ name: 'referee', displayName: t('Member') },
|
||||
{ name: 'rewards', displayName: t('Rewards earned') },
|
||||
{ name: 'volume', displayName: t('Total volume') },
|
||||
{ name: 'gamesPlayed', displayName: t('Games played') },
|
||||
@ -373,21 +442,43 @@ const Members = ({ members }: { members?: Member[] }) => {
|
||||
const RefereeLink = ({
|
||||
pubkey,
|
||||
isCreator,
|
||||
profiles,
|
||||
}: {
|
||||
pubkey: string;
|
||||
isCreator: boolean;
|
||||
profiles?: { partyId: string; alias: string }[];
|
||||
}) => {
|
||||
const t = useT();
|
||||
const linkCreator = useLinks(DApp.Explorer);
|
||||
const link = linkCreator(EXPLORER_PARTIES.replace(':id', pubkey));
|
||||
|
||||
const alias = profiles?.find((p) => p.partyId === pubkey)?.alias;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-baseline gap-2">
|
||||
<Link to={link} target="_blank" className="underline underline-offset-4">
|
||||
{truncateMiddle(pubkey)}
|
||||
</Link>{' '}
|
||||
<span className="text-muted text-xs">{isCreator ? t('Owner') : ''}</span>
|
||||
</>
|
||||
{alias || truncateMiddle(pubkey)}
|
||||
</Link>
|
||||
{!alias && (
|
||||
<Tooltip
|
||||
description={t(
|
||||
'You can set your pubkey alias by using the key selector in the top right corner.'
|
||||
)}
|
||||
>
|
||||
<button className="text-muted text-xs">
|
||||
<VegaIcon name={VegaIconNames.QUESTION_MARK} size={14} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{alias && (
|
||||
<span className="text-muted text-xs">{truncateMiddle(pubkey)}</span>
|
||||
)}
|
||||
{isCreator && (
|
||||
<span className="text-muted text-xs border border-vega-clight-300 dark:border-vega-cdark-300 rounded px-1 py-[1px]">
|
||||
{t('Owner')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -70,6 +70,12 @@ export const JoinButton = ({
|
||||
}) => {
|
||||
const t = useT();
|
||||
|
||||
/**
|
||||
* A team cannot be joined (closed) when set as such
|
||||
* and the currently connected pubkey is not whitelisted.
|
||||
*/
|
||||
const isTeamClosed = team.closed && !team.allowList.includes(pubKey || '');
|
||||
|
||||
if (!pubKey || isReadOnly) {
|
||||
return (
|
||||
<Tooltip description={t('Connect your wallet to join the team')}>
|
||||
@ -79,8 +85,9 @@ export const JoinButton = ({
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
// Party is the creator of a team
|
||||
else if (partyTeam && partyTeam.referrer === pubKey) {
|
||||
if (partyTeam && partyTeam.referrer === pubKey) {
|
||||
// Party is the creator of THIS team
|
||||
if (partyTeam.teamId === team.teamId) {
|
||||
return (
|
||||
@ -105,8 +112,24 @@ export const JoinButton = ({
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Party is in a team, but not this one
|
||||
else if (partyTeam && partyTeam.teamId !== team.teamId) {
|
||||
if (partyTeam && partyTeam.teamId !== team.teamId) {
|
||||
// This team is closed.
|
||||
if (isTeamClosed) {
|
||||
return (
|
||||
<Tooltip description={t('You cannot join a private team')}>
|
||||
<Button
|
||||
intent={Intent.Primary}
|
||||
data-testid="switch-team-button"
|
||||
disabled={true}
|
||||
>
|
||||
{t('Switch team')}{' '}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
// This team is open.
|
||||
return (
|
||||
<Button
|
||||
onClick={() => onJoin('switch')}
|
||||
@ -117,8 +140,9 @@ export const JoinButton = ({
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
// Joined. Current party is already in this team
|
||||
else if (partyTeam && partyTeam.teamId === team.teamId) {
|
||||
if (partyTeam && partyTeam.teamId === team.teamId) {
|
||||
return (
|
||||
<Button intent={Intent.None} disabled={true}>
|
||||
<span className="flex items-center gap-2">
|
||||
@ -131,6 +155,17 @@ export const JoinButton = ({
|
||||
);
|
||||
}
|
||||
|
||||
// This team is closed.
|
||||
if (isTeamClosed) {
|
||||
return (
|
||||
<Tooltip description={t('You cannot join a closed team')}>
|
||||
<Button intent={Intent.Primary} disabled={true}>
|
||||
{t('Join team')}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
// This team is open.
|
||||
return (
|
||||
<Button onClick={() => onJoin('join')} intent={Intent.Primary}>
|
||||
{t('Join team')}
|
||||
|
@ -67,7 +67,7 @@ export const CompetitionsLeaderboard = ({
|
||||
),
|
||||
earned: num(td.totalQuantumRewards),
|
||||
games: num(td.totalGamesPlayed),
|
||||
status: td.closed ? t('Closed') : t('Open'),
|
||||
status: td.closed ? t('Private') : t('Public'),
|
||||
volume: num(td.totalQuantumVolume),
|
||||
};
|
||||
})}
|
||||
|
@ -242,6 +242,7 @@ def test_team_page_games_table(team_page: Tuple[Page, str, str, VegaServiceNull]
|
||||
expect(page.get_by_test_id("games-toggle")).to_have_text("Results (10)")
|
||||
expect(page.get_by_test_id("rank-0")).to_have_text("1")
|
||||
expect(page.get_by_test_id("epoch-0")).to_have_text("19")
|
||||
expect(page.get_by_test_id("endtime-0")).to_be_visible()
|
||||
expect(page.get_by_test_id("type-0")).to_have_text(
|
||||
"Price maker fees paid • tDAI "
|
||||
)
|
||||
@ -256,6 +257,9 @@ def test_team_page_members_table(team_page: Tuple[Page, str, str, VegaServiceNul
|
||||
page.get_by_test_id("members-toggle").click()
|
||||
expect(page.get_by_test_id("members-toggle")).to_have_text("Members (4)")
|
||||
expect(page.get_by_test_id("referee-0")).to_be_visible()
|
||||
expect(page.get_by_test_id("icon-question-mark").nth(0)).to_be_visible()
|
||||
expect(page.get_by_test_id("referee-3").locator(".text-muted").nth(1)
|
||||
).to_have_text("Owner")
|
||||
expect(page.get_by_test_id("joinedAt-0")).to_be_visible()
|
||||
expect(page.get_by_test_id("joinedAtEpoch-0")).to_have_text("9")
|
||||
|
||||
@ -263,6 +267,8 @@ def test_team_page_members_table(team_page: Tuple[Page, str, str, VegaServiceNul
|
||||
def test_team_page_headline(team_page: Tuple[Page, str, str, VegaServiceNull]):
|
||||
page, team_name, team_id, vega = team_page
|
||||
expect(page.get_by_test_id("team-name")).to_have_text(team_name)
|
||||
expect(page.get_by_test_id("icon-open-external").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("icon-copy")).to_be_visible()
|
||||
expect(page.get_by_test_id("members-count-stat")).to_have_text("4")
|
||||
|
||||
expect(page.get_by_test_id("total-games-stat")).to_have_text("1")
|
||||
@ -295,7 +301,7 @@ def test_leaderboard(competitions_page: Tuple[Page, str, VegaServiceNull]):
|
||||
page.get_by_test_id("rank-1").locator(".text-vega-clight-500")
|
||||
).to_have_count(1)
|
||||
expect(page.get_by_test_id("team-1")).to_have_text(team_name)
|
||||
expect(page.get_by_test_id("status-1")).to_have_text("Open")
|
||||
expect(page.get_by_test_id("status-1")).to_have_text("Public")
|
||||
|
||||
# FIXME: the numbers are different we need to clarify this with the backend
|
||||
# expect(competitions_page.get_by_test_id("earned-1")).to_have_text("160")
|
||||
@ -320,7 +326,6 @@ def test_game_card(competitions_page: Tuple[Page, str, VegaServiceNull]):
|
||||
"Price maker fees paid • tDAI"
|
||||
)
|
||||
expect(game_1.get_by_test_id("assessed-over")).to_have_text("15 epochs")
|
||||
page.pause()
|
||||
expect(game_1.get_by_test_id("scope")).to_have_text("Eligible")
|
||||
expect(game_1.get_by_test_id("staking-requirement")).to_have_text("-")
|
||||
expect(game_1.get_by_test_id("average-position")).to_have_text("-")
|
||||
|
@ -18,6 +18,7 @@
|
||||
"Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction": "Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction",
|
||||
"Are you sure you want to join team: {{team}}": "Are you sure you want to join team: {{team}}",
|
||||
"As a team creator, you cannot switch teams": "As a team creator, you cannot switch teams",
|
||||
"You cannot join a private team": "You cannot join a private team",
|
||||
"Assessed over": "Assessed over",
|
||||
"Asset (1)": "Asset (1)",
|
||||
"Assets": "Assets",
|
||||
@ -213,6 +214,8 @@
|
||||
"Market triggers cancellation or governance vote has passed to cancel": "Market triggers cancellation or governance vote has passed to cancel",
|
||||
"Markets": "Markets",
|
||||
"Member ID": "Member ID",
|
||||
"Member": "Member",
|
||||
"You can set your pubkey alias by using the key selector in the top right corner.": "You can set your pubkey alias by using the key selector in the top right corner.",
|
||||
"Members": "Members",
|
||||
"Members ({{count}})": "Members ({{count}})",
|
||||
"Menu": "Menu",
|
||||
@ -496,5 +499,9 @@
|
||||
"{{distance}} ago": "{{distance}} ago",
|
||||
"{{entity}} scope": "{{entity}} scope",
|
||||
"{{instrumentCode}} liquidity provision": "{{instrumentCode}} liquidity provision",
|
||||
"{{reward}}x": "{{reward}}x"
|
||||
"{{reward}}x": "{{reward}}x",
|
||||
"Private": "Private",
|
||||
"Public": "Public",
|
||||
"Copy this page url.": "Copy this page url.",
|
||||
"Visit the team's page.": "Visit the team's page."
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user