feat: show DAOs in a modal and match NFT gallery styling

(cherry picked from commit a29835078c490e73ef2cc447d8c10959915cd560)
This commit is contained in:
Matthew Cantelon
2021-05-21 17:11:25 -07:00
committed by Alec LaLonde
parent 591b7d1e9f
commit 62376d0f9b
8 changed files with 246 additions and 82 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -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">

View File

@@ -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}>

View File

@@ -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>
);
};

View File

@@ -48,11 +48,13 @@ export const PlayerFragment = gql`
daohausMemberships {
id
shares
molochAddress
moloch {
id
title
version
totalShares
chain
}
}
brightid_status {

View File

@@ -14,6 +14,7 @@ const membershipsQuery = gql`
id
title
version
chain
}
}
}

View File

@@ -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 =