mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-04-24 03:00:09 -04:00
feat: show DAOs in a modal and match NFT gallery styling
(cherry picked from commit a29835078c490e73ef2cc447d8c10959915cd560)
This commit is contained in:
committed by
Alec LaLonde
parent
591b7d1e9f
commit
62376d0f9b
BIN
packages/web/assets/chains/polygon.png
Normal file
BIN
packages/web/assets/chains/polygon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
packages/web/assets/chains/xDai.png
Normal file
BIN
packages/web/assets/chains/xDai.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -10,13 +10,16 @@ const SHOW_MEMBERSHIPS = 4;
|
||||
|
||||
export const PlayerTileMemberships: React.FC<Props> = ({ player }) => (
|
||||
<Wrap>
|
||||
{player.daohausMemberships.slice(0, SHOW_MEMBERSHIPS).map((member) => (
|
||||
<WrapItem key={member.id}>
|
||||
<MetaTag size="md" fontWeight="normal">
|
||||
{member.moloch.title}
|
||||
</MetaTag>
|
||||
</WrapItem>
|
||||
))}
|
||||
{player.daohausMemberships
|
||||
.filter((m) => m.moloch.title !== null)
|
||||
.slice(0, SHOW_MEMBERSHIPS)
|
||||
.map((member) => (
|
||||
<WrapItem key={member.id}>
|
||||
<MetaTag size="md" fontWeight="normal">
|
||||
{member.moloch.title}
|
||||
</MetaTag>
|
||||
</WrapItem>
|
||||
))}
|
||||
{player.daohausMemberships.length > SHOW_MEMBERSHIPS && (
|
||||
<WrapItem>
|
||||
<MetaTag size="md" fontWeight="normal">
|
||||
|
||||
@@ -109,7 +109,7 @@ export const PlayerGallery: React.FC<Props> = ({ player, onRemoveClick }) => {
|
||||
>
|
||||
NFT Gallery
|
||||
</Text>
|
||||
<ModalCloseButton />
|
||||
<ModalCloseButton color="blueLight" />
|
||||
</HStack>
|
||||
</Box>
|
||||
<Flex p={2} css={modalContentStyles}>
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
import { Box, Flex, HStack, Text } from '@metafam/ds';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Heading,
|
||||
HStack,
|
||||
Link,
|
||||
Modal,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalOverlay,
|
||||
SimpleGrid,
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
import { isBackdropFilterSupported } from 'utils/compatibilityHelpers';
|
||||
|
||||
import polygonImage from '../../../assets/chains/polygon.png';
|
||||
import xDaiImage from '../../../assets/chains/xDai.png';
|
||||
import ethereumImage from '../../../assets/moloch/ethereum.png';
|
||||
import hausdaoImage from '../../../assets/moloch/hausdao.png';
|
||||
import metacartelImage from '../../../assets/moloch/metacartel.png';
|
||||
@@ -10,94 +26,236 @@ import metagameImage from '../../../assets/moloch/metagame.png';
|
||||
import raidGuildImage from '../../../assets/moloch/raid_guild.png';
|
||||
import { ProfileSection } from '../../ProfileSection';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment; onRemoveClick: () => void };
|
||||
export const PlayerMemberships: React.FC<Props> = ({
|
||||
const getImageMoloch = (title: string) => {
|
||||
if (title.toLowerCase().includes('hausdao')) return hausdaoImage;
|
||||
if (title.toLowerCase().includes('metacartel')) return metacartelImage;
|
||||
if (title.toLowerCase().includes('metaclan')) return metaclanImage;
|
||||
if (title.toLowerCase().includes('metagame')) return metagameImage;
|
||||
if (title.toLowerCase().includes('raid guild')) return raidGuildImage;
|
||||
if (title.toLowerCase().includes('xdai')) return xDaiImage;
|
||||
if (title.toLowerCase().includes('polygon')) return polygonImage;
|
||||
return ethereumImage;
|
||||
};
|
||||
|
||||
const LinkDao: React.FC<{ chain: string; address: string }> = ({
|
||||
chain,
|
||||
address,
|
||||
children,
|
||||
}) => {
|
||||
const DaoHeading = () => (
|
||||
<Heading
|
||||
fontWeight="bold"
|
||||
textTransform="uppercase"
|
||||
color="cyanText"
|
||||
fontSize="xs"
|
||||
mb="1"
|
||||
>
|
||||
{children || `Unknown ${chain} DAO`}
|
||||
</Heading>
|
||||
);
|
||||
|
||||
let explorerUrl;
|
||||
if (chain.toLowerCase() === 'xdai')
|
||||
explorerUrl = `https://blockscout.com/xdai/mainnet/address/${address}`;
|
||||
else if (chain.toLowerCase() === 'ethereum')
|
||||
explorerUrl = `https://etherscan.io/address/${address}`;
|
||||
else return <DaoHeading />;
|
||||
|
||||
return (
|
||||
<Link href={explorerUrl} isExternal>
|
||||
<DaoHeading />
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
type DaoListingProps = {
|
||||
memberId: string;
|
||||
memberShares?: string;
|
||||
memberRank?: string;
|
||||
memberXp?: number;
|
||||
title?: string;
|
||||
daoShares?: string;
|
||||
chain?: string;
|
||||
address?: string;
|
||||
};
|
||||
|
||||
const DaoListing: React.FC<DaoListingProps> = ({
|
||||
title,
|
||||
memberShares,
|
||||
daoShares,
|
||||
memberRank,
|
||||
memberXp,
|
||||
chain,
|
||||
address,
|
||||
}) => {
|
||||
let message;
|
||||
if (memberXp !== undefined) {
|
||||
message = `XP: ${Math.floor(memberXp || 0)}`;
|
||||
} else {
|
||||
message = `Shares: ${memberShares}/${daoShares}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<HStack alignItems="center" mb={6}>
|
||||
<Flex bg="purpleBoxLight" width={16} height={16} mr={6}>
|
||||
<Box
|
||||
bgImage={`url(${getImageMoloch(title || chain || '')})`}
|
||||
backgroundSize="cover"
|
||||
width={12}
|
||||
height={12}
|
||||
m="auto"
|
||||
/>
|
||||
</Flex>
|
||||
<Box>
|
||||
<LinkDao chain={chain || ''} address={address || ''}>
|
||||
{title}
|
||||
</LinkDao>
|
||||
<HStack alignItems="center">
|
||||
<Text fontSize="xs" casing="capitalize" mr={3}>
|
||||
{memberRank || 'player'}
|
||||
</Text>
|
||||
<Text fontSize="xs">{message}</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
</HStack>
|
||||
);
|
||||
};
|
||||
|
||||
type MembershipSectionProps = {
|
||||
player: PlayerFragmentFragment;
|
||||
onRemoveClick: () => void;
|
||||
};
|
||||
|
||||
export const PlayerMemberships: React.FC<MembershipSectionProps> = ({
|
||||
player,
|
||||
onRemoveClick,
|
||||
}) => {
|
||||
const [show, setShow] = React.useState(false);
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
// TODO Probably a better way to do that or should be completed, API/IPFS ?
|
||||
const getImageMoloch = (title: string) => {
|
||||
if (title.toLowerCase().includes('hausdao')) return hausdaoImage;
|
||||
if (title.toLowerCase().includes('metacartel')) return metacartelImage;
|
||||
if (title.toLowerCase().includes('metaclan')) return metaclanImage;
|
||||
if (title.toLowerCase().includes('raid guild')) return raidGuildImage;
|
||||
return ethereumImage;
|
||||
};
|
||||
const modalContentStyles = isBackdropFilterSupported()
|
||||
? {
|
||||
backgroundColor: 'rgba(255,255,255,0.08)',
|
||||
backdropFilter: 'blur(8px)',
|
||||
}
|
||||
: {
|
||||
backgroundColor: 'rgba(7, 2, 29, 0.91)',
|
||||
};
|
||||
|
||||
const memberships: DaoListingProps[] = [
|
||||
{
|
||||
memberId: 'metagame-pinned',
|
||||
title: 'MetaGame',
|
||||
memberRank: player.rank || '',
|
||||
memberXp: player.total_xp,
|
||||
},
|
||||
...(player.daohausMemberships || []).map((m) => ({
|
||||
memberId: m.id,
|
||||
title: m.moloch.title || undefined,
|
||||
memberShares: m.shares,
|
||||
daoShares: m.moloch.totalShares,
|
||||
chain: m.moloch.chain,
|
||||
address: m.molochAddress,
|
||||
})),
|
||||
];
|
||||
|
||||
return (
|
||||
<ProfileSection title="Memberships" onRemoveClick={onRemoveClick}>
|
||||
<HStack alignItems="center" mb={6}>
|
||||
<Flex bg="purpleBoxLight" width={16} height={16} mr={6}>
|
||||
<Box
|
||||
bgImage={`url(${metagameImage})`}
|
||||
backgroundSize="cover"
|
||||
width={12}
|
||||
height={12}
|
||||
m="auto"
|
||||
/>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Text fontSize="md" mb="1">
|
||||
MetaGame
|
||||
</Text>
|
||||
<HStack alignItems="center">
|
||||
<Text fontSize="xs" casing="capitalize" mr={3}>
|
||||
{
|
||||
// TODO Im not 100% sure this should be player.rank ?
|
||||
}
|
||||
{(player.rank || '').toLowerCase()}
|
||||
</Text>
|
||||
<Text fontSize="xs">
|
||||
{`XP: ${Math.floor(player.total_xp || 0)}`}
|
||||
</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
</HStack>
|
||||
{
|
||||
// TODO Fake data => Should be retrieved from DAO
|
||||
(player.daohausMemberships || [])
|
||||
.slice(0, show ? 999 : 3)
|
||||
.map((member) => (
|
||||
<HStack alignItems="center" mb={6} key={member.id}>
|
||||
<Flex bg="purpleBoxLight" width={16} height={16} mr={6}>
|
||||
<Box
|
||||
bgImage={`url(${getImageMoloch(member.moloch.title || '')})`}
|
||||
backgroundSize="cover"
|
||||
width={12}
|
||||
height={12}
|
||||
m="auto"
|
||||
/>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Text fontSize="md" mb="1">
|
||||
{member.moloch.title}
|
||||
</Text>
|
||||
<HStack alignItems="center">
|
||||
<Text fontSize="xs" casing="capitalize" mr={3}>
|
||||
player
|
||||
</Text>
|
||||
<Text fontSize="xs">
|
||||
Shares: {member.shares}/{member.moloch.totalShares}
|
||||
</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
</HStack>
|
||||
))
|
||||
}
|
||||
{(player.daohausMemberships || []).length > 3 && (
|
||||
{memberships.slice(0, 4).map((dao) => (
|
||||
<DaoListing
|
||||
key={dao.memberId}
|
||||
memberId={dao.memberId}
|
||||
title={dao.title}
|
||||
memberShares={dao.memberShares}
|
||||
daoShares={dao.daoShares}
|
||||
memberRank={dao.memberRank}
|
||||
memberXp={dao.memberXp}
|
||||
chain={dao.chain}
|
||||
address={dao.address}
|
||||
/>
|
||||
))}
|
||||
|
||||
{memberships.length > 4 && (
|
||||
<Text
|
||||
as="span"
|
||||
fontFamily="body"
|
||||
fontSize="xs"
|
||||
color="cyanText"
|
||||
cursor="pointer"
|
||||
onClick={() => setShow(!show)}
|
||||
onClick={onOpen}
|
||||
>
|
||||
View {show ? 'less' : 'all'}
|
||||
View all
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
isCentered
|
||||
scrollBehavior="inside"
|
||||
>
|
||||
<ModalOverlay>
|
||||
<ModalContent maxW="6xl" bg="none">
|
||||
<Box bg="purple80" borderTopRadius="lg" p={4} w="100%">
|
||||
<HStack>
|
||||
<Text
|
||||
fontFamily="mono"
|
||||
fontSize="sm"
|
||||
fontWeight="bold"
|
||||
color="blueLight"
|
||||
as="div"
|
||||
mr="auto"
|
||||
>
|
||||
Memberships
|
||||
</Text>
|
||||
<ModalCloseButton color="blueLight" />
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
<Flex p={2} css={modalContentStyles}>
|
||||
<Box
|
||||
overflowY="scroll"
|
||||
overflowX="hidden"
|
||||
maxH="80vh"
|
||||
borderBottomRadius="lg"
|
||||
w="100%"
|
||||
color="white"
|
||||
css={{
|
||||
scrollbarColor: 'rgba(70,20,100,0.8) rgba(255,255,255,0)',
|
||||
'::-webkit-scrollbar': {
|
||||
width: '8px',
|
||||
background: 'none',
|
||||
},
|
||||
'::-webkit-scrollbar-thumb': {
|
||||
background: 'rgba(70,20,100,0.8)',
|
||||
borderRadius: '999px',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SimpleGrid
|
||||
columns={{ base: 1, md: 2 }}
|
||||
gap={6}
|
||||
padding={6}
|
||||
boxShadow="md"
|
||||
>
|
||||
{memberships.map((dao) => (
|
||||
<DaoListing
|
||||
key={dao.memberId}
|
||||
memberId={dao.memberId}
|
||||
title={dao.title}
|
||||
memberShares={dao.memberShares}
|
||||
daoShares={dao.daoShares}
|
||||
memberRank={dao.memberRank}
|
||||
memberXp={dao.memberXp}
|
||||
chain={dao.chain}
|
||||
address={dao.address}
|
||||
/>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
</Flex>
|
||||
</ModalContent>
|
||||
</ModalOverlay>
|
||||
</Modal>
|
||||
</ProfileSection>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -48,11 +48,13 @@ export const PlayerFragment = gql`
|
||||
daohausMemberships {
|
||||
id
|
||||
shares
|
||||
molochAddress
|
||||
moloch {
|
||||
id
|
||||
title
|
||||
version
|
||||
totalShares
|
||||
chain
|
||||
}
|
||||
}
|
||||
brightid_status {
|
||||
|
||||
@@ -14,6 +14,7 @@ const membershipsQuery = gql`
|
||||
id
|
||||
title
|
||||
version
|
||||
chain
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export type PersonalityOption = {
|
||||
};
|
||||
|
||||
export type Membership = Pick<Member, 'id'> & {
|
||||
moloch: Pick<Moloch, 'id' | 'title' | 'version'>;
|
||||
moloch: Pick<Moloch, 'id' | 'title' | 'version' | 'chain'>;
|
||||
};
|
||||
|
||||
export type MeType =
|
||||
|
||||
Reference in New Issue
Block a user