chore: remove chakra (#86)
* refactor: remove chakra * refactor: remove stitches folder
This commit is contained in:
parent
75a6de5ac7
commit
0553bef914
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../src/theme/stitches';
|
import { dripStitches } from '../src/theme';
|
||||||
import addons from '@storybook/addons';
|
import addons from '@storybook/addons';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { themes } from '@storybook/theming';
|
import { themes } from '@storybook/theming';
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,12 @@
|
||||||
},
|
},
|
||||||
"author": "Fleek",
|
"author": "Fleek",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/icons": "^2.0.13",
|
|
||||||
"@chakra-ui/react": "^2.4.2",
|
|
||||||
"@emotion/react": "^11.10.5",
|
|
||||||
"@emotion/styled": "^11.10.5",
|
|
||||||
"@ethersproject/providers": "^5.7.2",
|
"@ethersproject/providers": "^5.7.2",
|
||||||
"@radix-ui/colors": "^0.1.8",
|
"@radix-ui/colors": "^0.1.8",
|
||||||
"@react-icons/all-files": "^4.1.0",
|
"@react-icons/all-files": "^4.1.0",
|
||||||
"@reduxjs/toolkit": "^1.9.1",
|
"@reduxjs/toolkit": "^1.9.1",
|
||||||
"@stitches/react": "^1.2.8",
|
"@stitches/react": "^1.2.8",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"framer-motion": "^7.6.17",
|
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';
|
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';
|
||||||
import { WalletButton } from './components';
|
|
||||||
import { initializeWallet } from './store';
|
import { initializeWallet } from './store';
|
||||||
import { themeGlobals } from 'theme/stitches/globals';
|
import { themeGlobals } from '@/theme/globals';
|
||||||
import { Home, MintSite, MintedSiteDetail } from './views';
|
import { Home } from './views';
|
||||||
|
|
||||||
initializeWallet();
|
initializeWallet();
|
||||||
|
|
||||||
|
|
@ -10,12 +9,9 @@ export const App = () => {
|
||||||
themeGlobals();
|
themeGlobals();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WalletButton />
|
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/mint-site" element={<MintSite />} />
|
|
||||||
<Route path="/home" element={<Home />} />
|
<Route path="/home" element={<Home />} />
|
||||||
<Route path="/detail" element={<MintedSiteDetail />} />
|
|
||||||
<Route path="*" element={<Navigate to="/home" />} />
|
<Route path="*" element={<Navigate to="/home" />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import {
|
|
||||||
AccordionItem as AccordionItemChakra,
|
|
||||||
AccordionButton,
|
|
||||||
Box,
|
|
||||||
Heading,
|
|
||||||
AccordionIcon,
|
|
||||||
AccordionPanel,
|
|
||||||
AccordionPanelProps,
|
|
||||||
forwardRef,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
type AccordionProps = AccordionPanelProps & {
|
|
||||||
children: React.ReactNode;
|
|
||||||
heading: string;
|
|
||||||
};
|
|
||||||
export const AccordionItem = forwardRef<AccordionProps, 'div'>(
|
|
||||||
({ children, heading, ...panelProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<AccordionItemChakra>
|
|
||||||
<AccordionButton borderBottomWidth="1px">
|
|
||||||
<Box flex="1" textAlign="left">
|
|
||||||
<Heading size="md"> {heading}</Heading>
|
|
||||||
</Box>
|
|
||||||
<AccordionIcon />
|
|
||||||
</AccordionButton>
|
|
||||||
<AccordionPanel ref={ref} {...panelProps} pb={4} overflowY="scroll">
|
|
||||||
{children}
|
|
||||||
</AccordionPanel>
|
|
||||||
</AccordionItemChakra>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './accordion-item';
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import { SiteNFTDetail } from '@/types';
|
|
||||||
import { HStack } from '@chakra-ui/react';
|
|
||||||
import { CardAttributes } from '../card';
|
|
||||||
|
|
||||||
type AttributesDetailProps = {
|
|
||||||
owner: string;
|
|
||||||
attributes: SiteNFTDetail['attributes'];
|
|
||||||
tokendId: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AttributesDetail = ({
|
|
||||||
owner,
|
|
||||||
attributes,
|
|
||||||
tokendId,
|
|
||||||
}: AttributesDetailProps) => {
|
|
||||||
return (
|
|
||||||
<HStack shouldWrapChildren display="inline" spacing="0px">
|
|
||||||
<CardAttributes heading="Owner" info={owner} />
|
|
||||||
{attributes.map(
|
|
||||||
(attribute) =>
|
|
||||||
attribute.value !== '' && (
|
|
||||||
<CardAttributes
|
|
||||||
key={attribute.trait_type}
|
|
||||||
heading={attribute.trait_type}
|
|
||||||
info={attribute.value}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
<CardAttributes heading="Token ID" info={tokendId} />
|
|
||||||
</HStack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './attributes-detail';
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import { Card, CardBody, Tooltip } from '@chakra-ui/react';
|
|
||||||
import { TileInfo } from '../tile-info';
|
|
||||||
|
|
||||||
type CardAttributesProps = {
|
|
||||||
heading: string;
|
|
||||||
info: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CardAttributes = ({ heading, info }: CardAttributesProps) => (
|
|
||||||
<Card
|
|
||||||
mr="10px"
|
|
||||||
mb="5px"
|
|
||||||
direction={{ base: 'column', sm: 'row' }}
|
|
||||||
overflow="hidden"
|
|
||||||
variant="outline"
|
|
||||||
width="200px"
|
|
||||||
>
|
|
||||||
<Tooltip label={info} bg="gray">
|
|
||||||
<CardBody width="200px">
|
|
||||||
<TileInfo size="sm" heading={heading} info={info} widthText={160} />
|
|
||||||
</CardBody>
|
|
||||||
</Tooltip>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
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';
|
|
||||||
import { FleekERC721 } from '@/integrations';
|
|
||||||
import { useQuery } from 'react-query';
|
|
||||||
|
|
||||||
interface CardSiteProps {
|
|
||||||
tokenId: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
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> = ({ tokenId }) => {
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const { data, isLoading } = useQuery<SiteNFTDetail>(
|
|
||||||
`fetchDetail${tokenId}`,
|
|
||||||
() => FleekERC721.tokenMetadata(tokenId)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!data || isLoading) return null;
|
|
||||||
const { name, owner, image, external_url: externalUrl } = data as any;
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
_hover={{ cursor: 'pointer' }}
|
|
||||||
borderColor="custom.white.100 !important"
|
|
||||||
boxShadow="1px 10px 24px -2px #85848480"
|
|
||||||
backgroundColor="custom.white.50"
|
|
||||||
border="1px"
|
|
||||||
borderRadius="10px"
|
|
||||||
width="350px"
|
|
||||||
height="350px"
|
|
||||||
onClick={() => navigate(`/detail?tokenId=${tokenId}`)}
|
|
||||||
>
|
|
||||||
<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="custom.black"
|
|
||||||
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" />
|
|
||||||
<InfoContainer heading="Token ID" info={tokenId} width="100px" />
|
|
||||||
<InfoContainer
|
|
||||||
heading="External url"
|
|
||||||
width="100px"
|
|
||||||
info={
|
|
||||||
<Link
|
|
||||||
href={externalUrl}
|
|
||||||
isExternal
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<u>{externalUrl}</u>
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
export * from './card-attributes';
|
|
||||||
export * from './card-site';
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../../theme/stitches'; //TODO replace with absolute path
|
import { dripStitches } from '../../../theme'; //TODO replace with absolute path
|
||||||
import { Flex, Grid } from '../../layout';
|
import { Flex, Grid } from '../../layout';
|
||||||
|
|
||||||
const { styled } = dripStitches;
|
const { styled } = dripStitches;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../../theme/stitches'; //TODO replace with absolute path
|
import { dripStitches } from '../../../theme'; //TODO replace with absolute path
|
||||||
|
|
||||||
const { styled } = dripStitches;
|
const { styled } = dripStitches;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../../theme/stitches'; //TODO replace with absolute path
|
import { dripStitches } from '../../../theme'; //TODO replace with absolute path
|
||||||
import { Flex, Grid } from '../../layout';
|
import { Flex, Grid } from '../../layout';
|
||||||
|
|
||||||
const { styled } = dripStitches;
|
const { styled } = dripStitches;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../../theme/stitches'; //TODO replace with absolute path
|
import { dripStitches } from '../../../theme'; //TODO replace with absolute path
|
||||||
import React, { HTMLAttributes, useMemo } from 'react';
|
import React, { HTMLAttributes, useMemo } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Flex } from '../../layout';
|
||||||
import { Button } from './button';
|
import { Button } from './button';
|
||||||
import { IconButton } from './icon-button';
|
import { IconButton } from './icon-button';
|
||||||
import { Icon as IconComponent } from '../icon';
|
import { Icon as IconComponent } from '../icon';
|
||||||
import { dripStitches } from '../../../theme/stitches';
|
import { dripStitches } from '../../../theme';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Components/Button',
|
title: 'Components/Button',
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../../theme/stitches';
|
import { dripStitches } from '../../../theme';
|
||||||
import { CSS } from '@stitches/react';
|
import { CSS } from '@stitches/react';
|
||||||
|
|
||||||
type StyledButtonProps = React.ComponentProps<typeof StyledButton>;
|
type StyledButtonProps = React.ComponentProps<typeof StyledButton>;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../../theme/stitches'; //TODO replace for absolute path
|
import { dripStitches } from '../../../theme'; //TODO replace for absolute path
|
||||||
|
|
||||||
const { styled } = dripStitches;
|
const { styled } = dripStitches;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
import { ArrowBackIcon } from '@chakra-ui/icons';
|
|
||||||
import { IconButton } from '@chakra-ui/react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
export const HomeButton = () => {
|
|
||||||
return (
|
|
||||||
<IconButton
|
|
||||||
as={Link}
|
|
||||||
to="/home"
|
|
||||||
aria-label="back home"
|
|
||||||
icon={<ArrowBackIcon />}
|
|
||||||
variant="link"
|
|
||||||
size={'xl'}
|
|
||||||
textDecoration={'none'}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './home-button';
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import { forwardRef, Image, ImageProps } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
type ImagePreviewProps = ImageProps & {
|
|
||||||
image: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ImagePreview = forwardRef<ImagePreviewProps, 'img'>(
|
|
||||||
({ image, ...imageProps }, ref) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* TODO add fallback Image */}
|
|
||||||
<Image
|
|
||||||
ref={ref}
|
|
||||||
src={image}
|
|
||||||
{...imageProps}
|
|
||||||
fallbackSrc="https://via.placeholder.com/150"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './image-preview';
|
|
||||||
|
|
@ -1,10 +1,2 @@
|
||||||
export * from './wallet-button';
|
export * from './core';
|
||||||
export * from './loading';
|
export * from './layout';
|
||||||
export * from './home-button';
|
|
||||||
export * from './image-preview';
|
|
||||||
export * from './tile-info';
|
|
||||||
export * from './card';
|
|
||||||
export * from './accordion-item';
|
|
||||||
export * from './input-field-form';
|
|
||||||
export * from './attributes-detail';
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './input-field-form';
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import {
|
|
||||||
FormControl,
|
|
||||||
FormControlProps,
|
|
||||||
FormErrorMessage,
|
|
||||||
FormLabel,
|
|
||||||
forwardRef,
|
|
||||||
Input,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { Field } from 'formik';
|
|
||||||
|
|
||||||
type InputFieldFormProps = FormControlProps & {
|
|
||||||
label: string;
|
|
||||||
fieldName: string;
|
|
||||||
error?: string;
|
|
||||||
};
|
|
||||||
export const InputFieldForm = forwardRef<InputFieldFormProps, 'div'>(
|
|
||||||
({ label, fieldName, error, ...formControlProps }, ref) => (
|
|
||||||
<FormControl ref={ref} {...formControlProps}>
|
|
||||||
<FormLabel htmlFor={fieldName}>{label}</FormLabel>
|
|
||||||
<Field as={Input} name={fieldName} id={fieldName} type="text" />
|
|
||||||
{error && <FormErrorMessage>{error}</FormErrorMessage>}
|
|
||||||
</FormControl>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../theme/stitches'; //TODO replace with absolute path
|
import { dripStitches } from '../../theme'; //TODO replace with absolute path
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const { styled } = dripStitches;
|
const { styled } = dripStitches;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { dripStitches } from '../../theme/stitches'; //TODO replace with absolute path
|
import { dripStitches } from '../../theme'; //TODO replace with absolute path
|
||||||
|
|
||||||
const { styled } = dripStitches;
|
const { styled } = dripStitches;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './loading';
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
import { Flex, Spinner } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
export const Loading = () => {
|
|
||||||
return (
|
|
||||||
<Flex justifyContent="center" height="80vh" alignItems="center">
|
|
||||||
<Spinner
|
|
||||||
thickness="3px"
|
|
||||||
speed="0.65s"
|
|
||||||
emptyColor="gray.200"
|
|
||||||
color="blue.500"
|
|
||||||
size="xl"
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './tile-info';
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
import {
|
|
||||||
Flex,
|
|
||||||
forwardRef,
|
|
||||||
Heading,
|
|
||||||
HeadingProps,
|
|
||||||
Text,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
|
|
||||||
type TileInfoProps = HeadingProps & {
|
|
||||||
heading: string;
|
|
||||||
info: React.ReactNode;
|
|
||||||
widthText?: number;
|
|
||||||
textAlignText?: 'center' | 'left'; //TODO allow more text alignment types
|
|
||||||
direction?: 'column' | 'row';
|
|
||||||
alignItems?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const TileInfo = forwardRef<TileInfoProps, 'h2'>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
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={widthText}
|
|
||||||
whiteSpace="nowrap"
|
|
||||||
overflow="hidden"
|
|
||||||
textOverflow="ellipsis"
|
|
||||||
textAlign={textAlignText}
|
|
||||||
>
|
|
||||||
{info}
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
export * from './wallet-button';
|
|
||||||
export * from './wallet.utils';
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
import { useCallback } from 'react';
|
|
||||||
import { useAppDispatch, useWalletStore, walletActions } from '@/store';
|
|
||||||
import { contractAddress } from '@/utils';
|
|
||||||
import {
|
|
||||||
Menu,
|
|
||||||
MenuButton,
|
|
||||||
MenuList,
|
|
||||||
MenuItem,
|
|
||||||
Button,
|
|
||||||
Flex,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { Icon } from '../core/icon';
|
|
||||||
import { WalletType } from './wallet.utils';
|
|
||||||
|
|
||||||
const WalletMenu: React.FC = () => {
|
|
||||||
const { account = '', provider } = useWalletStore();
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const handleCopyAccount = useCallback(() => {
|
|
||||||
navigator.clipboard.writeText(account);
|
|
||||||
}, [account]);
|
|
||||||
|
|
||||||
const handleDisconnect = useCallback(() => {
|
|
||||||
dispatch(walletActions.disconnect());
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Menu colorScheme={'custom.gray.200'}>
|
|
||||||
<Button borderRadius="50px" as={MenuButton}>
|
|
||||||
<Flex alignItems={'center'}>
|
|
||||||
<Icon
|
|
||||||
name={WalletType[provider?.toString() as keyof typeof WalletType]}
|
|
||||||
mr="0.5em"
|
|
||||||
/>
|
|
||||||
{contractAddress(account)}
|
|
||||||
</Flex>
|
|
||||||
</Button>
|
|
||||||
<MenuList bg={'custom.gray.200'}>
|
|
||||||
<MenuItem
|
|
||||||
_hover={{ bg: 'custom.gray.100' }}
|
|
||||||
bg={'custom.gray.200'}
|
|
||||||
onClick={handleCopyAccount}
|
|
||||||
>
|
|
||||||
Copy Account
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
_hover={{ bg: 'custom.gray.100' }}
|
|
||||||
bg={'custom.gray.200'}
|
|
||||||
onClick={handleDisconnect}
|
|
||||||
>
|
|
||||||
Disconnect
|
|
||||||
</MenuItem>
|
|
||||||
</MenuList>
|
|
||||||
</Menu>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ConnectionMenu: React.FC = () => {
|
|
||||||
const { state } = useWalletStore();
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const handleConnectWallet = useCallback(() => {
|
|
||||||
dispatch(walletActions.connect('metamask'));
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Menu>
|
|
||||||
<Button
|
|
||||||
borderRadius="50px"
|
|
||||||
as={MenuButton}
|
|
||||||
isLoading={state === 'loading'}
|
|
||||||
disabled={state === 'loading'}
|
|
||||||
>
|
|
||||||
Connect
|
|
||||||
</Button>
|
|
||||||
<MenuList bg={'custom.gray.200'}>
|
|
||||||
<MenuItem
|
|
||||||
_hover={{ bg: 'custom.gray.100' }}
|
|
||||||
bg={'custom.gray.200'}
|
|
||||||
onClick={handleConnectWallet}
|
|
||||||
>
|
|
||||||
Metamask
|
|
||||||
</MenuItem>
|
|
||||||
</MenuList>
|
|
||||||
</Menu>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WalletButton: React.FC = () => {
|
|
||||||
const { state } = useWalletStore();
|
|
||||||
|
|
||||||
if (state === 'connected') {
|
|
||||||
return <WalletMenu />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <ConnectionMenu />;
|
|
||||||
};
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export enum WalletType {
|
|
||||||
metamask = 'metamask',
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +1,32 @@
|
||||||
|
import {
|
||||||
|
amber,
|
||||||
|
amberDark,
|
||||||
|
blue,
|
||||||
|
blueDark,
|
||||||
|
gray,
|
||||||
|
grayDark,
|
||||||
|
green,
|
||||||
|
greenDark,
|
||||||
|
red,
|
||||||
|
redDark,
|
||||||
|
slate,
|
||||||
|
slateDark,
|
||||||
|
} from '@radix-ui/colors';
|
||||||
|
|
||||||
|
//not in usage yet
|
||||||
export const colors = {
|
export const colors = {
|
||||||
custom: {
|
...gray,
|
||||||
gray: {
|
...slate,
|
||||||
100: '#4e4e4e',
|
...blue,
|
||||||
200: '#282824',
|
...red,
|
||||||
},
|
...green,
|
||||||
black: '#161616',
|
...amber,
|
||||||
blue: {
|
};
|
||||||
100: '#1d4ed8',
|
export const darkColors = {
|
||||||
},
|
...grayDark,
|
||||||
white: {
|
...slateDark,
|
||||||
50: '#c5c5c50a',
|
...blueDark,
|
||||||
100: '#f3f3f36b',
|
...redDark,
|
||||||
},
|
...greenDark,
|
||||||
},
|
...amberDark,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1 +1,8 @@
|
||||||
|
export * from './media';
|
||||||
export * from './colors';
|
export * from './colors';
|
||||||
|
export * from './radii';
|
||||||
|
export * from './shadows';
|
||||||
|
export * from './sizes';
|
||||||
|
export * from './spacing';
|
||||||
|
export * from './typography';
|
||||||
|
export * from './z-indices';
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,2 @@
|
||||||
import { extendTheme } from '@chakra-ui/react';
|
export * from './themes';
|
||||||
import { colors } from './foundations';
|
export * from './foundations';
|
||||||
|
|
||||||
const appTheme = {
|
|
||||||
styles: {
|
|
||||||
global: {
|
|
||||||
body: {
|
|
||||||
color: 'rgba(255, 255, 255)',
|
|
||||||
bg: 'custom.black',
|
|
||||||
margin: '25px 50px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fonts: {
|
|
||||||
heading: 'Nunito Sans,Helvetica,Arial,Lucida,sans-serif',
|
|
||||||
body: 'Nunito Sans,Helvetica,Arial,Lucida,sans-serif',
|
|
||||||
},
|
|
||||||
sizes: {
|
|
||||||
modalHeight: '345px',
|
|
||||||
},
|
|
||||||
colors,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const theme = extendTheme(appTheme);
|
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
import {
|
|
||||||
amber,
|
|
||||||
amberDark,
|
|
||||||
blue,
|
|
||||||
blueDark,
|
|
||||||
gray,
|
|
||||||
grayDark,
|
|
||||||
green,
|
|
||||||
greenDark,
|
|
||||||
red,
|
|
||||||
redDark,
|
|
||||||
slate,
|
|
||||||
slateDark,
|
|
||||||
} from '@radix-ui/colors';
|
|
||||||
|
|
||||||
//not in usage yet
|
|
||||||
export const colors = {
|
|
||||||
...gray,
|
|
||||||
...slate,
|
|
||||||
...blue,
|
|
||||||
...red,
|
|
||||||
...green,
|
|
||||||
...amber,
|
|
||||||
};
|
|
||||||
export const darkColors = {
|
|
||||||
...grayDark,
|
|
||||||
...slateDark,
|
|
||||||
...blueDark,
|
|
||||||
...redDark,
|
|
||||||
...greenDark,
|
|
||||||
...amberDark,
|
|
||||||
};
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
export * from './media';
|
|
||||||
export * from './colors';
|
|
||||||
export * from './radii';
|
|
||||||
export * from './shadows';
|
|
||||||
export * from './sizes';
|
|
||||||
export * from './spacing';
|
|
||||||
export * from './typography';
|
|
||||||
export * from './z-indices';
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
export * from './themes';
|
|
||||||
export * from './foundations';
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { createStitches, DefaultThemeMap } from '@stitches/react';
|
import { createStitches, DefaultThemeMap } from '@stitches/react';
|
||||||
import type { ConfigType } from '@stitches/react/types/config';
|
import type { ConfigType } from '@stitches/react/types/config';
|
||||||
|
|
||||||
import { allToNegative } from '../../utils';
|
import { allToNegative } from '../utils';
|
||||||
import {
|
import {
|
||||||
colors,
|
colors,
|
||||||
darkColors,
|
darkColors,
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
import { useSearchParams } from 'react-router-dom';
|
|
||||||
import { useQuery } from 'react-query';
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
Box,
|
|
||||||
Card,
|
|
||||||
CardBody,
|
|
||||||
Flex,
|
|
||||||
Heading,
|
|
||||||
Link,
|
|
||||||
VStack,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import {
|
|
||||||
HomeButton,
|
|
||||||
ImagePreview,
|
|
||||||
AccordionItem,
|
|
||||||
Loading,
|
|
||||||
AttributesDetail,
|
|
||||||
} from '@/components';
|
|
||||||
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
|
||||||
import { ErrorScreen } from '@/views';
|
|
||||||
import { SiteNFTDetail } from '@/types';
|
|
||||||
import { FleekERC721 } from '@/integrations';
|
|
||||||
|
|
||||||
export const MintedSiteDetail = () => {
|
|
||||||
const [searchParams] = useSearchParams();
|
|
||||||
const tokenIdParam = searchParams.get('tokenId');
|
|
||||||
//TODO handle response type
|
|
||||||
const { data, status } = useQuery<SiteNFTDetail>(
|
|
||||||
`fetchDetail${tokenIdParam}`,
|
|
||||||
async () => FleekERC721.tokenMetadata(Number(tokenIdParam))
|
|
||||||
);
|
|
||||||
|
|
||||||
if (status === 'loading') {
|
|
||||||
return <Loading />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status === 'error') {
|
|
||||||
return <ErrorScreen />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { owner, name, description, image, externalUrl, attributes } =
|
|
||||||
data as SiteNFTDetail;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Flex width="full" align="center" justifyContent="center" mt="30px">
|
|
||||||
<Box width={{ base: '100%' }}>
|
|
||||||
<HomeButton />
|
|
||||||
<Box
|
|
||||||
flexDirection="row"
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-evenly"
|
|
||||||
mt={10}
|
|
||||||
>
|
|
||||||
<Box mr={5}>
|
|
||||||
<Box
|
|
||||||
display="flex"
|
|
||||||
flexDirection="row"
|
|
||||||
alignItems="flex-end"
|
|
||||||
mb={5}
|
|
||||||
>
|
|
||||||
<Heading mr={5}>{name}</Heading>
|
|
||||||
</Box>
|
|
||||||
<Card backgroundColor="transparent" border="1px">
|
|
||||||
<CardBody padding="1px 8px 10px 8px">
|
|
||||||
<Accordion defaultIndex={[0, 1]} allowMultiple width="45vw">
|
|
||||||
<AccordionItem
|
|
||||||
heading="Description"
|
|
||||||
minH={120}
|
|
||||||
maxH="auto"
|
|
||||||
children={
|
|
||||||
<p
|
|
||||||
style={{
|
|
||||||
whiteSpace: 'pre-line',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<AccordionItem
|
|
||||||
heading="Attributes"
|
|
||||||
children={
|
|
||||||
<AttributesDetail
|
|
||||||
owner={owner}
|
|
||||||
attributes={attributes}
|
|
||||||
tokendId={tokenIdParam as string}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
padding="16px"
|
|
||||||
/>
|
|
||||||
</Accordion>
|
|
||||||
<Box ml={5} mt={2}>
|
|
||||||
<Link href={externalUrl} isExternal>
|
|
||||||
Visit site <ExternalLinkIcon mx="2px" />
|
|
||||||
</Link>
|
|
||||||
</Box>
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
</Box>
|
|
||||||
<VStack alignItems="flex-start">
|
|
||||||
<Box
|
|
||||||
border="1px"
|
|
||||||
width="-webkit-fill-available"
|
|
||||||
padding="5px 10px"
|
|
||||||
borderTopRadius={10}
|
|
||||||
>
|
|
||||||
<Heading size="md">Preview</Heading>
|
|
||||||
</Box>
|
|
||||||
<Box
|
|
||||||
mt="0px !important"
|
|
||||||
boxSize="md"
|
|
||||||
border="1px"
|
|
||||||
padding={10}
|
|
||||||
borderRadius={20}
|
|
||||||
borderTopRadius={0}
|
|
||||||
boxShadow="12px 10px 14px 6px #868686d1"
|
|
||||||
>
|
|
||||||
<ImagePreview
|
|
||||||
image={image}
|
|
||||||
width="auto"
|
|
||||||
height="auto"
|
|
||||||
maxW="100%"
|
|
||||||
maxH="100%"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './detail';
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
import { Flex, Heading } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
export const ErrorScreen = () => {
|
|
||||||
return (
|
|
||||||
<Flex justifyContent="center" height="80vh" alignItems="center">
|
|
||||||
<Heading size="md">Something went wrong</Heading>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export * from './error-screen';
|
|
||||||
|
|
@ -1,18 +1,10 @@
|
||||||
import React from 'react';
|
import { Flex } from '@/components';
|
||||||
import { Heading, Button } from '@chakra-ui/react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Flex } from '@chakra-ui/react';
|
export const Home = () => {
|
||||||
import { ListSites } from './list';
|
return (
|
||||||
|
<Flex css={{ justifyContent: 'center' }}>
|
||||||
export const Home = () => {
|
<h1>Home</h1>
|
||||||
return (
|
</Flex>
|
||||||
<Flex flexDirection="column" alignItems="center">
|
);
|
||||||
<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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1 @@
|
||||||
export * from './home';
|
export * from './home';
|
||||||
export * from './mint-site';
|
|
||||||
export * from './detail';
|
|
||||||
export * from './error-screen';
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
export * from './mint-site';
|
|
||||||
export * from './mint-site.utils';
|
|
||||||
|
|
@ -1,262 +0,0 @@
|
||||||
import React, { useCallback } from 'react';
|
|
||||||
import {
|
|
||||||
Heading,
|
|
||||||
Flex,
|
|
||||||
Box,
|
|
||||||
FormControl,
|
|
||||||
FormLabel,
|
|
||||||
Button,
|
|
||||||
FormErrorMessage,
|
|
||||||
Textarea,
|
|
||||||
Grid,
|
|
||||||
GridItem,
|
|
||||||
VStack,
|
|
||||||
InputGroup,
|
|
||||||
Input,
|
|
||||||
InputRightElement,
|
|
||||||
InputProps,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { Formik, Field, useFormikContext } from 'formik';
|
|
||||||
import { getRepoAndCommit } from '@/utils';
|
|
||||||
import { validateFields } from './mint-site.utils';
|
|
||||||
import { HomeButton, InputFieldForm } from '@/components';
|
|
||||||
import { FleekERC721 } from '@/integrations';
|
|
||||||
import { useWalletStore } from '@/store';
|
|
||||||
import { useToast } from '@/hooks';
|
|
||||||
|
|
||||||
interface FormValues {
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
githubCommit: string;
|
|
||||||
ownerAddress: string;
|
|
||||||
externalUrl: string;
|
|
||||||
image: string;
|
|
||||||
ens?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialValues = {
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
githubCommit: '',
|
|
||||||
ownerAddress: '',
|
|
||||||
externalUrl: '',
|
|
||||||
image: '',
|
|
||||||
ens: '',
|
|
||||||
} as FormValues;
|
|
||||||
|
|
||||||
const OwnerAdress = (props: InputProps) => {
|
|
||||||
const { setFieldValue } = useFormikContext();
|
|
||||||
|
|
||||||
const handlePasteAddress = () => {
|
|
||||||
if (setFieldValue && props.name) {
|
|
||||||
navigator.clipboard
|
|
||||||
.readText()
|
|
||||||
.then((text) => setFieldValue(props.name as string, text));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<InputGroup size="md">
|
|
||||||
<Input {...props} pr="4.5rem" />
|
|
||||||
<InputRightElement width="4.5rem">
|
|
||||||
<Button h="1.75rem" size="sm" onClick={handlePasteAddress}>
|
|
||||||
Paste
|
|
||||||
</Button>
|
|
||||||
</InputRightElement>
|
|
||||||
</InputGroup>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MintSite = () => {
|
|
||||||
const setToastInfo = useToast();
|
|
||||||
const { provider } = useWalletStore();
|
|
||||||
|
|
||||||
const handleSubmitForm = useCallback(
|
|
||||||
async (values: FormValues) => {
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
githubCommit,
|
|
||||||
ownerAddress,
|
|
||||||
externalUrl,
|
|
||||||
image,
|
|
||||||
ens,
|
|
||||||
} = values;
|
|
||||||
|
|
||||||
const { repo, commit_hash } = getRepoAndCommit(githubCommit);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!provider) throw new Error('No provider found');
|
|
||||||
await FleekERC721.mint(
|
|
||||||
{
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
owner: ownerAddress,
|
|
||||||
externalUrl,
|
|
||||||
image,
|
|
||||||
ens,
|
|
||||||
commitHash: commit_hash,
|
|
||||||
repo,
|
|
||||||
},
|
|
||||||
provider
|
|
||||||
);
|
|
||||||
setToastInfo({
|
|
||||||
title: 'Success!',
|
|
||||||
description: 'Your site has been minted.',
|
|
||||||
status: 'success',
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
setToastInfo({
|
|
||||||
title: 'Error!',
|
|
||||||
description:
|
|
||||||
'We had an error while minting your site. Please try again later',
|
|
||||||
status: 'error',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[provider]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Flex width="full" align="center" justifyContent="center" mt="30px">
|
|
||||||
<Box width={{ base: '100%' }}>
|
|
||||||
<HomeButton />
|
|
||||||
<VStack spacing="10px">
|
|
||||||
<Box textAlign="center" mt={2}>
|
|
||||||
<Heading>Mint your Site</Heading>
|
|
||||||
</Box>
|
|
||||||
<Box textAlign="left" width="80%" justifyContent="center">
|
|
||||||
<Formik
|
|
||||||
validate={validateFields}
|
|
||||||
initialValues={initialValues}
|
|
||||||
onSubmit={handleSubmitForm}
|
|
||||||
>
|
|
||||||
{({ values, touched, handleSubmit, isSubmitting, errors }) => (
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<Box
|
|
||||||
display="flex"
|
|
||||||
flexDirection={{ base: 'column', md: 'row' }}
|
|
||||||
>
|
|
||||||
<InputFieldForm
|
|
||||||
label="Name"
|
|
||||||
fieldName="name"
|
|
||||||
mr={5}
|
|
||||||
error={errors.name}
|
|
||||||
isInvalid={!!errors.name && touched.name}
|
|
||||||
isRequired
|
|
||||||
/>
|
|
||||||
<FormControl
|
|
||||||
isRequired
|
|
||||||
isInvalid={
|
|
||||||
!!errors.ownerAddress && touched.ownerAddress
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FormLabel htmlFor="ownerAddress">
|
|
||||||
Owner address
|
|
||||||
</FormLabel>
|
|
||||||
<Field
|
|
||||||
as={OwnerAdress}
|
|
||||||
name="ownerAddress"
|
|
||||||
id="ownerAddress"
|
|
||||||
/>
|
|
||||||
{errors.ownerAddress && (
|
|
||||||
<FormErrorMessage>
|
|
||||||
{errors.ownerAddress}
|
|
||||||
</FormErrorMessage>
|
|
||||||
)}
|
|
||||||
</FormControl>
|
|
||||||
</Box>
|
|
||||||
<FormControl
|
|
||||||
mt={6}
|
|
||||||
isRequired
|
|
||||||
isInvalid={!!errors.description && touched.description}
|
|
||||||
>
|
|
||||||
<FormLabel htmlFor="description">Description</FormLabel>
|
|
||||||
<Field
|
|
||||||
as={Textarea}
|
|
||||||
name="description"
|
|
||||||
id="description"
|
|
||||||
/>
|
|
||||||
{errors.description && (
|
|
||||||
<FormErrorMessage>
|
|
||||||
{errors.description}
|
|
||||||
</FormErrorMessage>
|
|
||||||
)}
|
|
||||||
</FormControl>
|
|
||||||
<Box
|
|
||||||
display="flex"
|
|
||||||
flexDirection={{ base: 'column', md: 'row' }}
|
|
||||||
mt={6}
|
|
||||||
>
|
|
||||||
<InputFieldForm
|
|
||||||
label="Image (IPFS Link)"
|
|
||||||
fieldName="image"
|
|
||||||
mr={5}
|
|
||||||
error={errors.image}
|
|
||||||
isInvalid={!!errors.image && touched.image}
|
|
||||||
isRequired
|
|
||||||
/>
|
|
||||||
<InputFieldForm
|
|
||||||
label="External url"
|
|
||||||
fieldName="externalUrl"
|
|
||||||
error={errors.externalUrl}
|
|
||||||
isInvalid={!!errors.externalUrl && touched.externalUrl}
|
|
||||||
isRequired
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Grid
|
|
||||||
templateColumns={{
|
|
||||||
md: 'repeat(3, 1fr)',
|
|
||||||
}}
|
|
||||||
gap={4}
|
|
||||||
mt={6}
|
|
||||||
>
|
|
||||||
<GridItem colSpan={2}>
|
|
||||||
<InputFieldForm
|
|
||||||
label="Github commit url"
|
|
||||||
fieldName="githubCommit"
|
|
||||||
mr={5}
|
|
||||||
error={errors.githubCommit}
|
|
||||||
isInvalid={
|
|
||||||
!!errors.githubCommit && touched.githubCommit
|
|
||||||
}
|
|
||||||
isRequired
|
|
||||||
/>
|
|
||||||
</GridItem>
|
|
||||||
<GridItem colSpan={{ base: 2, md: 1 }}>
|
|
||||||
<InputFieldForm label="ENS" fieldName="ens" />
|
|
||||||
</GridItem>
|
|
||||||
</Grid>
|
|
||||||
<Button
|
|
||||||
colorScheme="blue"
|
|
||||||
backgroundColor="custom.blue.100"
|
|
||||||
width="full"
|
|
||||||
mt={4}
|
|
||||||
type="submit"
|
|
||||||
isLoading={isSubmitting}
|
|
||||||
loadingText="Minting..."
|
|
||||||
disabled={
|
|
||||||
isSubmitting ||
|
|
||||||
!values.name ||
|
|
||||||
!values.description ||
|
|
||||||
!values.githubCommit ||
|
|
||||||
!values.ownerAddress ||
|
|
||||||
!values.image ||
|
|
||||||
!values.externalUrl ||
|
|
||||||
!provider
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Mint
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</Box>
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
import { isValidImageUrl, isValidUrl } from '@/utils';
|
|
||||||
import { ethers } from 'ethers';
|
|
||||||
import { FormikValues } from 'formik';
|
|
||||||
|
|
||||||
export const validateFields = (values: FormikValues) => {
|
|
||||||
const errors: FormikValues = {};
|
|
||||||
if (!values.name) {
|
|
||||||
errors.name = 'Name cannot be empty';
|
|
||||||
}
|
|
||||||
if (!values.description) {
|
|
||||||
errors.description = 'Description cannot be empty';
|
|
||||||
}
|
|
||||||
if (!values.githubCommit) {
|
|
||||||
errors.githubCommit = 'Github commit cannot be empty';
|
|
||||||
} else if (!isValidUrl(values.githubCommit)) {
|
|
||||||
errors.githubCommit = 'Github commit is not a valid url';
|
|
||||||
}
|
|
||||||
if (!values.ownerAddress) {
|
|
||||||
errors.ownerAddress = 'Owner address cannot be empty';
|
|
||||||
} else if (!ethers.utils.isAddress(values.ownerAddress)) {
|
|
||||||
errors.ownerAddress = 'Owner address is not a valid address';
|
|
||||||
}
|
|
||||||
if (!values.externalUrl) {
|
|
||||||
errors.externalUrl = 'External url cannot be empty';
|
|
||||||
} else if (!isValidUrl(values.externalUrl)) {
|
|
||||||
errors.externalUrl = 'External url is not a valid url';
|
|
||||||
}
|
|
||||||
if (!values.image) {
|
|
||||||
errors.image = 'Image cannot be empty';
|
|
||||||
} else if (!isValidImageUrl(values.image)) {
|
|
||||||
errors.image = 'Image url is not a valid url';
|
|
||||||
}
|
|
||||||
//TODO check if ENS is a valid ens name
|
|
||||||
return errors;
|
|
||||||
};
|
|
||||||
1147
ui/yarn.lock
1147
ui/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue