-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from ElvenTools/profile
Profile page
- Loading branch information
Showing
21 changed files
with
3,315 additions
and
2,486 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// After minting an NFT, there is no guarantee that the image thumbnail | ||
// will be immediately available through Elrond API | ||
// This is why we have this helper. It will fallback to the IPFS source using a custom | ||
// IPFS gateway, we take the CID from Elrond's IPFS gateway url here to be sure that we will get it | ||
|
||
import { FC, CSSProperties, PropsWithChildren } from 'react'; | ||
import { Box } from '@chakra-ui/react'; | ||
import Image, { ImageProps } from 'next/image'; | ||
import { customIPFSGateway, elrondIPFSGateway } from '../config/network'; | ||
|
||
const commonImageStyles: CSSProperties = { | ||
objectFit: 'contain', | ||
borderRadius: 10, | ||
}; | ||
|
||
const commonImagesProps = { | ||
sizes: '280px', | ||
height: 280, | ||
width: 280, | ||
priority: true, | ||
style: commonImageStyles, | ||
placeholder: 'blur' as ImageProps['placeholder'], | ||
blurDataURL: | ||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAAEYCAQAAAAthyEHAAAB0ElEQVR42u3SQQ0AAAgEIC+eqaxuBb9ukIH0FJxFGIRBGIRBGIQBYRAGYRAGYRAGhEEYhEEYhEEYEAZhEAZhEAaEQRiEQRiEQRgQBmEQBmEQBmFAGIRBGIRBGIQBYRAGYRAGYUAYhEEYhEEYhAFhEAZhEAZhEAaEQRiEQRiEQRgQBmEQBmEQBoRBGIRBGIRBGBAGYRAGYRAGYUAYhEEYhEEYhBEGYRAGYRAGYUAYhEEYhEEYhAFhEAZhEAZhEAaEQRiEQRiEAWEQBmEQBmEQBoRBGIRBGIRBGBAGYRAGYRAGYUAYhEEYhEEYEAZhEAZhEAZhQBiEQRiEQRiEAWEQBmEQBmEQBoRBGIRBGIQBYRAGYRAGYRAGhEEYhEEYhEEYEAZhEAZhEAZhhEEYhEEYhEEYEAZhEAZhEAZhQBiEQRiEQRiEAWEQBmEQBmFAGIRBGIRBGIQBYRAGYRAGYRAGhEEYhEEYhEEYEAZhEAZhEAaEQRiEQRiEQRgQBmEQBmEQBmFAGIRBGIRBGIQBYRAGYRAGYUAYhEEYhEEYhAFhEAZhEAZhEAaEQRiEQRiEQRhhEAZhEAZhEAaEQRiEQRiEQRgQBmEQBmEQBmFAGIRBGP5YwUTb2T0xhhoAAAAASUVORK5CYII=', | ||
}; | ||
|
||
interface NftImageHelperProps { | ||
thumbnail: string; | ||
elrondIPFSGatewayUrl: string; | ||
href?: string; | ||
} | ||
|
||
const isDefaultThumbnail = (thumbnail: string) => { | ||
return thumbnail.includes('default.png'); | ||
}; | ||
|
||
const getImageUrlFromIPFS = ( | ||
elrondIPFSGatewayUrl: string, | ||
thumbnail: string | ||
) => { | ||
if (elrondIPFSGatewayUrl) { | ||
const CIDandImageFileName = elrondIPFSGatewayUrl.replace( | ||
elrondIPFSGateway, | ||
'' | ||
); | ||
return `${customIPFSGateway}${CIDandImageFileName}`; | ||
} | ||
return thumbnail; | ||
}; | ||
|
||
interface WithHrefProps { | ||
href?: string; | ||
} | ||
|
||
const MaybeWithHref: FC<PropsWithChildren<WithHrefProps>> = ({ | ||
href, | ||
children, | ||
}) => { | ||
if (href) { | ||
return ( | ||
<Box | ||
as="a" | ||
href={href} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
position="relative" | ||
display="block" | ||
> | ||
{children} | ||
</Box> | ||
); | ||
} | ||
return <Box position="relative">{children}</Box>; | ||
}; | ||
|
||
export const NftImageHelper: FC<NftImageHelperProps> = ({ | ||
thumbnail, | ||
elrondIPFSGatewayUrl, | ||
href, | ||
}) => { | ||
return ( | ||
<> | ||
{isDefaultThumbnail(thumbnail) ? ( | ||
<MaybeWithHref href={href}> | ||
<Image | ||
src={getImageUrlFromIPFS(elrondIPFSGatewayUrl, thumbnail)} | ||
alt="" | ||
{...commonImagesProps} | ||
/> | ||
</MaybeWithHref> | ||
) : ( | ||
<MaybeWithHref href={href}> | ||
<Image src={thumbnail} alt="" {...commonImagesProps} /> | ||
</MaybeWithHref> | ||
)} | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { Box, Stack, Spinner, Card, CardBody, Text } from '@chakra-ui/react'; | ||
import Link from 'next/link'; | ||
import { useAccount } from '../hooks/auth/useAccount'; | ||
import { useApiCall } from '../hooks/interaction/useApiCall'; | ||
import { NFT } from '../types/nfts'; | ||
import { SCQueryType } from '../hooks/interaction/useScQuery'; | ||
import { useElvenScQuery } from '../hooks/interaction/elvenScHooks/useElvenScQuery'; | ||
import { NftImageHelper } from './NftImageHelper'; | ||
import { networkConfig, chainType } from '../config/network'; | ||
|
||
const SIZE_PER_PAGE = 10000; | ||
|
||
export const ProfileNFTsList = () => { | ||
const { address } = useAccount(); | ||
|
||
const { data: collectionTicker, isLoading: collectionTickerLoading } = | ||
useElvenScQuery<number>({ | ||
funcName: 'getNftTokenId', | ||
type: SCQueryType.STRING, | ||
}); | ||
|
||
const { data: nfts, isLoading: nftsDataPending } = useApiCall<NFT[]>({ | ||
url: `/accounts/${address}/nfts?collections=${collectionTicker}&size=${SIZE_PER_PAGE}`, | ||
autoInit: Boolean(address) && Boolean(collectionTicker), | ||
}); | ||
|
||
if (nftsDataPending || collectionTickerLoading) { | ||
return ( | ||
<Stack | ||
flex={1} | ||
direction="row" | ||
alignItems="center" | ||
justifyContent="center" | ||
mt={8} | ||
> | ||
<Spinner size="lg" /> | ||
</Stack> | ||
); | ||
} | ||
|
||
if (!nfts || nfts.length === 0) { | ||
return ( | ||
<Box mt={12} textAlign="center"> | ||
<Text>No NFTs minted yet!</Text> | ||
<Link href="/mint"> | ||
<Text textDecoration="underline">Mint some!</Text> | ||
</Link> | ||
</Box> | ||
); | ||
} | ||
|
||
return ( | ||
<> | ||
<Stack | ||
direction="row" | ||
mt={12} | ||
justifyContent="center" | ||
flexWrap="wrap" | ||
gap={6} | ||
spacing={0} | ||
> | ||
{nfts?.map((nft) => ( | ||
<Card | ||
maxW="xs" | ||
minW="xs" | ||
key={nft.identifier} | ||
backgroundColor="elvenTools.dark.darker" | ||
> | ||
<CardBody> | ||
<Stack height={280} position="relative"> | ||
<NftImageHelper | ||
thumbnail={nft.media?.[0].thumbnailUrl} | ||
elrondIPFSGatewayUrl={nft.url} | ||
href={`${networkConfig[chainType].explorerAddress}/nfts/${nft.identifier}`} | ||
/> | ||
</Stack> | ||
<Box | ||
fontWeight={800} | ||
mt={5} | ||
color="elvenTools.white" | ||
textAlign="center" | ||
> | ||
<a | ||
href={`${networkConfig[chainType].explorerAddress}/nfts/${nft.identifier}`} | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
{nft.name} | ||
</a> | ||
</Box> | ||
<Box color="elvenTools.white" textAlign="center"> | ||
<a | ||
href={`${networkConfig[chainType].explorerAddress}/nfts/${nft.identifier}`} | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
{nft.identifier} | ||
</a> | ||
</Box> | ||
</CardBody> | ||
</Card> | ||
))} | ||
</Stack> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { Box, Avatar, Stack, Icon, Tooltip } from '@chakra-ui/react'; | ||
import { BiLink } from 'react-icons/bi'; | ||
import { avatarIdUrl, networkConfig, chainType } from '../config/network'; | ||
import { shortenHash } from '../utils/shortenHash'; | ||
import { Account } from '../types/account'; | ||
import { useApiCall } from '../hooks/interaction/useApiCall'; | ||
import { useAccount } from '../hooks/auth/useAccount'; | ||
|
||
export const ProfileUserData = () => { | ||
const { address } = useAccount(); | ||
|
||
const { data: accountData, isLoading: accountDataPending } = | ||
useApiCall<Account>({ url: `/accounts/${address}` }); | ||
|
||
return ( | ||
<Stack direction="row" justifyContent="center"> | ||
<Stack | ||
direction="column" | ||
alignItems="center" | ||
justifyContent="center" | ||
spacing={0} | ||
> | ||
<Avatar mt={8} size="2xl" src={avatarIdUrl(address)} /> | ||
<Box> | ||
<Box mt={4} fontWeight={900} fontSize={32} display="inline-block"> | ||
{accountData?.username ? ( | ||
<Box>@{accountData?.username}</Box> | ||
) : ( | ||
<Tooltip | ||
bg="elvenTools.dark.darker" | ||
fontWeight="light" | ||
placement="top" | ||
py={3} | ||
px={5} | ||
hasArrow | ||
arrowSize={12} | ||
borderRadius={10} | ||
label={ | ||
'Check Buildo Begins tool on how to get one! (github.com/xdevguild/buildo-begins)' | ||
} | ||
> | ||
<Box> | ||
<a | ||
href="https://github.com/xdevguild/buildo-begins#general-operations" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
{accountDataPending ? '' : 'No herotag!'} | ||
</a> | ||
</Box> | ||
</Tooltip> | ||
)} | ||
</Box> | ||
</Box> | ||
<Box> | ||
<Box display="inline-block"> | ||
<Stack | ||
direction="row" | ||
alignItems="center" | ||
as="a" | ||
href={`${networkConfig[chainType].explorerAddress}/address/${address}`} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
<Tooltip | ||
bg="elvenTools.dark.darker" | ||
fontWeight="light" | ||
placement="top" | ||
py={3} | ||
px={5} | ||
hasArrow | ||
arrowSize={12} | ||
borderRadius={10} | ||
label={address} | ||
> | ||
<Box fontWeight={700} fontSize={22}> | ||
{shortenHash(address, 8)} | ||
</Box> | ||
</Tooltip> | ||
<Icon as={BiLink} w={6} h={6} /> | ||
</Stack> | ||
</Box> | ||
</Box> | ||
</Stack> | ||
</Stack> | ||
); | ||
}; |
Oops, something went wrong.