diff --git a/packages/web/assets/fake/nft1.png b/packages/web/assets/fake/nft1.png new file mode 100644 index 00000000..fd0b4969 Binary files /dev/null and b/packages/web/assets/fake/nft1.png differ diff --git a/packages/web/assets/fake/nft2.png b/packages/web/assets/fake/nft2.png new file mode 100644 index 00000000..abfe96ab Binary files /dev/null and b/packages/web/assets/fake/nft2.png differ diff --git a/packages/web/assets/moloch/ethereum.png b/packages/web/assets/moloch/ethereum.png new file mode 100644 index 00000000..f7102ae1 Binary files /dev/null and b/packages/web/assets/moloch/ethereum.png differ diff --git a/packages/web/assets/moloch/hausdao.png b/packages/web/assets/moloch/hausdao.png new file mode 100644 index 00000000..9031e2b1 Binary files /dev/null and b/packages/web/assets/moloch/hausdao.png differ diff --git a/packages/web/assets/moloch/metacartel.png b/packages/web/assets/moloch/metacartel.png new file mode 100644 index 00000000..ebec2d99 Binary files /dev/null and b/packages/web/assets/moloch/metacartel.png differ diff --git a/packages/web/assets/moloch/metaclan.png b/packages/web/assets/moloch/metaclan.png new file mode 100644 index 00000000..fef88dfa Binary files /dev/null and b/packages/web/assets/moloch/metaclan.png differ diff --git a/packages/web/assets/moloch/metagame.png b/packages/web/assets/moloch/metagame.png new file mode 100644 index 00000000..5c159277 Binary files /dev/null and b/packages/web/assets/moloch/metagame.png differ diff --git a/packages/web/assets/moloch/raid_guild.png b/packages/web/assets/moloch/raid_guild.png new file mode 100644 index 00000000..ef6b9a1b Binary files /dev/null and b/packages/web/assets/moloch/raid_guild.png differ diff --git a/packages/web/components/Player/Box/PlayerAchievements.tsx b/packages/web/components/Player/Box/PlayerAchievements.tsx new file mode 100644 index 00000000..960593d0 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerAchievements.tsx @@ -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 = ({ + player, + setRemoveBox, +}) => { + const [show, setShow] = React.useState(false); + const fakeData = [ + 'Founding Father of MetaGame', + 'Summoner of Meta Fam', + 'Dragon Quests Quest', + ]; + + return ( + + {(fakeData || []).slice(0, show ? 999 : 3).map((title) => ( + + + {title} + + ))} + {(player.daohausMemberships || []).length > 3 && ( + setShow(!show)} + > + View {show ? 'less' : 'all'} + + )} + + ); +}; diff --git a/packages/web/components/Player/Box/PlayerAddBox.tsx b/packages/web/components/Player/Box/PlayerAddBox.tsx new file mode 100644 index 00000000..ad875195 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerAddBox.tsx @@ -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 = ({ boxList, setNewBox }) => { + const [show, setShow] = React.useState(false); + const addBox = (e: any) => { + setShow(false); + setNewBox(e.target.value); + }; + + return ( + + {!show && ( + + )} + {show && ( + <> + + + + + + )} + + ); +}; diff --git a/packages/web/components/Player/Box/PlayerBoxe.tsx b/packages/web/components/Player/Box/PlayerBoxe.tsx new file mode 100644 index 00000000..73fa7c6a --- /dev/null +++ b/packages/web/components/Player/Box/PlayerBoxe.tsx @@ -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 = ({ + children, + title, + setRemoveBox, +}) => ( + + {!!title && ( + + + + {title} + + + + + )} + + {children} + + +); diff --git a/packages/web/components/Player/Box/PlayerCollab.tsx b/packages/web/components/Player/Box/PlayerCollab.tsx new file mode 100644 index 00000000..d6c2eb82 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerCollab.tsx @@ -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 = ({ player }) => { + return ( + + + + + role + + + Community Lead + + + + + + timezone + + + + + {player.box_profile?.location || '-'} + + + + + + + Availability + + + + + {player.availability_hours || '0'}h/week + + + + + {}} mr={4}> + collab + + {}} disabled> + trust + + + + + ); +}; diff --git a/packages/web/components/Player/Box/PlayerContactButtons.tsx b/packages/web/components/Player/Box/PlayerContactButtons.tsx new file mode 100644 index 00000000..3590bdc7 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerContactButtons.tsx @@ -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 = ({ + player, + setRemoveBox, +}) => { + return ( + + + {player.Accounts.map((acc) => { + if (acc.type === 'TWITTER') { + const link = `https://twitter.com/${acc.identifier}`; + return ( + + ); + } + if (acc.type === 'GITHUB') { + const link = `https://github.com/${acc.identifier}`; + return ( + + ); + } + return null; + })} + + + ); +}; diff --git a/packages/web/components/Player/Box/PlayerGallery.tsx b/packages/web/components/Player/Box/PlayerGallery.tsx new file mode 100644 index 00000000..96ec5083 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerGallery.tsx @@ -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 = ({ 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 ( + + {(fakeData || []).slice(0, show ? 999 : 3).map((nft) => ( + + + + + + + {nft.title} + + + {nft.priceInEth}Ξ ($ + {parseFloat(`${nft.priceInEth * fakeEthPrice}`).toFixed(2)}) + + + + ))} + {(player.daohausMemberships || []).length > 3 && ( + setShow(!show)} + > + View {show ? 'less' : 'all'} + + )} + + ); +}; diff --git a/packages/web/components/Player/Box/PlayerHero.tsx b/packages/web/components/Player/Box/PlayerHero.tsx new file mode 100644 index 00000000..10d4ed95 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerHero.tsx @@ -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 = ({ player }) => { + const [show, setShow] = React.useState(false); + + return ( + + + + + + + {getPlayerName(player)} + + {player.playerType?.title && ( + + {player.playerType.title.toUpperCase()} + + )} + + + <> +

+ {`${getPlayerDescription(player).substring( + 0, + show ? getPlayerDescription(player).length : 115, + )}${show || '...'} `} + setShow(!show)} + > + Read {show ? 'less' : 'more'} + +

+ +
+ + {player.EnneagramType && ( + + {player.EnneagramType.name} + + + {player.EnneagramType.name} + + + {player.EnneagramType.description} + + + + )} + +
+
+
+ ); +}; diff --git a/packages/web/components/Player/Box/PlayerMemberships.tsx b/packages/web/components/Player/Box/PlayerMemberships.tsx new file mode 100644 index 00000000..4453e5d9 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerMemberships.tsx @@ -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 = ({ + 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 ( + + + + + + + + MetaGame + + + + { + // TODO Im not 100% sure this should be player.rank ? + } + {(player.rank || '').toLowerCase()} + + XP: {Math.round(player.totalXp || 0)} + + + + { + // TODO Fake data => Should be retrieved from DAO + (player.daohausMemberships || []) + .slice(0, show ? 999 : 3) + .map((member) => ( + + + + + + + {member.moloch.title} + + + + player + + XP: 0 + + + + )) + } + {(player.daohausMemberships || []).length > 3 && ( + setShow(!show)} + > + View {show ? 'less' : 'all'} + + )} + + ); +}; diff --git a/packages/web/components/Player/Box/PlayerSkills.tsx b/packages/web/components/Player/Box/PlayerSkills.tsx new file mode 100644 index 00000000..50e68543 --- /dev/null +++ b/packages/web/components/Player/Box/PlayerSkills.tsx @@ -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 = ({ player, setRemoveBox }) => { + return ( + + + {!(player.Player_Skills || []).length && ( + + Gamer + + )} + { + // TODO based on reference design category color was not used ? + } + {(player.Player_Skills || []).map(({ Skill }) => ( + + {Skill.name} + + ))} + + + ); +}; diff --git a/packages/web/components/Player/PlayerHero.tsx b/packages/web/components/Player/PlayerHero.tsx deleted file mode 100644 index 230d02e1..00000000 --- a/packages/web/components/Player/PlayerHero.tsx +++ /dev/null @@ -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 = ({ player }) => { - return ( - - - - - - - {getPlayerName(player)} - - {player.playerType?.title ? ( - - {player.playerType?.title.toUpperCase()} - - ) : null} - - - - - - - - ); -}; diff --git a/packages/web/pages/player/[username].tsx b/packages/web/pages/player/[username].tsx index 8ace4069..fd1492c3 100644 --- a/packages/web/pages/player/[username].tsx +++ b/packages/web/pages/player/[username].tsx @@ -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; const PlayerPage: React.FC = ({ 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([]); + 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 ; } + 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 ( + removeBox(column, name)} + /> + ); + case BOX_TYPE.PLAYER_CONTACT_BUTTONS: + return ( + removeBox(column, name)} + /> + ); + case BOX_TYPE.PLAYER_GALLERY: + return ( + removeBox(column, name)} + /> + ); + case BOX_TYPE.PLAYER_MEMBERSHIPS: + return ( + removeBox(column, name)} + /> + ); + default: + case BOX_TYPE.PLAYER_ACHIEVEMENTS: + return ( + removeBox(column, name)} + /> + ); + } + }; + return ( - <> - - + // TODO Should be a custom background and maybe on app level(with the header) + - - -

{getPlayerDescription(player)}

- {player.EnneagramType ? ( - - {player.EnneagramType.name} - - - {player.EnneagramType.name} - - - {player.EnneagramType.description} - - - - ) : null} -
- {player.Player_Skills.length ? ( - - - {player.Player_Skills.map(({ Skill }) => ( - - {Skill.name} - - ))} - - - ) : null} - {player.daohausMemberships.length ? ( - - - {player.daohausMemberships.map((member) => ( - - {member.moloch.title} - - ))} - - - ) : null} -
+ + + + + + {(fakeData || [[], [], []])[0].map((name) => ( + {getBox(0, name)} + ))} + + addBox(0, name)} + /> + + + + + + + + + + {(fakeData || [[], [], []])[1].map((name) => ( + {getBox(1, name)} + ))} + + addBox(1, name)} + /> + + + + {(fakeData || [[], [], []])[2].map((name) => ( + {getBox(2, name)} + ))} + + addBox(2, name)} + /> + + + + + +
- +
); };