mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-01-23 05:08:01 -05:00
Implement list of Guilds in frontend
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,12 @@
|
||||
import { Button, ButtonProps } from '@chakra-ui/core';
|
||||
import React from 'react';
|
||||
|
||||
export const MetaButton: React.FC<ButtonProps> = ({ children, ...props }) => (
|
||||
type LinkProps = { href: string; target: '_blank' };
|
||||
|
||||
export const MetaButton: React.FC<ButtonProps & LinkProps> = ({
|
||||
children,
|
||||
...props
|
||||
}) => (
|
||||
<Button
|
||||
colorScheme="purple"
|
||||
textTransform="uppercase"
|
||||
|
||||
@@ -13,6 +13,8 @@ interface MetaColors {
|
||||
platinum: string;
|
||||
gold: string;
|
||||
silver: string;
|
||||
discord: string;
|
||||
discordDark: string;
|
||||
bronze: string;
|
||||
purple80: string;
|
||||
}
|
||||
@@ -91,6 +93,8 @@ export const theme: Theme = {
|
||||
purpleTag: '#40347C',
|
||||
blueLight: '#A5B9F6',
|
||||
cyanText: '#79F8FB',
|
||||
discord: '#7289da',
|
||||
discordDark: '#5d6eb3',
|
||||
},
|
||||
fonts: {
|
||||
body: '"IBM Plex Sans", sans-serif',
|
||||
|
||||
42
packages/web/components/Guild/GuildHero.tsx
Normal file
42
packages/web/components/Guild/GuildHero.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Avatar, Box, MetaButton, Text, VStack } from '@metafam/ds';
|
||||
import { GuildFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
|
||||
import { ProfileSection } from '../ProfileSection';
|
||||
import { GuildLinks } from './GuildLinks';
|
||||
|
||||
type Props = { guild: GuildFragmentFragment };
|
||||
|
||||
export const GuildHero: React.FC<Props> = ({ guild }) => {
|
||||
return (
|
||||
<ProfileSection>
|
||||
<VStack spacing={8}>
|
||||
{guild.logo ? (
|
||||
<Avatar
|
||||
w={{ base: '32', md: '56' }}
|
||||
h={{ base: '32', md: '56' }}
|
||||
src={guild.logo}
|
||||
name={guild.name}
|
||||
/>
|
||||
) : null}
|
||||
<Box textAlign="center">
|
||||
<Text fontSize="xl" fontFamily="heading" mb="1">
|
||||
{guild.name}
|
||||
</Text>
|
||||
<Text fontFamily="mono" fontSize="md" color="blueLight">
|
||||
{`${guild.type} GUILD`}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text>{guild.description}</Text>
|
||||
</Box>
|
||||
{guild.join_button_url ? (
|
||||
<MetaButton as="a" href={guild.join_button_url} target="_blank">
|
||||
Join
|
||||
</MetaButton>
|
||||
) : null}
|
||||
<GuildLinks guild={guild} />
|
||||
</VStack>
|
||||
</ProfileSection>
|
||||
);
|
||||
};
|
||||
67
packages/web/components/Guild/GuildLinks.tsx
Normal file
67
packages/web/components/Guild/GuildLinks.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Button, Wrap } from '@metafam/ds';
|
||||
import { GuildFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
import { FaDiscord, FaGlobe } from 'react-icons/fa';
|
||||
|
||||
type Props = {
|
||||
guild: GuildFragmentFragment;
|
||||
};
|
||||
|
||||
export const GuildLinks: React.FC<Props> = ({ guild }) => {
|
||||
return (
|
||||
<Wrap>
|
||||
{guild.website_url ? (
|
||||
<Button
|
||||
as="a"
|
||||
href={guild.website_url}
|
||||
target="_blank"
|
||||
size="xs"
|
||||
colorScheme="blackAlpha"
|
||||
leftIcon={<FaGlobe />}
|
||||
>
|
||||
Website
|
||||
</Button>
|
||||
) : null}
|
||||
{guild.discord_invite_url ? (
|
||||
<Button
|
||||
as="a"
|
||||
href={guild.discord_invite_url}
|
||||
target="_blank"
|
||||
size="xs"
|
||||
bgColor="discord"
|
||||
_hover={{ bgColor: 'discordDark' }}
|
||||
leftIcon={<FaDiscord />}
|
||||
>
|
||||
Discord
|
||||
</Button>
|
||||
) : null}
|
||||
{/*
|
||||
{guild.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 (
|
||||
<Button
|
||||
as="a"
|
||||
href={link}
|
||||
target="_blank"
|
||||
key={link}
|
||||
size="xs"
|
||||
colorScheme="blackAlpha"
|
||||
backgroundColor="black"
|
||||
leftIcon={<FaGithub />}
|
||||
>
|
||||
{acc.identifier}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})} */}
|
||||
</Wrap>
|
||||
);
|
||||
};
|
||||
78
packages/web/components/Guild/GuildTile.tsx
Normal file
78
packages/web/components/Guild/GuildTile.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import {
|
||||
Avatar,
|
||||
Flex,
|
||||
Heading,
|
||||
HStack,
|
||||
MetaButton,
|
||||
MetaTag,
|
||||
Text,
|
||||
VStack,
|
||||
Wrap,
|
||||
} from '@metafam/ds';
|
||||
import { GuildLinks } from 'components/Guild/GuildLinks';
|
||||
import { GuildFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
|
||||
type Props = {
|
||||
guild: GuildFragmentFragment;
|
||||
};
|
||||
|
||||
export const GuildTile: React.FC<Props> = ({ guild }) => (
|
||||
<Flex
|
||||
direction="column"
|
||||
key={guild.id}
|
||||
bg="whiteAlpha.200"
|
||||
style={{ backdropFilter: 'blur(7px)' }}
|
||||
rounded="lg"
|
||||
p="6"
|
||||
maxW="30rem"
|
||||
w="100%"
|
||||
align="stretch"
|
||||
position="relative"
|
||||
overflow="hidden"
|
||||
justify="space-between"
|
||||
>
|
||||
<VStack w="100%" spacing="6" align="stretch" mb={6} position="relative">
|
||||
<VStack>
|
||||
{guild.logo ? (
|
||||
<Avatar size="xl" src={guild.logo} name={guild.name} />
|
||||
) : null}
|
||||
|
||||
<Heading size="sm" color="white">
|
||||
{guild.name}
|
||||
</Heading>
|
||||
</VStack>
|
||||
<Wrap w="100%" justify="center">
|
||||
{guild.type ? <MetaTag size="md">{guild.type} GUILD</MetaTag> : null}
|
||||
</Wrap>
|
||||
{guild.description ? (
|
||||
<VStack spacing={2} align="stretch">
|
||||
<Text fontFamily="mono" fontSize="sm" color="blueLight">
|
||||
ABOUT
|
||||
</Text>
|
||||
<Text fontSize="sm">{guild.description}</Text>
|
||||
</VStack>
|
||||
) : null}
|
||||
</VStack>
|
||||
<VStack w="100%" spacing="6" align="stretch">
|
||||
<VStack spacing={2} align="stretch">
|
||||
<Text fontFamily="mono" fontSize="sm" color="blueLight">
|
||||
LINKS
|
||||
</Text>
|
||||
<HStack mt="2">
|
||||
<GuildLinks guild={guild} />
|
||||
</HStack>
|
||||
</VStack>
|
||||
{guild.join_button_url ? (
|
||||
<MetaButton
|
||||
as="a"
|
||||
href={guild.join_button_url}
|
||||
target="_blank"
|
||||
fontFamily="mono"
|
||||
>
|
||||
Join
|
||||
</MetaButton>
|
||||
) : null}
|
||||
</VStack>
|
||||
</Flex>
|
||||
);
|
||||
16
packages/web/components/GuildList.tsx
Normal file
16
packages/web/components/GuildList.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { SimpleGrid } from '@metafam/ds';
|
||||
import { GuildTile } from 'components/Guild/GuildTile';
|
||||
import { GuildFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
|
||||
type Props = {
|
||||
guilds: GuildFragmentFragment[];
|
||||
};
|
||||
|
||||
export const GuildList: React.FC<Props> = ({ guilds }) => (
|
||||
<SimpleGrid columns={[1, null, 2, 3]} spacing="8">
|
||||
{guilds.map((p) => (
|
||||
<GuildTile key={p.id} guild={p} />
|
||||
))}
|
||||
</SimpleGrid>
|
||||
);
|
||||
@@ -76,7 +76,7 @@ export const PageHeader: React.FC = () => {
|
||||
direction={{ base: 'column', md: 'row' }}
|
||||
spacing={{ base: 4, md: 6, lg: 10 }}
|
||||
>
|
||||
<MenuItem href="/">Players</MenuItem>
|
||||
<MenuItem href="/guilds">Guilds</MenuItem>
|
||||
<MenuItem href="https://discord.gg/VYZPBnx" isExternal>
|
||||
Discord
|
||||
</MenuItem>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Box, Text } from '@metafam/ds';
|
||||
import React from 'react';
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
value?: string | null | undefined;
|
||||
} & React.ComponentProps<typeof Text>;
|
||||
|
||||
export const PlayerFeature: React.FC<Props> = ({
|
||||
title,
|
||||
value,
|
||||
children,
|
||||
...props
|
||||
}) => (
|
||||
<Box>
|
||||
<Text
|
||||
fontFamily="body"
|
||||
fontSize="sm"
|
||||
color="blueLight"
|
||||
textTransform="uppercase"
|
||||
mb="2"
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
<Text fontFamily="body" fontSize="md" fontWeight="bold" {...props}>
|
||||
{value || children}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
@@ -1,58 +0,0 @@
|
||||
import { Container, Divider, MetaTag, Wrap } from '@metafam/ds';
|
||||
import { PlayerFeature } from 'components/Player/PlayerFeature';
|
||||
import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import React from 'react';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment };
|
||||
|
||||
export const PlayerFeatures: React.FC<Props> = ({ player }) => {
|
||||
return (
|
||||
<Container maxW="xl">
|
||||
<Wrap
|
||||
spacing="8"
|
||||
ml={{ base: '4', lg: '64' }}
|
||||
pt={{ base: '4', md: '12', lg: 0 }}
|
||||
>
|
||||
<PlayerFeature
|
||||
title="XP"
|
||||
value={Math.floor(player.totalXp).toString()}
|
||||
/>
|
||||
{player.rank && (
|
||||
<Divider orientation="vertical" color="whiteAlpha.400" />
|
||||
)}
|
||||
{player.rank && (
|
||||
<PlayerFeature title="Rank">
|
||||
<MetaTag
|
||||
backgroundColor={player.rank?.toLowerCase()}
|
||||
size="md"
|
||||
color="blackAlpha.600"
|
||||
>
|
||||
{player.rank}
|
||||
</MetaTag>
|
||||
</PlayerFeature>
|
||||
)}
|
||||
{player.box_profile?.location && (
|
||||
<Divider orientation="vertical" color="whiteAlpha.400" />
|
||||
)}
|
||||
{player.box_profile?.location && (
|
||||
<PlayerFeature
|
||||
title="Location"
|
||||
value={player.box_profile?.location}
|
||||
/>
|
||||
)}
|
||||
<Divider orientation="vertical" color="whiteAlpha.400" />
|
||||
{/* <PlayerFeature title="Role" value="N/A" color="whiteAlpha.500" /> */}
|
||||
{/* <Divider orientation="vertical" color="whiteAlpha.400" /> */}
|
||||
<PlayerFeature
|
||||
title="Availability"
|
||||
value={
|
||||
player.availability_hours != null
|
||||
? `${player.availability_hours} hr / week`
|
||||
: 'N/A'
|
||||
}
|
||||
color={player.availability_hours ? undefined : 'whiteAlpha.500'}
|
||||
/>
|
||||
</Wrap>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import { HStack, Text } from '@metafam/ds';
|
||||
import React from 'react';
|
||||
import { FaMedal } from 'react-icons/fa';
|
||||
|
||||
import { PlayerSection } from './PlayerSection';
|
||||
import { ProfileSection } from '../../ProfileSection';
|
||||
|
||||
// TODO Fake data
|
||||
type Props = { onRemoveClick: () => void };
|
||||
@@ -15,7 +15,7 @@ export const PlayerAchievements: React.FC<Props> = ({ onRemoveClick }) => {
|
||||
];
|
||||
|
||||
return (
|
||||
<PlayerSection title="Achievements" onRemoveClick={onRemoveClick}>
|
||||
<ProfileSection title="Achievements" onRemoveClick={onRemoveClick}>
|
||||
{(fakeData || []).slice(0, show ? 999 : 3).map((title) => (
|
||||
<HStack alignItems="baseline" mb={3}>
|
||||
<FaMedal color="#FBB112" />
|
||||
@@ -34,6 +34,6 @@ export const PlayerAchievements: React.FC<Props> = ({ onRemoveClick }) => {
|
||||
View {show ? 'less' : 'all'}
|
||||
</Text>
|
||||
)}
|
||||
</PlayerSection>
|
||||
</ProfileSection>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ export const PlayerCollab: React.FC<Props> = ({ player }) => {
|
||||
<HStack
|
||||
spacing={6}
|
||||
divider={
|
||||
<Divider height="3rem" color="purpleTag" orientation="vertical" />
|
||||
<Divider height="3rem" color="whiteAlpha.400" orientation="vertical" />
|
||||
}
|
||||
>
|
||||
<Box>
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import React from 'react';
|
||||
import { FaTimes } from 'react-icons/fa';
|
||||
|
||||
import { PlayerSection } from './PlayerSection';
|
||||
import { ProfileSection } from '../../ProfileSection';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment; onRemoveClick: () => void };
|
||||
|
||||
@@ -67,7 +67,7 @@ export const PlayerGallery: React.FC<Props> = ({ player, onRemoveClick }) => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const { favorites, data, loading } = useOpenSeaCollectibles({ player });
|
||||
return (
|
||||
<PlayerSection title="NFT Gallery" onRemoveClick={onRemoveClick}>
|
||||
<ProfileSection title="NFT Gallery" onRemoveClick={onRemoveClick}>
|
||||
{!loading &&
|
||||
favorites?.map((nft) => <GalleryItem nft={nft} key={nft.tokenId} />)}
|
||||
{!loading && data?.length > 3 && (
|
||||
@@ -133,6 +133,6 @@ export const PlayerGallery: React.FC<Props> = ({ player, onRemoveClick }) => {
|
||||
</ModalContent>
|
||||
</ModalOverlay>
|
||||
</Modal>
|
||||
</PlayerSection>
|
||||
</ProfileSection>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,20 +9,20 @@ import {
|
||||
|
||||
import { PersonalityTypes } from '../../../graphql/types';
|
||||
import { FlexContainer } from '../../Container';
|
||||
import { ProfileSection } from '../../ProfileSection';
|
||||
import { PlayerContacts } from '../PlayerContacts';
|
||||
import { PlayerCollab } from './PlayerCollab';
|
||||
import { PlayerSection } from './PlayerSection';
|
||||
|
||||
const BIO_LENGTH = 240;
|
||||
|
||||
type Props = { player: PlayerFragmentFragment };
|
||||
export const PlayerHero: React.FC<Props> = ({ player }) => {
|
||||
const [show, setShow] = React.useState(
|
||||
getPlayerDescription(player).length < 115,
|
||||
getPlayerDescription(player).length < BIO_LENGTH,
|
||||
);
|
||||
|
||||
return (
|
||||
<PlayerSection>
|
||||
<ProfileSection>
|
||||
<VStack spacing={8}>
|
||||
<Avatar
|
||||
w={{ base: '32', md: '56' }}
|
||||
@@ -34,12 +34,7 @@ export const PlayerHero: React.FC<Props> = ({ player }) => {
|
||||
<Text fontSize="xl" fontFamily="heading" mb="1">
|
||||
{getPlayerName(player)}
|
||||
</Text>
|
||||
|
||||
<HStack mt="2">
|
||||
<PlayerContacts player={player} />
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text>
|
||||
{`${getPlayerDescription(player).substring(
|
||||
@@ -60,6 +55,10 @@ export const PlayerHero: React.FC<Props> = ({ player }) => {
|
||||
)}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<HStack mt="2">
|
||||
<PlayerContacts player={player} />
|
||||
</HStack>
|
||||
<Box w="100%">
|
||||
<PlayerCollab player={player} />
|
||||
</Box>
|
||||
@@ -89,6 +88,6 @@ export const PlayerHero: React.FC<Props> = ({ player }) => {
|
||||
</FlexContainer>
|
||||
) : null}
|
||||
</VStack>
|
||||
</PlayerSection>
|
||||
</ProfileSection>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ 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 { PlayerSection } from './PlayerSection';
|
||||
import { ProfileSection } from '../../ProfileSection';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment; onRemoveClick: () => void };
|
||||
export const PlayerMemberships: React.FC<Props> = ({
|
||||
@@ -27,7 +27,7 @@ export const PlayerMemberships: React.FC<Props> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<PlayerSection title="Memberships" onRemoveClick={onRemoveClick}>
|
||||
<ProfileSection title="Memberships" onRemoveClick={onRemoveClick}>
|
||||
<HStack alignItems="center" mb={6}>
|
||||
<Flex bg="purpleBoxLight" width={16} height={16} mr={6}>
|
||||
<Box
|
||||
@@ -94,6 +94,6 @@ export const PlayerMemberships: React.FC<Props> = ({
|
||||
View {show ? 'less' : 'all'}
|
||||
</Text>
|
||||
)}
|
||||
</PlayerSection>
|
||||
</ProfileSection>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { PlayerFragmentFragment } from 'graphql/autogen/types';
|
||||
import { SkillColors } from 'graphql/types';
|
||||
import React from 'react';
|
||||
|
||||
import { PlayerSection } from './PlayerSection';
|
||||
import { ProfileSection } from '../../ProfileSection';
|
||||
|
||||
type Props = { player: PlayerFragmentFragment; onRemoveClick: () => void };
|
||||
export const PlayerSkills: React.FC<Props> = ({ player, onRemoveClick }) => {
|
||||
@@ -11,7 +11,7 @@ export const PlayerSkills: React.FC<Props> = ({ player, onRemoveClick }) => {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<PlayerSection title="Skills" onRemoveClick={onRemoveClick}>
|
||||
<ProfileSection title="Skills" onRemoveClick={onRemoveClick}>
|
||||
<Wrap>
|
||||
{(player.Player_Skills || []).map(({ Skill }) => (
|
||||
<MetaTag
|
||||
@@ -28,6 +28,6 @@ export const PlayerSkills: React.FC<Props> = ({ player, onRemoveClick }) => {
|
||||
</MetaTag>
|
||||
))}
|
||||
</Wrap>
|
||||
</PlayerSection>
|
||||
</ProfileSection>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Box, HStack, Text } from '@metafam/ds';
|
||||
import React from 'react';
|
||||
import { FaTimes } from 'react-icons/fa';
|
||||
|
||||
export type PlayerSectionProps = {
|
||||
export type ProfileSectionProps = {
|
||||
title?: string;
|
||||
children?: React.ReactNode;
|
||||
onRemoveClick?: () => void;
|
||||
@@ -10,7 +10,7 @@ export type PlayerSectionProps = {
|
||||
};
|
||||
|
||||
// TODO If MetaBox is only used for Player profile maybe merge both component
|
||||
export const PlayerSection: React.FC<PlayerSectionProps> = ({
|
||||
export const ProfileSection: React.FC<ProfileSectionProps> = ({
|
||||
children,
|
||||
title,
|
||||
onRemoveClick,
|
||||
@@ -53,3 +53,18 @@ export const PlayerFragment = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const GuildFragment = gql`
|
||||
fragment GuildFragment on Guild {
|
||||
id
|
||||
guildname
|
||||
description
|
||||
discord_invite_url
|
||||
join_button_url
|
||||
logo
|
||||
moloch_address
|
||||
name
|
||||
type
|
||||
website_url
|
||||
}
|
||||
`;
|
||||
|
||||
23
packages/web/graphql/getGuild.ts
Normal file
23
packages/web/graphql/getGuild.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import gql from 'fake-tag';
|
||||
|
||||
import { GetGuildQuery, GetGuildQueryVariables } from './autogen/types';
|
||||
import { client } from './client';
|
||||
import { GuildFragment } from './fragments';
|
||||
|
||||
const guildQuery = gql`
|
||||
query GetGuild($guildname: String!) {
|
||||
Guild(where: { guildname: { _eq: $guildname } }) {
|
||||
...GuildFragment
|
||||
}
|
||||
}
|
||||
${GuildFragment}
|
||||
`;
|
||||
|
||||
export const getGuild = async (guildname: string | undefined) => {
|
||||
if (!guildname) return null;
|
||||
const { data } = await client
|
||||
.query<GetGuildQuery, GetGuildQueryVariables>(guildQuery, { guildname })
|
||||
.toPromise();
|
||||
|
||||
return data?.Guild[0];
|
||||
};
|
||||
30
packages/web/graphql/getGuilds.ts
Normal file
30
packages/web/graphql/getGuilds.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import gql from 'fake-tag';
|
||||
|
||||
import { GetGuildsQuery, GetGuildsQueryVariables } from './autogen/types';
|
||||
import { client } from './client';
|
||||
import { GuildFragment } from './fragments';
|
||||
|
||||
const guildsQuery = gql`
|
||||
query GetGuilds($limit: Int) {
|
||||
Guild(limit: $limit) {
|
||||
...GuildFragment
|
||||
}
|
||||
}
|
||||
${GuildFragment}
|
||||
`;
|
||||
|
||||
export const getGuilds = async (limit = 50) => {
|
||||
const { data, error } = await client
|
||||
.query<GetGuildsQuery, GetGuildsQueryVariables>(guildsQuery, { limit })
|
||||
.toPromise();
|
||||
|
||||
if (!data) {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return data.Guild;
|
||||
};
|
||||
88
packages/web/pages/guild/[guildname].tsx
Normal file
88
packages/web/pages/guild/[guildname].tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import { Box, Flex, LoadingState, Stack } from '@metafam/ds';
|
||||
import { getGuild } from 'graphql/getGuild';
|
||||
import { getGuilds } from 'graphql/getGuilds';
|
||||
import {
|
||||
GetStaticPaths,
|
||||
GetStaticPropsContext,
|
||||
InferGetStaticPropsType,
|
||||
} from 'next';
|
||||
import Error from 'next/error';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import { PageContainer } from '../../components/Container';
|
||||
import { GuildHero } from '../../components/Guild/GuildHero';
|
||||
import { ProfileSection } from '../../components/ProfileSection';
|
||||
|
||||
type Props = InferGetStaticPropsType<typeof getStaticProps>;
|
||||
|
||||
const GuildPage: React.FC<Props> = ({ guild }) => {
|
||||
const router = useRouter();
|
||||
|
||||
if (router.isFallback) {
|
||||
return <LoadingState />;
|
||||
}
|
||||
|
||||
if (!guild) {
|
||||
return <Error statusCode={404} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<Stack
|
||||
spacing={6}
|
||||
align="center"
|
||||
direction={{ base: 'column', lg: 'row' }}
|
||||
alignItems="flex-start"
|
||||
maxWidth="7xl"
|
||||
>
|
||||
<Flex flex={1} d="column">
|
||||
<Box mb="6">
|
||||
<GuildHero guild={guild} />
|
||||
</Box>
|
||||
<Box mb="6">
|
||||
<ProfileSection />
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex flex={2}>
|
||||
<Flex
|
||||
align="center"
|
||||
direction={{ base: 'column', lg: 'row' }}
|
||||
alignItems="flex-start"
|
||||
>
|
||||
<ProfileSection />
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Stack>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default GuildPage;
|
||||
|
||||
type QueryParams = { guildname: string };
|
||||
|
||||
export const getStaticPaths: GetStaticPaths<QueryParams> = async () => {
|
||||
const guilds = await getGuilds();
|
||||
|
||||
return {
|
||||
paths: guilds.map(({ guildname }) => ({
|
||||
params: { guildname },
|
||||
})),
|
||||
fallback: true,
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticProps = async (
|
||||
context: GetStaticPropsContext<QueryParams>,
|
||||
) => {
|
||||
const guildname = context.params?.guildname;
|
||||
const guild = await getGuild(guildname);
|
||||
|
||||
return {
|
||||
props: {
|
||||
guild,
|
||||
},
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
25
packages/web/pages/guilds.tsx
Normal file
25
packages/web/pages/guilds.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { PageContainer } from 'components/Container';
|
||||
import { GuildList } from 'components/GuildList';
|
||||
import { getGuilds } from 'graphql/getGuilds';
|
||||
import { InferGetStaticPropsType } from 'next';
|
||||
import React from 'react';
|
||||
|
||||
type Props = InferGetStaticPropsType<typeof getStaticProps>;
|
||||
|
||||
export const getStaticProps = async () => {
|
||||
const guilds = await getGuilds();
|
||||
return {
|
||||
props: {
|
||||
guilds,
|
||||
},
|
||||
revalidate: 10,
|
||||
};
|
||||
};
|
||||
|
||||
const GuildsPage: React.FC<Props> = ({ guilds }) => (
|
||||
<PageContainer>
|
||||
<GuildList guilds={guilds} />
|
||||
</PageContainer>
|
||||
);
|
||||
|
||||
export default GuildsPage;
|
||||
@@ -95,7 +95,6 @@ const PlayerPage: React.FC<Props> = ({ player }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
// TODO Should be a custom background and maybe on app level(with the header)
|
||||
<PageContainer>
|
||||
<Flex
|
||||
align="center"
|
||||
|
||||
Reference in New Issue
Block a user