Feature/moar like designed (#177)
* Implement player mockup based on Design reference * Fix missing type
BIN
packages/web/assets/fake/nft1.png
Normal file
|
After Width: | Height: | Size: 448 KiB |
BIN
packages/web/assets/fake/nft2.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
packages/web/assets/moloch/ethereum.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
packages/web/assets/moloch/hausdao.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
packages/web/assets/moloch/metacartel.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
packages/web/assets/moloch/metaclan.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
packages/web/assets/moloch/metagame.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
packages/web/assets/moloch/raid_guild.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
43
packages/web/components/Player/Box/PlayerAchievements.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { HStack, Text } from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
import { FaMedal } from 'react-icons/fa';
|
||||
|
||||
import { PlayerBox } from './PlayerBoxe';
|
||||
|
||||
// TODO Fake data
|
||||
type Props = { player: PlayerFragmentFragment; setRemoveBox: () => void };
|
||||
export const PlayerAchievements: React.FC<Props> = ({
|
||||
player,
|
||||
setRemoveBox,
|
||||
}) => {
|
||||
const [show, setShow] = React.useState(false);
|
||||
const fakeData = [
|
||||
'Founding Father of MetaGame',
|
||||
'Summoner of Meta Fam',
|
||||
'Dragon Quests Quest',
|
||||
];
|
||||
|
||||
return (
|
||||
<PlayerBox title="Achievements" setRemoveBox={setRemoveBox}>
|
||||
{(fakeData || []).slice(0, show ? 999 : 3).map((title) => (
|
||||
<HStack alignItems="baseline" mb={3}>
|
||||
<FaMedal color="#FBB112" />
|
||||
<Text fontSize="md">{title}</Text>
|
||||
</HStack>
|
||||
))}
|
||||
{(player.daohausMemberships || []).length > 3 && (
|
||||
<Text
|
||||
as="span"
|
||||
fontFamily="body"
|
||||
fontSize="xs"
|
||||
color="cyanText"
|
||||
cursor="pointer"
|
||||
onClick={() => setShow(!show)}
|
||||
>
|
||||
View {show ? 'less' : 'all'}
|
||||
</Text>
|
||||
)}
|
||||
</PlayerBox>
|
||||
);
|
||||
};
|
||||
72
packages/web/components/Player/Box/PlayerAddBox.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Button, Flex, HStack, Select } from '@metafam/ds';
|
||||
import React from 'react';
|
||||
|
||||
type Props = { boxList: string[]; setNewBox: (name: string) => void };
|
||||
export const PlayerAddBox: React.FC<Props> = ({ boxList, setNewBox }) => {
|
||||
const [show, setShow] = React.useState(false);
|
||||
const addBox = (e: any) => {
|
||||
setShow(false);
|
||||
setNewBox(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex
|
||||
h="200px"
|
||||
bg="whiteAlpha.200"
|
||||
borderBottomRadius="lg"
|
||||
border="dashed 1px rgba(255, 255, 255, 0.3)"
|
||||
borderTopRadius="lg"
|
||||
p={6}
|
||||
boxShadow="md"
|
||||
css={{ backdropFilter: 'blur(8px)' }}
|
||||
>
|
||||
{!show && (
|
||||
<Button
|
||||
onClick={() => setShow(true)}
|
||||
m="auto"
|
||||
bg="blue20"
|
||||
_hover={{ bg: 'purpleBoxLight', opacity: '0.8' }}
|
||||
color="offwhite"
|
||||
opacity="0.4"
|
||||
>
|
||||
ADD NEW SECTION
|
||||
</Button>
|
||||
)}
|
||||
{show && (
|
||||
<>
|
||||
<HStack m="auto">
|
||||
<Select
|
||||
css={{
|
||||
'&>option': {
|
||||
'background-color': '#40347C',
|
||||
'border-bottom': '2px solid #962d22',
|
||||
},
|
||||
}}
|
||||
placeholder="Select a section"
|
||||
borderColor="offwhite"
|
||||
onChange={addBox}
|
||||
>
|
||||
{!(boxList || []).length && (
|
||||
<option value="nothing" disabled>
|
||||
No choice :/
|
||||
</option>
|
||||
)}
|
||||
{(boxList || []).sort().map((box) => (
|
||||
<option value={box}>{box}</option>
|
||||
))}
|
||||
</Select>
|
||||
<Button
|
||||
onClick={() => setShow(false)}
|
||||
bg="blue20"
|
||||
_hover={{ bg: 'purpleBoxLight', opacity: '1' }}
|
||||
color="offwhite"
|
||||
opacity="0.8"
|
||||
>
|
||||
CANCEL
|
||||
</Button>
|
||||
</HStack>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
51
packages/web/components/Player/Box/PlayerBoxe.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { Box, HStack, Text } from '@metafam/ds';
|
||||
import React from 'react';
|
||||
import { FaTimes } from 'react-icons/fa';
|
||||
|
||||
export type PlayerBoxProps = {
|
||||
title?: string;
|
||||
children?: React.ReactNode;
|
||||
setRemoveBox?: () => void;
|
||||
};
|
||||
|
||||
// TODO If MetaBox is only used for Player profile maybe merge both component
|
||||
export const PlayerBox: React.FC<PlayerBoxProps> = ({
|
||||
children,
|
||||
title,
|
||||
setRemoveBox,
|
||||
}) => (
|
||||
<Box>
|
||||
{!!title && (
|
||||
<Box bg="rgba(70, 20, 100, 0.8)" borderTopRadius="lg" p={4}>
|
||||
<HStack>
|
||||
<Text
|
||||
fontFamily="mono"
|
||||
fontSize="sm"
|
||||
fontWeight="bold"
|
||||
color="blueLight"
|
||||
as="div"
|
||||
mr="auto"
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
<FaTimes
|
||||
color="#A5B9F6"
|
||||
opacity="0.4"
|
||||
cursor="pointer"
|
||||
onClick={setRemoveBox}
|
||||
/>
|
||||
</HStack>
|
||||
</Box>
|
||||
)}
|
||||
<Box
|
||||
bg="whiteAlpha.200"
|
||||
borderBottomRadius="lg"
|
||||
borderTopRadius={!title ? 'lg' : 0}
|
||||
p={6}
|
||||
boxShadow="md"
|
||||
css={{ backdropFilter: 'blur(8px)' }}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
69
packages/web/components/Player/Box/PlayerCollab.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Box, Flex, HStack, MetaButton, Text } from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
import { FaClock, FaGlobe } from 'react-icons/fa';
|
||||
|
||||
import { PlayerBox } from './PlayerBoxe';
|
||||
|
||||
// TODO Fake data, role not found and location instead of timezone
|
||||
type Props = { player: PlayerFragmentFragment };
|
||||
export const PlayerCollab: React.FC<Props> = ({ player }) => {
|
||||
return (
|
||||
<PlayerBox>
|
||||
<Flex align="center" direction="row">
|
||||
<Box>
|
||||
<Text fontSize="xs" color="blueLight" casing="uppercase" mb={3}>
|
||||
role
|
||||
</Text>
|
||||
<Text fontSize="xl" mb="1">
|
||||
Community Lead
|
||||
</Text>
|
||||
</Box>
|
||||
<Box
|
||||
height="3rem"
|
||||
borderRight="1px"
|
||||
borderColor="purpleBoxLight"
|
||||
mr={4}
|
||||
ml={4}
|
||||
/>
|
||||
<Box ml={1}>
|
||||
<Text fontSize="xs" color="blueLight" casing="uppercase" mb={3}>
|
||||
timezone
|
||||
</Text>
|
||||
<HStack alignItems="baseline">
|
||||
<FaGlobe color="#A5B9F6" />
|
||||
<Text fontSize="xl" mb="1">
|
||||
{player.box_profile?.location || '-'}
|
||||
</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
<Box
|
||||
height="3rem"
|
||||
borderRight="1px"
|
||||
borderColor="purpleBoxLight"
|
||||
mr={4}
|
||||
ml={4}
|
||||
/>
|
||||
<Box>
|
||||
<Text fontSize="xs" color="blueLight" casing="uppercase" mb={3}>
|
||||
Availability
|
||||
</Text>
|
||||
<HStack alignItems="baseline">
|
||||
<FaClock color="#A5B9F6" />
|
||||
<Text fontSize="xl" mb="1">
|
||||
{player.availability_hours || '0'}h/week
|
||||
</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
<Box ml="auto">
|
||||
<MetaButton size="lg" px={8} onClick={() => {}} mr={4}>
|
||||
collab
|
||||
</MetaButton>
|
||||
<MetaButton size="lg" px={8} onClick={() => {}} disabled>
|
||||
trust
|
||||
</MetaButton>
|
||||
</Box>
|
||||
</Flex>
|
||||
</PlayerBox>
|
||||
);
|
||||
};
|
||||
65
packages/web/components/Player/Box/PlayerContactButtons.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Button, HStack } from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
import { FaGithub, FaTwitter } from 'react-icons/fa';
|
||||
|
||||
import { PlayerBox } from './PlayerBoxe';
|
||||
|
||||
// TODO Maybe add more social platform
|
||||
type Props = { player: PlayerFragmentFragment; setRemoveBox: () => void };
|
||||
export const PlayerContactButtons: React.FC<Props> = ({
|
||||
player,
|
||||
setRemoveBox,
|
||||
}) => {
|
||||
return (
|
||||
<PlayerBox title="Contact" setRemoveBox={setRemoveBox}>
|
||||
<HStack>
|
||||
{player.Accounts.map((acc) => {
|
||||
if (acc.type === 'TWITTER') {
|
||||
const link = `https://twitter.com/${acc.identifier}`;
|
||||
return (
|
||||
<Button
|
||||
as="a"
|
||||
href={link}
|
||||
target="_blank"
|
||||
key={link}
|
||||
size="xs"
|
||||
colorScheme="twitter"
|
||||
backgroundColor="platinum"
|
||||
borderRadius="50%"
|
||||
h={12}
|
||||
w={12}
|
||||
ml={0}
|
||||
mr={8}
|
||||
>
|
||||
<FaTwitter size={24} color="#392373" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
if (acc.type === 'GITHUB') {
|
||||
const link = `https://github.com/${acc.identifier}`;
|
||||
return (
|
||||
<Button
|
||||
as="a"
|
||||
href={link}
|
||||
target="_blank"
|
||||
key={link}
|
||||
size="xs"
|
||||
colorScheme="blackAlpha"
|
||||
backgroundColor="platinum"
|
||||
borderRadius="50%"
|
||||
h={12}
|
||||
w={12}
|
||||
ml={0}
|
||||
mr={8}
|
||||
>
|
||||
<FaGithub size={24} color="#392373" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</HStack>
|
||||
</PlayerBox>
|
||||
);
|
||||
};
|
||||
64
packages/web/components/Player/Box/PlayerGallery.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import { Box, Flex, HStack, Text } from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
|
||||
import nft1Image from '../../../assets/fake/nft1.png';
|
||||
import nft2Image from '../../../assets/fake/nft2.png';
|
||||
import { PlayerBox } from './PlayerBoxe';
|
||||
|
||||
// TODO Fake data
|
||||
type Props = { player: PlayerFragmentFragment; setRemoveBox: () => void };
|
||||
export const PlayerGallery: React.FC<Props> = ({ player, setRemoveBox }) => {
|
||||
const [show, setShow] = React.useState(false);
|
||||
const fakeEthPrice = 500;
|
||||
const fakeData = [
|
||||
{ title: 'CryptoMon Cards - Aave', priceInEth: 0.025, img: nft1Image },
|
||||
{ title: 'metagamer', priceInEth: 6.942, img: nft2Image },
|
||||
];
|
||||
return (
|
||||
<PlayerBox title="Gallery" setRemoveBox={setRemoveBox}>
|
||||
{(fakeData || []).slice(0, show ? 999 : 3).map((nft) => (
|
||||
<HStack alignItems="end" mb={6}>
|
||||
<Flex width="126px" height="126px" mr={6}>
|
||||
<Box
|
||||
bgImage={`url(${nft.img})`}
|
||||
backgroundSize="contain"
|
||||
backgroundRepeat="no-repeat"
|
||||
backgroundPosition="center"
|
||||
width="124px"
|
||||
height="124px"
|
||||
m="auto"
|
||||
/>
|
||||
</Flex>
|
||||
<Box>
|
||||
<Text
|
||||
fontSize="xs"
|
||||
fontFamily="heading"
|
||||
mt={3}
|
||||
mb={3}
|
||||
casing="uppercase"
|
||||
>
|
||||
{nft.title}
|
||||
</Text>
|
||||
<Text fontSize="sm" mb="1">
|
||||
{nft.priceInEth}Ξ ($
|
||||
{parseFloat(`${nft.priceInEth * fakeEthPrice}`).toFixed(2)})
|
||||
</Text>
|
||||
</Box>
|
||||
</HStack>
|
||||
))}
|
||||
{(player.daohausMemberships || []).length > 3 && (
|
||||
<Text
|
||||
as="span"
|
||||
fontFamily="body"
|
||||
fontSize="xs"
|
||||
color="cyanText"
|
||||
cursor="pointer"
|
||||
onClick={() => setShow(!show)}
|
||||
>
|
||||
View {show ? 'less' : 'all'}
|
||||
</Text>
|
||||
)}
|
||||
</PlayerBox>
|
||||
);
|
||||
};
|
||||
92
packages/web/components/Player/Box/PlayerHero.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
Container,
|
||||
Flex,
|
||||
HStack,
|
||||
Image,
|
||||
P,
|
||||
Text,
|
||||
} from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
import {
|
||||
getPlayerDescription,
|
||||
getPlayerImage,
|
||||
getPlayerName,
|
||||
} from 'utils/playerHelpers';
|
||||
|
||||
import { PersonalityTypes } from '../../../graphql/types';
|
||||
import { FlexContainer } from '../../Container';
|
||||
import { PlayerBox } from './PlayerBoxe';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment };
|
||||
export const PlayerHero: React.FC<Props> = ({ player }) => {
|
||||
const [show, setShow] = React.useState(false);
|
||||
|
||||
return (
|
||||
<PlayerBox>
|
||||
<Container>
|
||||
<Flex pt={16} pb={6} pl={2} pr={2} direction="column" align="center">
|
||||
<Avatar
|
||||
w={{ base: '32', md: '56' }}
|
||||
h={{ base: '32', md: '56' }}
|
||||
src={getPlayerImage(player)}
|
||||
name={getPlayerName(player)}
|
||||
/>
|
||||
<Box pt="8" textAlign="center">
|
||||
<Text fontSize="xl" fontFamily="heading" mb="1">
|
||||
{getPlayerName(player)}
|
||||
</Text>
|
||||
{player.playerType?.title && (
|
||||
<Text color="offwhite" casing="uppercase">
|
||||
{player.playerType.title.toUpperCase()}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
<Box pt="12" w="100%" textAlign="left">
|
||||
<>
|
||||
<P>
|
||||
{`${getPlayerDescription(player).substring(
|
||||
0,
|
||||
show ? getPlayerDescription(player).length : 115,
|
||||
)}${show || '...'} `}
|
||||
<Text
|
||||
as="span"
|
||||
fontFamily="body"
|
||||
fontSize="xs"
|
||||
color="cyanText"
|
||||
cursor="pointer"
|
||||
onClick={() => setShow(!show)}
|
||||
>
|
||||
Read {show ? 'less' : 'more'}
|
||||
</Text>
|
||||
</P>
|
||||
</>
|
||||
</Box>
|
||||
<Box pt="8">
|
||||
{player.EnneagramType && (
|
||||
<HStack py={6} spacing={4}>
|
||||
<Image
|
||||
w="100%"
|
||||
maxW="4rem"
|
||||
src={PersonalityTypes[player.EnneagramType.name].image}
|
||||
alt={player.EnneagramType.name}
|
||||
style={{ mixBlendMode: 'color-dodge' }}
|
||||
/>
|
||||
<FlexContainer align="stretch">
|
||||
<Text color="white" fontWeight="bold">
|
||||
{player.EnneagramType.name}
|
||||
</Text>
|
||||
<Text color="blueLight">
|
||||
{player.EnneagramType.description}
|
||||
</Text>
|
||||
</FlexContainer>
|
||||
</HStack>
|
||||
)}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Container>
|
||||
</PlayerBox>
|
||||
);
|
||||
};
|
||||
99
packages/web/components/Player/Box/PlayerMemberships.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Box, Flex, HStack, Text } from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
|
||||
import ethereumImage from '../../../assets/moloch/ethereum.png';
|
||||
import hausdaoImage from '../../../assets/moloch/hausdao.png';
|
||||
import metacartelImage from '../../../assets/moloch/metacartel.png';
|
||||
import metaclanImage from '../../../assets/moloch/metaclan.png';
|
||||
import metagameImage from '../../../assets/moloch/metagame.png';
|
||||
import raidGuildImage from '../../../assets/moloch/raid_guild.png';
|
||||
import { PlayerBox } from './PlayerBoxe';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment; setRemoveBox: () => void };
|
||||
export const PlayerMemberships: React.FC<Props> = ({
|
||||
player,
|
||||
setRemoveBox,
|
||||
}) => {
|
||||
const [show, setShow] = React.useState(false);
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
return (
|
||||
<PlayerBox title="Memberships" setRemoveBox={setRemoveBox}>
|
||||
<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.round(player.totalXp || 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}>
|
||||
<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">XP: 0</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
</HStack>
|
||||
))
|
||||
}
|
||||
{(player.daohausMemberships || []).length > 3 && (
|
||||
<Text
|
||||
as="span"
|
||||
fontFamily="body"
|
||||
fontSize="xs"
|
||||
color="cyanText"
|
||||
cursor="pointer"
|
||||
onClick={() => setShow(!show)}
|
||||
>
|
||||
View {show ? 'less' : 'all'}
|
||||
</Text>
|
||||
)}
|
||||
</PlayerBox>
|
||||
);
|
||||
};
|
||||
45
packages/web/components/Player/Box/PlayerSkills.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { MetaTag, Wrap } from '@metafam/ds';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
|
||||
import { PlayerBox } from './PlayerBoxe';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment; setRemoveBox: () => void };
|
||||
export const PlayerSkills: React.FC<Props> = ({ player, setRemoveBox }) => {
|
||||
return (
|
||||
<PlayerBox title="Skills" setRemoveBox={setRemoveBox}>
|
||||
<Wrap>
|
||||
{!(player.Player_Skills || []).length && (
|
||||
<MetaTag
|
||||
size="md"
|
||||
fontWeight="normal"
|
||||
backgroundColor="rgba(70, 20, 100, 0.8)"
|
||||
pt={2}
|
||||
pb={2}
|
||||
pl={4}
|
||||
pr={4}
|
||||
>
|
||||
Gamer
|
||||
</MetaTag>
|
||||
)}
|
||||
{
|
||||
// TODO based on reference design category color was not used ?
|
||||
}
|
||||
{(player.Player_Skills || []).map(({ Skill }) => (
|
||||
<MetaTag
|
||||
key={Skill.id}
|
||||
size="md"
|
||||
fontWeight="normal"
|
||||
backgroundColor="rgba(70, 20, 100, 0.8)"
|
||||
pt={2}
|
||||
pb={2}
|
||||
pl={4}
|
||||
pr={4}
|
||||
>
|
||||
{Skill.name}
|
||||
</MetaTag>
|
||||
))}
|
||||
</Wrap>
|
||||
</PlayerBox>
|
||||
);
|
||||
};
|
||||
@@ -1,43 +0,0 @@
|
||||
import { Avatar, Box, Container, Flex, HStack, Text } from '@metafam/ds';
|
||||
import BackgroundImage from 'assets/login-background.jpg';
|
||||
import { PlayerContacts } from 'components/Player/PlayerContacts';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
import { getPlayerImage, getPlayerName } from 'utils/playerHelpers';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment };
|
||||
|
||||
export const PlayerHero: React.FC<Props> = ({ player }) => {
|
||||
return (
|
||||
<Box
|
||||
bgImage={`url(${BackgroundImage})`}
|
||||
backgroundSize="cover"
|
||||
h={{ base: '48', md: '3xs' }}
|
||||
mb="6"
|
||||
>
|
||||
<Container maxW="xl">
|
||||
<Flex pos="relative" top={{ base: '20', md: '10' }} align="center">
|
||||
<Avatar
|
||||
w={{ base: '32', md: '56' }}
|
||||
h={{ base: '32', md: '56' }}
|
||||
src={getPlayerImage(player)}
|
||||
name={getPlayerName(player)}
|
||||
/>
|
||||
<Box pl="8">
|
||||
<Text fontSize="xl" fontFamily="heading" mb="1">
|
||||
{getPlayerName(player)}
|
||||
</Text>
|
||||
{player.playerType?.title ? (
|
||||
<Text color="offwhite">
|
||||
{player.playerType?.title.toUpperCase()}
|
||||
</Text>
|
||||
) : null}
|
||||
<HStack mt="2">
|
||||
<PlayerContacts player={player} />
|
||||
</HStack>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -1,20 +1,8 @@
|
||||
import {
|
||||
Container,
|
||||
HStack,
|
||||
Image,
|
||||
MetaBox,
|
||||
MetaTag,
|
||||
P,
|
||||
SimpleGrid,
|
||||
Text,
|
||||
Wrap,
|
||||
} from '@metafam/ds';
|
||||
import { FlexContainer } from 'components/Container';
|
||||
import { PlayerFeatures } from 'components/Player/PlayerFeatures';
|
||||
import { PlayerHero } from 'components/Player/PlayerHero';
|
||||
import { Box, Container, Flex } from '@metafam/ds';
|
||||
import BackgroundImage from 'assets/profile-background.jpg';
|
||||
import { PlayerHero } from 'components/Player/Box/PlayerHero';
|
||||
import { getPlayer } from 'graphql/getPlayer';
|
||||
import { getPlayers } from 'graphql/getPlayers';
|
||||
import { PersonalityTypes, SkillColors } from 'graphql/types';
|
||||
import {
|
||||
GetStaticPaths,
|
||||
GetStaticPropsContext,
|
||||
@@ -22,73 +10,174 @@ import {
|
||||
} from 'next';
|
||||
import Error from 'next/error';
|
||||
import React from 'react';
|
||||
import { getPlayerDescription } from 'utils/playerHelpers';
|
||||
|
||||
import { PlayerAchievements } from '../../components/Player/Box/PlayerAchievements';
|
||||
import { PlayerAddBox } from '../../components/Player/Box/PlayerAddBox';
|
||||
import { PlayerCollab } from '../../components/Player/Box/PlayerCollab';
|
||||
import { PlayerContactButtons } from '../../components/Player/Box/PlayerContactButtons';
|
||||
import { PlayerGallery } from '../../components/Player/Box/PlayerGallery';
|
||||
import { PlayerMemberships } from '../../components/Player/Box/PlayerMemberships';
|
||||
import { PlayerSkills } from '../../components/Player/Box/PlayerSkills';
|
||||
|
||||
type Props = InferGetStaticPropsType<typeof getStaticProps>;
|
||||
|
||||
const PlayerPage: React.FC<Props> = ({ player }) => {
|
||||
// TODO Fake data should be saved in back-end
|
||||
const BOX_TYPE = {
|
||||
PLAYER_SKILLS: 'Skills',
|
||||
PLAYER_CONTACT_BUTTONS: 'Contact',
|
||||
PLAYER_GALLERY: 'Gallery',
|
||||
PLAYER_MEMBERSHIPS: 'Memberships',
|
||||
PLAYER_ACHIEVEMENTS: 'Achievements',
|
||||
};
|
||||
const [boxAvailableList, setBoxAvailableList] = React.useState<string[]>([]);
|
||||
const [fakeData, setFakeData] = React.useState([
|
||||
[
|
||||
BOX_TYPE.PLAYER_SKILLS,
|
||||
BOX_TYPE.PLAYER_CONTACT_BUTTONS,
|
||||
BOX_TYPE.PLAYER_GALLERY,
|
||||
],
|
||||
[BOX_TYPE.PLAYER_MEMBERSHIPS, BOX_TYPE.PLAYER_ACHIEVEMENTS],
|
||||
[],
|
||||
]);
|
||||
|
||||
if (!player) {
|
||||
return <Error statusCode={404} />;
|
||||
}
|
||||
|
||||
const addBox = (column: number, name: string) => {
|
||||
setBoxAvailableList(boxAvailableList.filter((box) => box !== name));
|
||||
const updatedFakeData = [...fakeData];
|
||||
updatedFakeData[column].push(name);
|
||||
setFakeData(updatedFakeData);
|
||||
};
|
||||
|
||||
const removeBox = (column: number, name: string) => {
|
||||
setBoxAvailableList([...boxAvailableList, name]);
|
||||
const updatedFakeData = [...fakeData];
|
||||
updatedFakeData[column] = updatedFakeData[column].filter(
|
||||
(box) => box !== name,
|
||||
);
|
||||
setFakeData(updatedFakeData);
|
||||
};
|
||||
|
||||
const getBox = (column: number, name: string): React.ReactNode => {
|
||||
switch (name) {
|
||||
case BOX_TYPE.PLAYER_SKILLS:
|
||||
return (
|
||||
<PlayerSkills
|
||||
player={player}
|
||||
setRemoveBox={() => removeBox(column, name)}
|
||||
/>
|
||||
);
|
||||
case BOX_TYPE.PLAYER_CONTACT_BUTTONS:
|
||||
return (
|
||||
<PlayerContactButtons
|
||||
player={player}
|
||||
setRemoveBox={() => removeBox(column, name)}
|
||||
/>
|
||||
);
|
||||
case BOX_TYPE.PLAYER_GALLERY:
|
||||
return (
|
||||
<PlayerGallery
|
||||
player={player}
|
||||
setRemoveBox={() => removeBox(column, name)}
|
||||
/>
|
||||
);
|
||||
case BOX_TYPE.PLAYER_MEMBERSHIPS:
|
||||
return (
|
||||
<PlayerMemberships
|
||||
player={player}
|
||||
setRemoveBox={() => removeBox(column, name)}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
case BOX_TYPE.PLAYER_ACHIEVEMENTS:
|
||||
return (
|
||||
<PlayerAchievements
|
||||
player={player}
|
||||
setRemoveBox={() => removeBox(column, name)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<PlayerHero player={player} />
|
||||
<PlayerFeatures player={player} />
|
||||
// TODO Should be a custom background and maybe on app level(with the header)
|
||||
<Container
|
||||
maxW="100%"
|
||||
bgImage={`url(${BackgroundImage})`}
|
||||
backgroundSize="cover"
|
||||
mt={4}
|
||||
>
|
||||
<Container maxW="xl">
|
||||
<SimpleGrid columns={[1, 1, 2, 3]} spacing="8" pt="12">
|
||||
<MetaBox title="About me">
|
||||
<P>{getPlayerDescription(player)}</P>
|
||||
{player.EnneagramType ? (
|
||||
<HStack py={6} spacing={4}>
|
||||
<Image
|
||||
w="100%"
|
||||
maxW="4rem"
|
||||
src={PersonalityTypes[player.EnneagramType.name].image}
|
||||
alt={player.EnneagramType.name}
|
||||
style={{ mixBlendMode: 'color-dodge' }}
|
||||
/>
|
||||
<FlexContainer align="stretch">
|
||||
<Text color="white" fontWeight="bold">
|
||||
{player.EnneagramType.name}
|
||||
</Text>
|
||||
<Text color="blueLight">
|
||||
{player.EnneagramType.description}
|
||||
</Text>
|
||||
</FlexContainer>
|
||||
</HStack>
|
||||
) : null}
|
||||
</MetaBox>
|
||||
{player.Player_Skills.length ? (
|
||||
<MetaBox title="Skills">
|
||||
<Wrap>
|
||||
{player.Player_Skills.map(({ Skill }) => (
|
||||
<MetaTag
|
||||
key={Skill.id}
|
||||
size="md"
|
||||
fontWeight="normal"
|
||||
backgroundColor={SkillColors[Skill.category]}
|
||||
>
|
||||
{Skill.name}
|
||||
</MetaTag>
|
||||
))}
|
||||
</Wrap>
|
||||
</MetaBox>
|
||||
) : null}
|
||||
{player.daohausMemberships.length ? (
|
||||
<MetaBox title="Memberships">
|
||||
<Wrap>
|
||||
{player.daohausMemberships.map((member) => (
|
||||
<MetaTag key={member.id} size="md" fontWeight="normal">
|
||||
{member.moloch.title}
|
||||
</MetaTag>
|
||||
))}
|
||||
</Wrap>
|
||||
</MetaBox>
|
||||
) : null}
|
||||
</SimpleGrid>
|
||||
<Flex
|
||||
align="center"
|
||||
direction={['column', null, null, 'row']}
|
||||
alignItems="flex-start"
|
||||
>
|
||||
<Box width={['100%', null, null, '33%']} mr={[0, null, null, 4]}>
|
||||
<Box mb="6">
|
||||
<PlayerHero player={player} />
|
||||
</Box>
|
||||
{(fakeData || [[], [], []])[0].map((name) => (
|
||||
<Box mb="6">{getBox(0, name)}</Box>
|
||||
))}
|
||||
<Box mb="6">
|
||||
<PlayerAddBox
|
||||
boxList={boxAvailableList}
|
||||
setNewBox={(name) => addBox(0, name)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
width={['100%', null, null, '66%']}
|
||||
ml={[0, null, null, 4]}
|
||||
mt="200px"
|
||||
>
|
||||
<Box width="100%">
|
||||
<Box mb="6">
|
||||
<PlayerCollab player={player} />
|
||||
</Box>
|
||||
<Flex
|
||||
align="center"
|
||||
direction={['column', null, null, 'row']}
|
||||
alignItems="flex-start"
|
||||
>
|
||||
<Box
|
||||
width={['100%', null, null, '50%']}
|
||||
mr={[0, null, null, 4]}
|
||||
>
|
||||
{(fakeData || [[], [], []])[1].map((name) => (
|
||||
<Box mb="6">{getBox(1, name)}</Box>
|
||||
))}
|
||||
<Box mb="6">
|
||||
<PlayerAddBox
|
||||
boxList={boxAvailableList}
|
||||
setNewBox={(name) => addBox(1, name)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
width={['100%', null, null, '50%']}
|
||||
ml={[0, null, null, 4]}
|
||||
>
|
||||
{(fakeData || [[], [], []])[2].map((name) => (
|
||||
<Box mb="6">{getBox(2, name)}</Box>
|
||||
))}
|
||||
<Box mb="6">
|
||||
<PlayerAddBox
|
||||
boxList={boxAvailableList}
|
||||
setNewBox={(name) => addBox(2, name)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Container>
|
||||
</>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||