feat: list minted sites (#42)

* feat: add mintes sites list view

* wip: add card but need styles

* style: add style to site card component

* style: add style to site card

* fix: fix onClick propagation

* chore: remove unused param

* Apply suggestions from code review

Co-authored-by: Felipe Mendes <zo.fmendes@gmail.com>

* Update list.tsx

Co-authored-by: Felipe Mendes <zo.fmendes@gmail.com>
This commit is contained in:
Camila Sosa Morales 2022-12-16 11:27:39 -03:00 committed by GitHub
parent 6451208871
commit d96175fa3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 198 additions and 11 deletions

View File

@ -16,7 +16,7 @@ export const CardAttributes = ({ heading, info }: CardAttributesProps) => (
width="200px"
>
<CardBody width="200px">
<TileInfo size="sm" heading={heading} info={info} width={160} />
<TileInfo size="sm" heading={heading} info={info} widthText={160} />
</CardBody>
</Card>
);

View File

@ -0,0 +1,101 @@
import { ImagePreview, TileInfo } from '@/components';
import { SiteNFTDetail } from '@/types';
import { useNavigate } from 'react-router-dom';
import {
Box,
Card,
CardBody,
Heading,
LayoutProps,
Link,
Stack,
} from '@chakra-ui/react';
import React from 'react';
interface CardSiteProps {
site: SiteNFTDetail;
tokenId?: string; // TODO add param and remove optional
}
type InfoContainerProps = {
heading: string;
info: React.ReactNode;
width: LayoutProps['width'];
};
const InfoContainer = ({ heading, info, width }: InfoContainerProps) => (
<TileInfo
size="xs"
direction="row"
mr="5px"
width={width}
heading={heading}
textAlignText="left"
info={info}
/>
);
export const SiteCard: React.FC<CardSiteProps> = ({ site, tokenId }) => {
const { name, owner, image, externalUrl } = site;
const navigate = useNavigate();
return (
<Card
borderColor="#f3f3f36b !important"
boxShadow="1px 10px 24px -2px #85848480"
backgroundColor="#c5c5c50a"
border="1px"
borderRadius="10px"
width="350px"
height="350px"
// TODO add token id param
onClick={() => {
navigate(`/detail?tokenId=${1}`);
}}
>
<CardBody width="350px" height="350px" paddingTop="10px">
<Heading size="md" textAlign="center" marginBottom="10px">
{name}
</Heading>
<Link
href={externalUrl}
isExternal
onClick={(e) => e.stopPropagation()}
>
<Box height="180px">
<ImagePreview
backgroundColor="#161616"
display="block"
marginLeft="auto"
marginRight="auto"
image={image}
objectFit="contain"
width="100%"
height="100%"
borderRadius="20px"
boxShadow="0px 12px 24px -5px #5a575761"
/>
</Box>
</Link>
<Stack mt="10px" spacing="3" overflowY="scroll">
<InfoContainer heading="Owner" info={owner} width="auto" />
{/* TODO add param */}
<InfoContainer heading="Token ID" info="1" width="100px" />
<InfoContainer
heading="External url"
width="100px"
info={
<Link
href={externalUrl}
isExternal
onClick={(e) => e.stopPropagation()}
>
<u>{externalUrl}</u>
</Link>
}
/>
</Stack>
</CardBody>
</Card>
);
};

View File

@ -1,2 +1,3 @@
export * from './card-attributes';
export * from './card-site';

View File

@ -8,22 +8,36 @@ import {
type TileInfoProps = HeadingProps & {
heading: string;
info: string;
width?: number;
info: React.ReactNode;
widthText?: number;
textAlignText?: 'center' | 'left';
direction?: 'column' | 'row';
alignItems?: string;
};
export const TileInfo = forwardRef<TileInfoProps, 'h2'>(
({ heading, info, width = 250, ...headingProps }, ref) => (
<Flex direction="column" alignItems="center">
(
{
heading,
info,
widthText = 250,
textAlignText = 'center',
direction = 'column',
alignItems = 'center',
...headingProps
},
ref
) => (
<Flex direction={direction} alignItems={alignItems}>
<Heading ref={ref} {...headingProps}>
{heading}
</Heading>
<Text
width={width}
width={widthText}
whiteSpace="nowrap"
overflow="hidden"
textOverflow="ellipsis"
textAlign="center"
textAlign={textAlignText}
>
{info}
</Text>

View File

@ -1,3 +1,3 @@
export * from './mint-site';
export * from './detail';
export * from './list';

39
ui/src/mocks/list.ts Normal file
View File

@ -0,0 +1,39 @@
const listSites = [
{
tokenId: 1,
name: 'Fleek Test App',
owner: '0x1b5b3e8a7c245d0f2d2b2e29ba11c03ef086c06e',
description:
'Roronoa Zoro, also known as `Pirate Hunter` Zoro, is the combatant of the Straw Hat Pirates, one of their two swordsmen and one of the Senior Officers of the Straw Hat Grand Fleet. Formerly a bounty hunter, he is the second member of Luffy`s crew and the first to join it, doing so in the Romance Dawn Arc.',
image:
'https://i.seadn.io/gae/Z0t4BsFONk8ebFnTtog3ricAhEpW_ZPhyhxcjHpofCmslJUc5jQ0OjxUuJbU5-3XE0rJZFf6JVdPFZYqtqyg2ri4gAGRpfwkFcidpw4?auto=format&w=1000',
externalUrl: 'https://onepiece.fandom.com/wiki/Roronoa_Zoro',
ens: 'zoro.eth',
commitHash: '6ea6ad16c46ae85faced7e50555ff7368422f57',
githubRepo: 'https://github.com/fleekxyz/contracts',
},
{
tokenId: 2,
name: 'Fleek Test App',
owner: '0x1b5b3e8a7c245d0f2d2b2e29ba11c03ef086c06e',
description:
' Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
image: 'https://storageapi.fleek.co/fleek-team-bucket/site/fleek-logo.png',
externalUrl: 'https://fleek.co',
ens: 'fleek.eth',
commitHash: '6ea6ad16c46ae85faced7e50555ff7368422f57',
githubRepo: 'https://github.com/fleekxyz/contracts',
},
];
export const fetchMintedSites = async () => {
//TODO get minted sites from api
return new Promise((resolved) => {
setTimeout(() => {
resolved({
listSites,
});
}, 2500);
});
};

View File

@ -2,15 +2,16 @@ import React from 'react';
import { Heading, Button } from '@chakra-ui/react';
import { Link } from 'react-router-dom';
import { Flex } from '@chakra-ui/react';
import { ListSites } from './list';
export const Home = () => {
return (
<Flex flexDirection="column" alignItems="center">
<Heading>Welcome to Sites as NFTs by Fleek</Heading>
{/* TODO add list sites */}
<Button as={Link} to="/mint-site" mt={10}>
<Heading marginTop="80px">Welcome to Sites as NFTs by Fleek</Heading>
<Button as={Link} to="/mint-site" mt="20px" mb="50px">
Mint your site
</Button>
<ListSites />
</Flex>
);
};

View File

@ -0,0 +1,31 @@
import React from 'react';
import { Loading } from '@/components';
import { fetchMintedSites } from '@/mocks';
import { SiteNFTDetails } from '@/types';
import { Grid, GridItem } from '@chakra-ui/react';
import { useQuery } from 'react-query';
import { SiteCard } from '@/components';
export const ListSites = () => {
const { data, isLoading } = useQuery<Array<SiteNFTDetails>, Error>(
'fetchSites',
fetchMintedSites
);
if (isLoading) return <Loading />;
return (
<Grid
templateColumns={{ base: 'repeat(4, 1fr)', md: 'repeat(5, 1fr)' }}
gap={10}
mt="40px"
>
{data &&
data.listSites.map((site: SiteNFTDetails) => (
<GridItem key={site.tokenId}>
<SiteCard site={site} />
</GridItem>
))}
</Grid>
);
};