mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-04-24 03:00:09 -04:00
PatronTile
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { SimpleGrid } from '@metafam/ds';
|
||||
import { Maybe } from '@metafam/utils';
|
||||
import { PatronTile } from 'components/Patron/PatronTile';
|
||||
import { PlayerTile } from 'components/Player/PlayerTile';
|
||||
import { Player } from 'graphql/autogen/types';
|
||||
import { Patron } from 'graphql/types';
|
||||
import React from 'react';
|
||||
|
||||
@@ -15,8 +16,13 @@ export const PatronList: React.FC<Props> = ({ patrons, pSeedPrice }) => (
|
||||
spacing="8"
|
||||
autoRows="minmax(35rem, auto)"
|
||||
>
|
||||
{patrons.map((patron, index) => (
|
||||
<PatronTile key={patron.id} {...{ patron, index, pSeedPrice }} />
|
||||
{patrons.map((player, index) => (
|
||||
<PlayerTile
|
||||
player={player as Player}
|
||||
pSeedPrice={pSeedPrice}
|
||||
index={index}
|
||||
isPatron
|
||||
/>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
);
|
||||
|
||||
64
packages/web/components/Patron/PatronRank.tsx
Normal file
64
packages/web/components/Patron/PatronRank.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Flex, MetaTag } from '@metafam/ds';
|
||||
import { computeRank, Constants, Maybe } from '@metafam/utils';
|
||||
import { utils } from 'ethers';
|
||||
import { Player } from 'graphql/autogen/types';
|
||||
import { Patron } from 'graphql/types';
|
||||
import React, { useMemo } from 'react';
|
||||
import { PATRON_RANKS, PATRONS_PER_RANK } from 'utils/patronHelpers';
|
||||
|
||||
type Props = {
|
||||
patron: Patron;
|
||||
index: number;
|
||||
pSeedPrice: Maybe<number>;
|
||||
};
|
||||
|
||||
export const PatronRank: React.FC<Props> = ({ index, patron, pSeedPrice }) => {
|
||||
const player = patron as Player;
|
||||
|
||||
const patronRank = useMemo(
|
||||
() => computeRank(index, PATRONS_PER_RANK, PATRON_RANKS),
|
||||
[index],
|
||||
);
|
||||
|
||||
const displayBalance = useMemo(() => {
|
||||
const pSeedAmount = parseFloat(
|
||||
utils.formatUnits(patron.pSeedBalance, Constants.PSEED_DECIMALS),
|
||||
);
|
||||
const pSeedBalance = `${Math.floor(pSeedAmount).toLocaleString()} pSEED`;
|
||||
return pSeedPrice == null
|
||||
? pSeedBalance
|
||||
: `$${(pSeedAmount * pSeedPrice).toLocaleString(undefined, {
|
||||
maximumFractionDigits: 0,
|
||||
})}`;
|
||||
}, [patron, pSeedPrice]);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
flexDir="column"
|
||||
gap={1}
|
||||
pos="absolute"
|
||||
left={-8}
|
||||
p={3}
|
||||
top={-8}
|
||||
background="rgba(255, 255, 255, 0.1)"
|
||||
backdropFilter="blur(10.5px)"
|
||||
borderRadius="8px"
|
||||
>
|
||||
{patron.pSeedBalance != null && (
|
||||
<MetaTag size="md">{displayBalance}</MetaTag>
|
||||
)}
|
||||
{patronRank && (
|
||||
<MetaTag
|
||||
backgroundColor={patronRank?.toLowerCase()}
|
||||
size="md"
|
||||
color="blackAlpha.600"
|
||||
>
|
||||
{patronRank}
|
||||
</MetaTag>
|
||||
)}
|
||||
<MetaTag size="md">{`XP: ${Math.floor(
|
||||
player.totalXP,
|
||||
).toLocaleString()}`}</MetaTag>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
@@ -1,164 +0,0 @@
|
||||
import {
|
||||
Box,
|
||||
getTimeZoneFor,
|
||||
Heading,
|
||||
HStack,
|
||||
LinkBox,
|
||||
LinkOverlay,
|
||||
MetaTag,
|
||||
MetaTile,
|
||||
MetaTileBody,
|
||||
MetaTileHeader,
|
||||
Text,
|
||||
VStack,
|
||||
Wrap,
|
||||
WrapItem,
|
||||
} from '@metafam/ds';
|
||||
import { computeRank, Constants, Maybe } from '@metafam/utils';
|
||||
import { PlayerAvatar } from 'components/Player/PlayerAvatar';
|
||||
import { PlayerContacts } from 'components/Player/PlayerContacts';
|
||||
import { PlayerTileMemberships } from 'components/Player/PlayerTileMemberships';
|
||||
import { SkillsTags } from 'components/Quest/Skills';
|
||||
import { utils } from 'ethers';
|
||||
import { Player, Skill } from 'graphql/autogen/types';
|
||||
import { Patron } from 'graphql/types';
|
||||
import NextLink from 'next/link';
|
||||
import React, { useMemo } from 'react';
|
||||
import { FaGlobe } from 'react-icons/fa';
|
||||
import { PATRON_RANKS, PATRONS_PER_RANK } from 'utils/patronHelpers';
|
||||
import {
|
||||
getPlayerBanner,
|
||||
getPlayerDescription,
|
||||
getPlayerName,
|
||||
getPlayerURL,
|
||||
} from 'utils/playerHelpers';
|
||||
|
||||
type Props = {
|
||||
patron: Patron;
|
||||
index: number;
|
||||
pSeedPrice: Maybe<number>;
|
||||
};
|
||||
|
||||
const MAX_BIO_LENGTH = 240;
|
||||
|
||||
export const PatronTile: React.FC<Props> = ({ index, patron, pSeedPrice }) => {
|
||||
const player = patron as Player;
|
||||
|
||||
const patronRank = useMemo(
|
||||
() => computeRank(index, PATRONS_PER_RANK, PATRON_RANKS),
|
||||
[index],
|
||||
);
|
||||
|
||||
const { label: timeZone = null } = useMemo(
|
||||
() =>
|
||||
getTimeZoneFor({ location: player.profile?.timeZone ?? undefined }) ?? {
|
||||
label: null,
|
||||
offset: null,
|
||||
},
|
||||
[player.profile?.timeZone],
|
||||
);
|
||||
|
||||
const displayDescription = useMemo(() => {
|
||||
const description = getPlayerDescription(player);
|
||||
return description && description.length > MAX_BIO_LENGTH
|
||||
? `${description.substring(0, MAX_BIO_LENGTH - 9)}…`
|
||||
: description;
|
||||
}, [player]);
|
||||
|
||||
const displayBalance = useMemo(() => {
|
||||
const pSeedAmount = parseFloat(
|
||||
utils.formatUnits(patron.pSeedBalance, Constants.PSEED_DECIMALS),
|
||||
);
|
||||
const pSeedBalance = `${Math.floor(pSeedAmount).toLocaleString()} pSEED`;
|
||||
return pSeedPrice == null
|
||||
? pSeedBalance
|
||||
: `$${(pSeedAmount * pSeedPrice).toLocaleString(undefined, {
|
||||
maximumFractionDigits: 0,
|
||||
})}`;
|
||||
}, [patron, pSeedPrice]);
|
||||
|
||||
return (
|
||||
<LinkBox>
|
||||
<MetaTile>
|
||||
<Box
|
||||
bgImage={`url(${getPlayerBanner(player)})`}
|
||||
bgSize="cover"
|
||||
bgPosition="center"
|
||||
position="absolute"
|
||||
top={0}
|
||||
left={0}
|
||||
w="100%"
|
||||
h="4.5rem"
|
||||
/>
|
||||
<NextLink as={getPlayerURL(player)} href="/player/[username]" passHref>
|
||||
<LinkOverlay>
|
||||
<MetaTileHeader>
|
||||
<VStack>
|
||||
<PlayerAvatar player={player} size="xl" />
|
||||
<Heading size="xs" color="white">
|
||||
{getPlayerName(player)}
|
||||
</Heading>
|
||||
</VStack>
|
||||
<Wrap w="100%" justify="center">
|
||||
{patron.pSeedBalance != null && (
|
||||
<WrapItem>
|
||||
<MetaTag size="md">{displayBalance}</MetaTag>
|
||||
</WrapItem>
|
||||
)}
|
||||
{patronRank && (
|
||||
<WrapItem>
|
||||
<MetaTag
|
||||
backgroundColor={patronRank?.toLowerCase()}
|
||||
size="md"
|
||||
color="blackAlpha.600"
|
||||
>
|
||||
{patronRank}
|
||||
</MetaTag>
|
||||
</WrapItem>
|
||||
)}
|
||||
<WrapItem>
|
||||
<MetaTag size="md">{`XP: ${Math.floor(
|
||||
player.totalXP,
|
||||
).toLocaleString()}`}</MetaTag>
|
||||
</WrapItem>
|
||||
</Wrap>
|
||||
{timeZone && (
|
||||
<HStack alignItems="center" w="auto" justify="center">
|
||||
<FaGlobe color="blueLight" fontSize="0.875rem" />
|
||||
<Text fontSize="sm">{timeZone || '―'}</Text>
|
||||
</HStack>
|
||||
)}
|
||||
{displayDescription && (
|
||||
<VStack spacing={2} align="stretch" pt="0.5rem">
|
||||
<Text textStyle="caption">About</Text>
|
||||
<Text fontSize="sm">{displayDescription}</Text>
|
||||
</VStack>
|
||||
)}
|
||||
</MetaTileHeader>
|
||||
</LinkOverlay>
|
||||
</NextLink>
|
||||
<MetaTileBody>
|
||||
{player.skills?.length && (
|
||||
<VStack spacing={2} align="stretch">
|
||||
<Text textStyle="caption">SKILLS</Text>
|
||||
<SkillsTags
|
||||
skills={player.skills.map((s) => s.Skill) as Skill[]}
|
||||
/>
|
||||
</VStack>
|
||||
)}
|
||||
|
||||
<PlayerTileMemberships player={player} />
|
||||
|
||||
{player.accounts?.length && (
|
||||
<VStack spacing={2} align="stretch">
|
||||
<Text textStyle="caption">CONTACT</Text>
|
||||
<HStack mt="2">
|
||||
<PlayerContacts player={player} />
|
||||
</HStack>
|
||||
</VStack>
|
||||
)}
|
||||
</MetaTileBody>
|
||||
</MetaTile>
|
||||
</LinkBox>
|
||||
);
|
||||
};
|
||||
@@ -5,23 +5,16 @@ import React from 'react';
|
||||
|
||||
type Props = {
|
||||
players: Player[];
|
||||
showSeasonalXP?: boolean;
|
||||
};
|
||||
|
||||
export const PlayerList: React.FC<Props> = ({
|
||||
players,
|
||||
showSeasonalXP = false,
|
||||
}) => (
|
||||
export const PlayerList: React.FC<Props> = ({ players }) => (
|
||||
<SimpleGrid
|
||||
columns={[1, null, 2, 3]}
|
||||
spacing={8}
|
||||
autoRows="minmax(35rem, auto)"
|
||||
>
|
||||
{players.map((player, idx) => (
|
||||
<PlayerTile
|
||||
key={player.profile?.username ?? idx}
|
||||
{...{ player, showSeasonalXP }}
|
||||
/>
|
||||
<PlayerTile key={player.profile?.username ?? idx} {...{ player }} />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
);
|
||||
|
||||
@@ -11,12 +11,15 @@ import {
|
||||
Text,
|
||||
VStack,
|
||||
} from '@metafam/ds';
|
||||
import { Maybe } from '@metafam/utils';
|
||||
import { PatronRank } from 'components/Patron/PatronRank';
|
||||
import { PlayerContacts } from 'components/Player/PlayerContacts';
|
||||
import { PlayerProfilePicture } from 'components/Player/PlayerProfilePicture';
|
||||
import { PlayerTileMemberships } from 'components/Player/PlayerTileMemberships';
|
||||
import { SkillsTags } from 'components/Quest/Skills';
|
||||
import { Player, Skill } from 'graphql/autogen/types';
|
||||
import { getAllMemberships, GuildMembership } from 'graphql/getMemberships';
|
||||
import { Patron } from 'graphql/types';
|
||||
import NextLink from 'next/link';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
@@ -30,12 +33,19 @@ import { DAOMembershipSmall } from './Section/PlayerMemberships';
|
||||
|
||||
type Props = {
|
||||
player: Player;
|
||||
showSeasonalXP?: boolean;
|
||||
isPatron?: boolean;
|
||||
pSeedPrice?: Maybe<number>;
|
||||
index?: number;
|
||||
};
|
||||
|
||||
const MAX_BIO_LENGTH = 240;
|
||||
|
||||
export const PlayerTile: React.FC<Props> = ({ player }) => {
|
||||
export const PlayerTile: React.FC<Props> = ({
|
||||
player,
|
||||
isPatron = false,
|
||||
pSeedPrice,
|
||||
index,
|
||||
}) => {
|
||||
const description = getPlayerDescription(player);
|
||||
const displayDescription =
|
||||
(description?.length ?? 0) > MAX_BIO_LENGTH
|
||||
@@ -68,7 +78,15 @@ export const PlayerTile: React.FC<Props> = ({ player }) => {
|
||||
>
|
||||
<MetaTileHeader>
|
||||
<VStack pos="relative" h="full">
|
||||
<PlayerRank {...{ player }} />
|
||||
{isPatron && typeof index === 'number' && pSeedPrice ? (
|
||||
<PatronRank
|
||||
patron={player as Patron}
|
||||
pSeedPrice={pSeedPrice}
|
||||
index={index}
|
||||
/>
|
||||
) : (
|
||||
<PlayerRank player={player} />
|
||||
)}
|
||||
<PlayerProfilePicture {...{ player }} size="xl" />
|
||||
<Flex px={3} w="full" pos="absolute" bottom={-6} zIndex={1}>
|
||||
<Heading
|
||||
|
||||
Reference in New Issue
Block a user