├── .env.local.example ├── .gitignore ├── .storybook ├── main.js └── preview.js ├── .vscode └── settings.json ├── README.md ├── TODO ├── components ├── airdropBanner │ ├── airdrop.module.css │ └── index.tsx ├── anchor │ └── index.tsx ├── artistCard │ └── ArtistCard.tsx ├── button │ └── index.tsx ├── button2 │ └── index.tsx ├── button3 │ └── index.tsx ├── button4 │ └── index.tsx ├── buyOutCard │ └── index.tsx ├── chainWarning │ └── index.tsx ├── dropdown │ └── index.tsx ├── footer │ └── index.tsx ├── fraktalButton │ └── index.tsx ├── fraktionOwners │ └── index.tsx ├── fraktionsDetail │ └── index.tsx ├── fraktionsList │ └── index.tsx ├── header │ └── index.tsx ├── icon │ ├── DiscordIcon.tsx │ ├── InstagramIcon.tsx │ ├── MediumIcon.tsx │ ├── TwitterIcon.tsx │ └── YoutubeIcon.tsx ├── infiniteScrollNft │ └── index.tsx ├── layout │ └── index.tsx ├── limitedInput │ └── index.tsx ├── listCard │ └── index.tsx ├── listCardAuction │ └── index.tsx ├── load-screens │ ├── index.tsx │ └── loaders.module.css ├── media │ └── index.tsx ├── modal │ └── index.tsx ├── newNFTHeader │ └── index.tsx ├── nft-auction-item │ └── index.tsx ├── nft-importcard-opensea │ └── index.tsx ├── nft-item-manager │ └── index.tsx ├── nft-item-opensea │ └── index.tsx ├── nft-item │ └── index.tsx ├── nftCard │ └── index.tsx ├── offerDetail │ └── index.tsx ├── pagination │ └── index.tsx ├── rescueCard │ └── index.tsx ├── revenuesDetail │ └── index.tsx ├── revenuesList │ └── index.tsx ├── search │ ├── index.tsx │ └── styles.css ├── tabsCard │ ├── index.tsx │ └── tabsCard.module.css ├── useENSAddress.ts ├── userOwnership │ └── index.tsx └── verifyNFT │ └── index.tsx ├── constants └── routes.ts ├── contexts ├── NFTIsMintingContext.tsx ├── Web3Context.tsx ├── dataContext.tsx └── userContext.tsx ├── default.js ├── hooks ├── externalContractLoader.js ├── useLoadingScreen.ts └── useMarketplace.ts ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── 404.tsx ├── _app.tsx ├── api │ └── hello.ts ├── artist │ ├── [...slug].tsx │ └── artist.module.css ├── artists.tsx ├── claim-bonus.tsx ├── claim.tsx ├── explore.tsx ├── import-nft.tsx ├── import-nft │ └── [...slug].tsx ├── import-nfts.tsx ├── index.tsx ├── list-nft.tsx ├── mint-nft.tsx ├── mintPage.tsx ├── my-nfts.tsx ├── nft │ └── [id] │ │ ├── auction.module.css │ │ ├── auction.tsx │ │ ├── closed.module.css │ │ ├── closed.tsx │ │ ├── details.tsx │ │ ├── fix-price-sale.tsx │ │ ├── list-item.tsx │ │ ├── manage.module.css │ │ └── manage.tsx └── rewards.tsx ├── public ├── close.svg ├── doge.svg ├── eth.png ├── eth.svg ├── favicon.ico ├── filler-image-1.png ├── filler-image-2.png ├── footer │ ├── discord.svg │ ├── icons8-discord.svg │ ├── icons8-instagram.svg │ ├── icons8-medium.svg │ ├── icons8-twitter.svg │ ├── medium.svg │ └── twitter.svg ├── fraktal-full-logo.png ├── images │ ├── 404_OhFrak.png │ └── Logo.png ├── info.svg ├── logo-wide.svg ├── logo.svg ├── nft-loading-card.svg ├── outlinedClose.png ├── sample-item.png ├── search.svg ├── timer.png └── trash.svg ├── redux ├── actions │ └── contractActions.ts ├── reducers │ ├── index.ts │ └── loadingScreenReducer.ts └── store.ts ├── stories ├── Button.stories.tsx ├── Button.tsx ├── Header.stories.tsx ├── Header.tsx ├── Introduction.stories.mdx ├── NFTDetailRevenue.stories.tsx ├── NFTDetails.tsx ├── Page.stories.tsx ├── Page.tsx ├── assets │ ├── code-brackets.svg │ ├── colors.svg │ ├── comments.svg │ ├── direction.svg │ ├── flow.svg │ ├── plugin.svg │ ├── repo.svg │ └── stackalt.svg ├── button.css ├── header.css └── page.css ├── styles ├── artists.module.css ├── fonts.css ├── globals.css ├── landing.module.css ├── mint-nft.module.css ├── my-nfts.module.css └── rewards.module.css ├── testnetfraktalauction ├── .gitignore ├── abis │ ├── Contract.json │ └── Factory.json ├── build │ ├── Contract │ │ ├── Contract.wasm │ │ └── abis │ │ │ └── Contract.json │ ├── Factory │ │ └── abis │ │ │ └── Factory.json │ ├── schema.graphql │ ├── subgraph.yaml │ └── templates │ │ └── Factory │ │ └── Factory.wasm ├── generated │ ├── Contract │ │ └── Contract.ts │ ├── schema.ts │ ├── templates.ts │ └── templates │ │ └── Factory │ │ └── Factory.ts ├── package.json ├── schema.graphql ├── src │ ├── mapping.ts │ └── mappings │ │ └── factory.ts ├── subgraph.yaml ├── tsconfig.json └── yarn.lock ├── tsconfig.json ├── types.ts ├── types └── workflow.ts ├── utils ├── alchemy.ts ├── constants.ts ├── contractCalls.ts ├── format.ts ├── graphQueries.js ├── helpers.ts ├── math.ts ├── merkleTreeProofs.json ├── merkleTreeProofsV2.json ├── nftHelpers.js ├── openSeaAPI.ts ├── pinataPinner.js ├── proofsGetter.js ├── search.ts └── stores │ ├── ensStore.ts │ └── queries │ └── getQueryENSForETHAddress.ts └── yarn.lock /.env.local.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_INFURA_ID="" 2 | NEXT_PUBLIC_INFURA_PROJECT_ID="" 3 | NEXT_PUBLIC_INFURA_PROJECT_SECRET="" 4 | NEXT_PUBLIC_RINKEBY_MARKET_CONTRACT="" 5 | NEXT_PUBLIC_RINKEBY_FACTORY_CONTRACT="" 6 | NEXT_PUBLIC_GRAPHQL_URL="" 7 | NEXT_PUBLIC_NETWORK_CHAIN_ID=4 8 | NEXT_PUBLIC_PINATA_API_KEY="" 9 | NEXT_PUBLIC_PINATA_API_SECRET="" 10 | NEXT_PUBLIC_ALCHEMY_API_KEY= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | .idea 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env 30 | .env.local 31 | .env.development.local 32 | .env.test.local 33 | .env.production.local 34 | 35 | # vercel 36 | .vercel 37 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "stories": [ 3 | "../stories/**/*.stories.mdx", 4 | "../stories/**/*.stories.@(js|jsx|ts|tsx)" 5 | ], 6 | "addons": [ 7 | "@storybook/addon-links", 8 | "@storybook/addon-essentials" 9 | ] 10 | } -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | export const parameters = { 2 | actions: { argTypesRegex: "^on[A-Z].*" }, 3 | controls: { 4 | matchers: { 5 | color: /(background|color)$/i, 6 | date: /Date$/, 7 | }, 8 | }, 9 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.arrowParens": "avoid", 3 | "prettier.singleQuote": false, 4 | "prettier.bracketSpacing": true, 5 | "prettier.tabWidth": 2 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 16 | 17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. 18 | 19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODO:: 2 | -------------------------------------------------------------------------------- 3 | 4 | BUGS: 5 | 6 | 7 | 8 | CONTRACTS: 9 | ------------------------------------------------------------------------------------------------ 10 | - User can unlock and keep voting, but result is taken from total locked attribute 11 | - Opensea assets in rinkeby have id > uint256 !! they fail on import (overflow) 12 | 13 | AUDITORY: 14 | ------------------------------------------------------------------------------------------------ 15 | REMEMBER CHECK EFFECT INTERACTIONS PATTERN :D 16 | FraktalMarket: 17 | - Replace transfer() for AddressUpgradeable.sendValue() in: 18 | -withdrawAccruedFees() 19 | -rescueEth() 20 | -makeOffer() 21 | -createRevenuePayment() 22 | 23 | - setMajority() does not check max value (10000 = 100%) 24 | - setFee() does not check max value (10000 = 100%) 25 | - setFee() uses >= 0 for a uint16 (never negative) 26 | 27 | FraktalMarket, FraktalNFT, PaymentSplitterUpgradeable > check only externally called functions. 28 | -external> public visibility 29 | 30 | This is just a formal revision of patterns. Not an analysis of the program. 31 | 32 | UI 33 | ------------------------------------------------------------------------------------------------ 34 | - Opensea API is veery slow to detect transfers 35 | - There is no tx handler (besides metamask) 36 | - Incorrect networks does not work very well, does not detect network change (add listener) 37 | - Does detect account change.. but is buggy.. 38 | 39 | SUBGRAPH 40 | ------------------------------------------------------------------------------------------------ 41 | -------------------------------------------------------------------------------- /components/airdropBanner/airdrop.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 964px; 3 | height: 80px; 4 | background: #FFFFFF; 5 | border: 1px solid #C387FF; 6 | box-sizing: border-box; 7 | box-shadow: 0px 1px 4px rgba(64, 84, 102, 0.04), 0px 4px 12px rgba(64, 84, 102, 0.08); 8 | border-radius: 4px; 9 | } 10 | .container div { 11 | 12 | } 13 | .airdropTitle { 14 | font-style: normal; 15 | font-weight: 600; 16 | font-size: 16px; 17 | line-height: 24px; 18 | } 19 | .subtitle { 20 | font-size:14px; 21 | line-height: 20px; 22 | } 23 | .airdropButton { 24 | font-size: 14px; 25 | width: 160px; 26 | height: 40px; 27 | background: #985CFF; 28 | border-radius: 24px; 29 | align-items: center; 30 | padding: 12px 24px; 31 | } -------------------------------------------------------------------------------- /components/airdropBanner/index.tsx: -------------------------------------------------------------------------------- 1 | import {Box, Button, Spacer, Flex, Stack, HStack, VStack, Text} from "@chakra-ui/react"; 2 | import styles from "./airdrop.module.css"; 3 | 4 | /** 5 | * Airdrop Banner 6 | * @param {any} title 7 | * @param {any} subtitle 8 | * @param {any} onClick 9 | * @param {any} buttonText 10 | * @param {any} icon 11 | * @returns {any} 12 | * @constructor 13 | */ 14 | const AirdropBanner = ({title, subtitle = '', onClick, buttonText, icon}) => { 15 | 16 | return ( 17 | 18 | 19 | 20 | {icon} 21 | 22 | 23 | 24 |

{title}

25 |
26 | {subtitle && ( 27 | 28 | {subtitle} 29 | 30 | )} 31 |
32 | 33 | 34 | 42 | 43 |
44 |
45 | ); 46 | }; 47 | 48 | export default AirdropBanner; -------------------------------------------------------------------------------- /components/anchor/index.tsx: -------------------------------------------------------------------------------- 1 | import NextLink from "next/link"; 2 | const Anchor = ({ href, passHref, target, children }) => { 3 | return ( 4 | 5 | 6 | {children} 7 | 8 | 9 | ) 10 | }; 11 | export default Anchor; -------------------------------------------------------------------------------- /components/artistCard/ArtistCard.tsx: -------------------------------------------------------------------------------- 1 | import { Box } from "@chakra-ui/react"; 2 | 3 | export default function ArtistCard(props) { 4 | return ( 5 | <> 6 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /components/button/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonProps } from "@chakra-ui/button"; 2 | import { forwardRef } from "react"; 3 | 4 | const FrakButton = forwardRef< 5 | HTMLButtonElement, 6 | ButtonProps & { isOutlined?: boolean } 7 | >(({ isOutlined, children, ...rest }, ref) => { 8 | return ( 9 | 26 | ); 27 | }); 28 | 29 | export default FrakButton; 30 | -------------------------------------------------------------------------------- /components/button2/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonProps } from '@chakra-ui/button'; 2 | import { Input, Text } from '@chakra-ui/react'; 3 | import { forwardRef } from 'react'; 4 | 5 | const FrakButton2 = forwardRef< 6 | HTMLButtonElement, 7 | ButtonProps & { 8 | isReady?: boolean; 9 | setFunction: Function; 10 | inputPlaceholder: string; 11 | currency: string; 12 | } 13 | >( 14 | ({ 15 | isReady, 16 | onClick, 17 | setFunction, 18 | inputPlaceholder, 19 | currency, 20 | children, 21 | ...rest 22 | }) => { 23 | return ( 24 |
35 | setFunction(d.target.value)} 37 | placeholder={inputPlaceholder ? inputPlaceholder : null} 38 | _focus={{ outline: 'none' }} 39 | style={{ 40 | textAlign: 'right', 41 | color: '#000000', 42 | fontWeight: 500, 43 | fontSize: '20px', 44 | outline: `none`, 45 | border: `none`, 46 | borderRadius: `15px 0px 0px 15px`, 47 | height: `38px`, 48 | minWidth: '20%', 49 | marginRight: `0px`, 50 | }} 51 | /> 52 |
53 | 67 | {currency ? currency : null} 68 | 69 |
70 | 99 |
100 | ); 101 | } 102 | ); 103 | 104 | export default FrakButton2; 105 | -------------------------------------------------------------------------------- /components/button3/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonProps } from '@chakra-ui/button'; 2 | import { Input, Box, Text } from '@chakra-ui/react'; 3 | import { forwardRef } from 'react'; 4 | 5 | const FrakButton3 = forwardRef< 6 | HTMLButtonElement, 7 | ButtonProps & { 8 | isReady?: boolean; 9 | setFunction: Function; 10 | inputPlaceholder: string; 11 | } 12 | >(({ isReady, onClick, setFunction, inputPlaceholder, children, ...rest }) => { 13 | return ( 14 | 26 | 27 | {inputPlaceholder} 28 | 29 | setFunction(d.target.value)} 34 | placeholder={inputPlaceholder ? inputPlaceholder : null} 35 | style={{ 36 | display: 'none', 37 | textAlign: 'right', 38 | color: '#000000', 39 | fontWeight: 500, 40 | fontSize: '24px', 41 | outline: `none`, 42 | border: `1px solid transparent`, 43 | borderRadius: `15px 0px 0px 15px`, 44 | height: `40px`, 45 | marginRight: `134px`, 46 | }} 47 | /> 48 | 75 | 76 | ); 77 | }); 78 | 79 | export default FrakButton3; 80 | -------------------------------------------------------------------------------- /components/button4/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonProps } from "@chakra-ui/button"; 2 | import { forwardRef } from "react"; 3 | const FrakButton4 = forwardRef< 4 | HTMLButtonElement, 5 | ButtonProps & { status?: string } 6 | >(({ status, children, ...rest }, ref) => { 7 | return ( 8 | 29 | ); 30 | }); 31 | 32 | export default FrakButton4; 33 | -------------------------------------------------------------------------------- /components/chainWarning/index.tsx: -------------------------------------------------------------------------------- 1 | import { utils } from "ethers"; 2 | import { Flex } from "@chakra-ui/layout"; 3 | 4 | import {getNetworkName} from "@/utils/helpers"; 5 | 6 | const ChainWarning: React.FC = () => { 7 | 8 | const switchChainOnMetaMask = async (): Promise => { 9 | try { 10 | await window.ethereum.request({ 11 | method: "wallet_switchEthereumChain", 12 | params: [ 13 | { 14 | chainId: utils.hexValue(parseInt(process.env.NEXT_PUBLIC_NETWORK_CHAIN_ID)), 15 | }, 16 | ], 17 | }); 18 | return true; 19 | } catch (switchError) { 20 | if (switchError.code === 4902) { 21 | console.error("error 4902"); 22 | } else { 23 | console.error("Unable to switch to chain on metamask", switchError); 24 | } 25 | } 26 | return false; 27 | }; 28 | 29 | return ( 30 | 31 |
switchChainOnMetaMask()} 43 | > 44 |
52 | Wrong network! 53 |
54 |
62 | Click here to switch to {getNetworkName(parseInt(process.env.NEXT_PUBLIC_NETWORK_CHAIN_ID))}. 63 |
64 |
65 |
66 | ); 67 | }; 68 | 69 | export default ChainWarning; 70 | -------------------------------------------------------------------------------- /components/dropdown/index.tsx: -------------------------------------------------------------------------------- 1 | import { Box, StackProps, Text, VStack } from "@chakra-ui/layout"; 2 | import React from "react"; 3 | 4 | const Dropdown: React.FC< 5 | StackProps & { 6 | items: string[]; 7 | onItemClick: (item: string, index: number) => void; 8 | } 9 | > = ({ items, onItemClick, ...rest }) => { 10 | return ( 11 | 20 | {items.map((item, index) => ( 21 | 33 | {item} 34 | 35 | ))} 36 | 37 | ); 38 | }; 39 | 40 | export default Dropdown; 41 | -------------------------------------------------------------------------------- /components/footer/index.tsx: -------------------------------------------------------------------------------- 1 | import { Image } from "@chakra-ui/image"; 2 | import { Text, Link, Container, Box } from "@chakra-ui/layout"; 3 | import { Heading, Flex, Icon, List, ListItem } from "@chakra-ui/react"; 4 | import TwitterIcon from "../icon/TwitterIcon"; 5 | import InstagramIcon from "../icon/InstagramIcon"; 6 | import DiscordIcon from "../icon/DiscordIcon"; 7 | import MediumIcon from '../icon/MediumIcon'; 8 | import YoutubeIcon from '../icon/YoutubeIcon'; 9 | 10 | const urlLists = [ 11 | { 12 | title: "Resources", 13 | items: [ 14 | { text: "Blog", url: "https://blog.fraktal.io/" }, 15 | { text: "Docs", url: "https://docs.fraktal.io/" }, 16 | { text: "Audit", url: "https://github.com/FraktalNFT/audits" } 17 | ] 18 | }, 19 | { 20 | title: "Get Involved", 21 | items: [ 22 | { text: "Stake", url: "https://docs.fraktal.io/fraktal-governance-token-frak/staking-frak" }, 23 | { text: "DAO", url: "https://dao.fraktal.io/#/" }, 24 | { text: "Github", url: "https://github.com/FraktalNFT" }, 25 | ] 26 | }, 27 | { 28 | title: "Need Help?", 29 | items: [ 30 | { text: "How it Works", url: "https://docs.fraktal.io/marketplace/get-started" }, 31 | { text: "Tutorials", url: "https://www.youtube.com/channel/UCUpcKyPeUJ2Mhx7OWOSZL6w" }, 32 | { text: "Support", url: "https://discord.com/invite/P6fCPvtZtq" } 33 | ] 34 | } 35 | ] 36 | 37 | const socials = [ 38 | { url: "https://twitter.com/fraktalnft", icon: TwitterIcon }, 39 | { url: "https://www.instagram.com/fraktal.io/", icon: InstagramIcon }, 40 | { url: "https://discord.com/invite/P6fCPvtZtq", icon: DiscordIcon }, 41 | { url: "https://www.youtube.com/channel/UCUpcKyPeUJ2Mhx7OWOSZL6w", icon: YoutubeIcon }, 42 | { url: "https://blog.fraktal.io/", icon: MediumIcon }, 43 | ] 44 | 45 | const Footer: React.FC = () => { 46 | return ( 47 | 51 | 52 | 53 | 54 | 55 | Fraktal is a community first project, with a mission to to empower 56 | artists to be in full control of their work and have unlimited 57 | creative freedom. 58 | 59 | 60 | 61 | 62 | {socials.map(({url, icon}, idx) => ( 63 | 64 | 65 | 66 | ))} 67 | 68 | 69 | 70 | © Fraktal Technologies Ltd. 71 | 72 | 73 | 74 | 75 | {urlLists.map(({title, items}, idx) => ( 76 | 77 | {title} 78 | 79 | {items.map(({url, text}, lidx) => ( 80 | 81 | 88 | {text} 89 | 90 | 91 | ))} 92 | 93 | 94 | ))} 95 | 96 | 97 | ); 98 | }; 99 | 100 | export default Footer; 101 | -------------------------------------------------------------------------------- /components/fraktalButton/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * React 3 | */ 4 | import { forwardRef, useState } from 'react'; 5 | /** 6 | * ChakraUI 7 | */ 8 | import { Button, ButtonProps } from '@chakra-ui/button'; 9 | 10 | const FraktalButton = forwardRef< 11 | HTMLButtonElement, 12 | ButtonProps & { 13 | isReady?: boolean; 14 | } 15 | >( 16 | ({ 17 | isReady, onClick, children, ...rest 18 | }) => { 19 | 20 | return ( 21 | <> 22 | 51 | 52 | ); 53 | } 54 | ); 55 | 56 | export default FraktalButton; 57 | -------------------------------------------------------------------------------- /components/fraktionOwners/index.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Box, 3 | Center, 4 | StackProps, 5 | Text, 6 | VStack, 7 | HStack, 8 | Stack, 9 | } from "@chakra-ui/layout"; 10 | import React, { forwardRef, useState, useEffect } from "react"; 11 | import { createRevenuePayment } from "../../utils/contractCalls"; 12 | import RevenuesDetail from "../revenuesDetail"; 13 | import FrakButton2 from "../button2"; 14 | import { utils } from "ethers"; 15 | import { getSubgraphData } from "../../utils/graphQueries"; 16 | import {getExplorerUrl} from "@/utils/helpers"; 17 | 18 | // if account has fraktions.. display info to list? 19 | 20 | export default function FraktionOwners(props) { 21 | const [internalData, setInternalData] = useState({}); 22 | let nftObject = props.nftObject; 23 | 24 | // const [owners, setOwners] = useState([]); 25 | 26 | useEffect(() => { 27 | async function getOwners(id) { 28 | let filteredData = props.data.filter(x=>{return x.owner && x.owner.id && x.amount > 0}) 29 | setInternalData(filteredData); 30 | } 31 | if (nftObject.id) { 32 | getOwners(nftObject.id); 33 | } 34 | }, [nftObject, props]); 35 | 36 | return ( 37 |
46 | 47 |
56 | NFT Owners 57 |
58 |
59 |
60 | 61 | 69 | Address 70 | 71 | 80 | Ownership 81 | 82 | 83 | {internalData && internalData.length && internalData.map( 84 | (user: object, index: number) => { 85 | let first4 = user.owner.id.substring(0, 6); // (0x + 4 digits) 86 | let last4 = user.owner.id.substring( 87 | user.owner.id.length - 4, 88 | user.owner.id.length 89 | ); 90 | let shortAddress = `${first4}...${last4}`; 91 | let ownedAmount = utils.parseUnits(user.amount,"wei");//in fei 92 | let percentOwned = ""; 93 | if(ownedAmount < utils.parseEther("1.0")){ 94 | percentOwned = "<0.01" 95 | }else{ 96 | percentOwned = utils.formatEther(ownedAmount.div(100)); 97 | } 98 | // let percentOwned = (parseInt(user.amount) / 10000) * 100; 99 | return ( 100 | 109 | 113 | 114 | {shortAddress} 115 | 116 | 117 | {percentOwned}% 118 | 119 | ); 120 | } 121 | )} 122 | 123 |
124 |
125 | ); 126 | } 127 | -------------------------------------------------------------------------------- /components/fraktionsList/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * React 3 | */ 4 | import React, {useEffect, useState} from "react"; 5 | 6 | import FraktionsDetail from '../fraktionsDetail'; 7 | 8 | import VerifyNFT from "@/components/verifyNFT"; 9 | // if account has fraktions.. display info to list? 10 | 11 | const FraktionsList=(({nftObject, fraktionsListed, tokenAddress, marketAddress, provider}) => { 12 | 13 | return( 14 | <> 15 |
23 |
32 | Fraktions 33 | 34 |
35 | {fraktionsListed && fraktionsListed.length ? 36 |
37 | {fraktionsListed.map(x=>{ 38 | return( 39 | 48 | ) 49 | })} 50 |
51 | : 52 |
53 | There are no listed Fraktions of this NFT. 54 |
55 | } 56 |
57 | 58 | ) 59 | 60 | }) 61 | 62 | 63 | export default FraktionsList; 64 | -------------------------------------------------------------------------------- /components/header/index.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Flex, HStack, Image, Link } from "@chakra-ui/react"; 2 | import NextLink from "next/link"; 3 | import FrakButton from "../button"; 4 | import { useWeb3Context } from "../../contexts/Web3Context"; 5 | import { shortenHash } from "../../utils/helpers"; 6 | import { useRouter } from "next/router"; 7 | import {ARTISTS, CREATE_NFT, EXPLORE, LANDING, IMPORT_NFTS, REWARDS, CLAIM, CLAIM_BONUS} from "@/constants/routes"; 8 | 9 | const Header = () => { 10 | const router = useRouter(); 11 | const { connectWeb3, account } = useWeb3Context(); 12 | 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | logo 20 | 21 | 22 | 23 | 24 | 30 | 31 | {router.pathname === EXPLORE ? ( 32 | 39 | Explore 40 | 41 | ) : ( 42 | 48 | Explore 49 | 50 | )} 51 | 52 | 53 | {router.pathname === CREATE_NFT || 54 | router.pathname === IMPORT_NFTS ? ( 55 | 62 | List NFT 63 | 64 | ) : ( 65 | 71 | List NFT 72 | 73 | )} 74 | 75 | 76 | {router.pathname === REWARDS ? ( 77 | 84 | Rewards 85 | 86 | ) : ( 87 | 93 | Rewards 94 | 95 | )} 96 | 97 | 98 | {/* 106 | How it Works 107 | */} 108 | 109 | 110 | {!account ? ( 111 | Connect Wallet 112 | ) : ( 113 | 114 | 124 | {shortenHash(account)} | View my NFTs 125 | 126 | 127 | )} 128 | 129 | 130 | 131 | ); 132 | }; 133 | 134 | export default Header; 135 | -------------------------------------------------------------------------------- /components/icon/DiscordIcon.tsx: -------------------------------------------------------------------------------- 1 | import { Icon } from '@chakra-ui/react' 2 | 3 | const DiscordIcon: React.FC = (props) => ( 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | ) 15 | 16 | export default DiscordIcon -------------------------------------------------------------------------------- /components/icon/MediumIcon.tsx: -------------------------------------------------------------------------------- 1 | import { Icon } from '@chakra-ui/react' 2 | 3 | const MediumIcon: React.FC = (props) => ( 4 | 5 | 6 | 7 | 8 | 9 | ) 10 | 11 | export default MediumIcon -------------------------------------------------------------------------------- /components/icon/TwitterIcon.tsx: -------------------------------------------------------------------------------- 1 | import { Icon } from '@chakra-ui/react' 2 | 3 | const TwitterIcon: React.FC = (props) => ( 4 | 5 | 7 | 8 | 9 | 10 | 12 | 13 | ) 14 | 15 | export default TwitterIcon; -------------------------------------------------------------------------------- /components/icon/YoutubeIcon.tsx: -------------------------------------------------------------------------------- 1 | import { Icon } from '@chakra-ui/react' 2 | 3 | const YoutubeIcon: React.FC = (props) => ( 4 | 5 | 6 | 7 | 8 | 9 | 10 | ) 11 | 12 | export default YoutubeIcon -------------------------------------------------------------------------------- /components/infiniteScrollNft/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * React 3 | */ 4 | import { useState, useEffect} from "react"; 5 | /** 6 | * Chakra UI 7 | */ 8 | import {Box, Grid, Spinner} from "@chakra-ui/react"; 9 | /** 10 | * Components 11 | */ 12 | import InfiniteScroll from "react-infinite-scroll-component"; 13 | import NFTImportCardOS from "@/components/nft-importcard-opensea"; 14 | 15 | /** 16 | * InfiniteScrollNft 17 | * @param nftItems 18 | * @constructor 19 | */ 20 | const InfiniteScrollNft = ({getData, nftItems, setTokenToImport, hasMore, setImportingNFT}) => { 21 | 22 | 23 | return ( 24 | } 29 | scrollThreshold={0.5} 30 | endMessage={

Nothing more to show

} 31 | > 32 | 39 | {nftItems.map((item, index) => ( 40 | { 44 | setTokenToImport(item); 45 | setImportingNFT(true); 46 | }} 47 | /> 48 | ))} 49 | 50 |
51 | ); 52 | } 53 | 54 | const Loading = () => { 55 | return ( 63 | 64 | ) 65 | }; 66 | 67 | export {Loading}; 68 | export default InfiniteScrollNft; -------------------------------------------------------------------------------- /components/limitedInput/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * React 3 | */ 4 | import { forwardRef, useState } from 'react'; 5 | /** 6 | * ChakraUI 7 | */ 8 | import { 9 | NumberInput, 10 | NumberInputField, 11 | Text 12 | } from '@chakra-ui/react'; 13 | import { ButtonProps } from '@chakra-ui/button'; 14 | /** 15 | * Components 16 | */ 17 | import FraktalButton from "@/components/fraktalButton"; 18 | 19 | /** 20 | * LimitedInput Component 21 | */ 22 | const LimitedInput = forwardRef< 23 | HTMLButtonElement, 24 | ButtonProps & { 25 | isReady?: boolean; 26 | setFunction: Function; 27 | inputPlaceholder: string; 28 | currency: string; 29 | maxFraktions: string; 30 | }>( 31 | ({ 32 | isReady, 33 | onClick, 34 | setFunction, 35 | inputPlaceholder, 36 | currency, 37 | children, 38 | maxFraktions, 39 | ...rest 40 | }) => { 41 | 42 | const [color, setColor] = useState("#000"); 43 | 44 | return ( 45 |
56 | { 65 | setFunction(num); 66 | (parseInt(num) > parseInt(maxFraktions)) ? setColor("#ff0000") : setColor("#000"); 67 | }} 68 | > 69 | 78 | 79 |
80 | 94 | {currency ? currency : null} 95 | 96 |
97 | 102 | {children} 103 | 104 |
105 | ); 106 | } 107 | ); 108 | 109 | export default LimitedInput; 110 | -------------------------------------------------------------------------------- /components/listCard/index.tsx: -------------------------------------------------------------------------------- 1 | import { formatEtherPrice } from '@/utils/format'; 2 | import { HStack, VStack } from '@chakra-ui/layout'; 3 | import { 4 | NumberInput, 5 | NumberInputField, 6 | NumberInputStepper, 7 | NumberIncrementStepper, 8 | NumberDecrementStepper, 9 | } from '@chakra-ui/react'; 10 | import { BigNumber, utils } from 'ethers'; 11 | 12 | const ListCard = ({ 13 | totalPrice, 14 | setTotalPrice, 15 | totalAmount, 16 | setTotalAmount, 17 | listingProcess, 18 | maxFraktions, 19 | }) => { 20 | const wei = totalPrice > 0 && utils.parseEther(totalPrice.toString()); 21 | const fei = totalAmount > 0 && utils.parseEther(totalAmount.toString()); 22 | const pricePerFraktion = 23 | totalPrice > 0 && totalAmount > 0 24 | ? wei.mul(utils.parseEther('1.0')).div(fei) 25 | : 0; 26 | return ( 27 | 28 | 29 |
38 | TOTAL PRICE 39 |
40 | { 43 | setTotalPrice(e.target.value); 44 | }} 45 | type="number" 46 | style={{ 47 | margin: '8px', 48 | border: '2px solid #E0E0E0', 49 | padding: '14.5px 16px', 50 | background: '#FFFFFF', 51 | borderRadius: '16px', 52 | }} 53 | > 54 |
63 | Per Fraktion:{' '} 64 | {pricePerFraktion ? formatEtherPrice(pricePerFraktion) : null} ETH 65 |
66 |
67 | 68 |
77 | TOTAL AMOUNT 78 |
79 | { 88 | setTotalAmount(num); 89 | }} 90 | > 91 | 101 | 102 | 103 | 104 | 105 | 106 |
115 | Of {maxFraktions} Fraktions 116 |
117 |
118 |
119 | ); 120 | }; 121 | 122 | export default ListCard; 123 | -------------------------------------------------------------------------------- /components/listCardAuction/index.tsx: -------------------------------------------------------------------------------- 1 | import { formatEtherPrice } from '@/utils/format'; 2 | import { HStack, VStack } from '@chakra-ui/layout'; 3 | import { 4 | NumberInput, 5 | NumberInputField, 6 | NumberInputStepper, 7 | NumberIncrementStepper, 8 | NumberDecrementStepper, 9 | } from '@chakra-ui/react'; 10 | import { utils } from 'ethers'; 11 | 12 | const ListCardAuction = ({ 13 | totalPrice, 14 | setTotalPrice, 15 | totalAmount, 16 | setTotalAmount, 17 | listingProcess, 18 | maxFraktions, 19 | }) => { 20 | const wei = totalPrice > 0 && utils.parseEther(totalPrice.toString()); 21 | const fei = totalAmount > 0 && utils.parseEther(totalAmount.toString()); 22 | const pricePerFraktion = 23 | totalPrice > 0 && totalAmount > 0 24 | ? wei.mul(utils.parseEther('1.0')).div(fei) 25 | : 0; 26 | return ( 27 | 28 | 29 |
38 | RESERVE PRICE 39 |
40 | { 43 | setTotalPrice(e.target.value); 44 | }} 45 | type="number" 46 | style={{ 47 | margin: '8px', 48 | border: '2px solid #E0E0E0', 49 | padding: '14.5px 16px', 50 | background: '#FFFFFF', 51 | borderRadius: '16px', 52 | }} 53 | > 54 |
63 | Per Fraktion:{' '} 64 | {pricePerFraktion ? formatEtherPrice(pricePerFraktion) : null} ETH 65 |
66 |
67 | 68 |
77 | TOTAL AMOUNT 78 |
79 | { 88 | setTotalAmount(num); 89 | }} 90 | > 91 | 101 | 102 | 103 | 104 | 105 | 106 |
115 | Of {maxFraktions} Fraktions 116 |
117 |
118 |
119 | ); 120 | }; 121 | 122 | export default ListCardAuction; 123 | -------------------------------------------------------------------------------- /components/load-screens/loaders.module.css: -------------------------------------------------------------------------------- 1 | 2 | .wrapper { 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | 8 | .checkmark { 9 | width: 60px; 10 | height: 60px; 11 | border-radius: 50%; 12 | display: block; 13 | stroke-width: 6; 14 | stroke-linecap: round; 15 | stroke-miterlimit: 10; 16 | margin: 10% auto; 17 | animation: fill .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both 18 | } 19 | 20 | .crossPathLeft { 21 | transform-origin: 50% 50%; 22 | stroke-dasharray: 48; 23 | stroke-dashoffset: 48; 24 | animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.5s forwards; 25 | } 26 | .crossPathRight { 27 | transform-origin: 50% 50%; 28 | stroke-dasharray: 48; 29 | stroke-dashoffset: 48; 30 | animation: stroke 0.5s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards; 31 | } 32 | 33 | .checkmarkCheck { 34 | transform-origin: 50% 50%; 35 | stroke-dasharray: 48; 36 | stroke-dashoffset: 48; 37 | animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards; 38 | } 39 | 40 | @keyframes stroke { 41 | 100% { 42 | stroke-dashoffset: 0 43 | } 44 | } 45 | 46 | @keyframes scale { 47 | 48 | 0%, 49 | 100% { 50 | transform: none 51 | } 52 | 53 | 50% { 54 | transform: scale3d(1, 1, 1) 55 | } 56 | } 57 | 58 | @keyframes fill { 59 | 100% { 60 | /* box-shadow: inset 0px 0px 0px 30px #7ac142*/ 61 | } 62 | } -------------------------------------------------------------------------------- /components/media/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from "react"; 2 | import {Image} from "@chakra-ui/image"; 3 | import {Box, Spinner} from "@chakra-ui/react"; 4 | 5 | const NFTMedia = ({imageURL, setIsImageLoaded, type, metadata={}}) => { 6 | 7 | const [image, setImage] = useState('https://image.fraktal.io/?height=350&image=' + encodeURIComponent(imageURL)); 8 | const [video, setVideo] = useState(""); 9 | 10 | async function loadMedia() { 11 | try { 12 | const loadImage = await fetch(imageURL); 13 | if (loadImage.headers.get('content-type') == 'image/gif') { 14 | setImage(imageURL); 15 | } 16 | setIsImageLoaded(true); 17 | } catch (e) { 18 | //TODO - Add Error 19 | } 20 | } 21 | 22 | useEffect(() => { 23 | loadVideo(); 24 | if (type == 'details') { 25 | loadMedia(); 26 | } 27 | }, []); 28 | 29 | const onImageLoad = (ms: number) => { 30 | setIsImageLoaded(true); 31 | }; 32 | 33 | const loadVideo = () => { 34 | if (!imageURL) { 35 | return null; 36 | } 37 | const fileExtension = imageURL.split('.').pop(); 38 | if (fileExtension === 'mp4') { 39 | setVideo(imageURL); 40 | return true; 41 | } 42 | if (!metadata.metadata) { 43 | return false; 44 | } 45 | if (metadata.metadata.animation_url) { 46 | if (metadata.metadata.animation_url.startsWith('ipfs://')) { 47 | let hasIpfsProtocol = metadata.metadata.animation_url.split('ipfs://'); 48 | setVideo('https://ipfs.io/ipfs/' + hasIpfsProtocol[1]); 49 | } else { 50 | setVideo(metadata.metadata.animation_url); 51 | } 52 | return true; 53 | } 54 | if (metadata.metadata.properties && metadata.metadata.properties.preview_media_file2 && metadata.metadata.properties.preview_media_file2_type.description == 'mp4') { 55 | setVideo(metadata.metadata.properties.preview_media_file2.description); 56 | return true; 57 | } 58 | }; 59 | 60 | const isVideo = () => { 61 | if (video === "") { 62 | return false; 63 | } 64 | setIsImageLoaded(true); 65 | return true; 66 | }; 67 | 68 | return ( 69 | <> 70 | {isVideo() ? ( 71 | 74 | ) : ( 75 | onImageLoad(50)} 88 | />) 89 | } 90 | 91 | 92 | ) 93 | } 94 | export default NFTMedia; -------------------------------------------------------------------------------- /components/modal/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactModal from "react-modal"; 3 | import { Image } from "@chakra-ui/react"; 4 | 5 | const customStyles = { 6 | content: { 7 | top: "50%", 8 | left: "50%", 9 | right: "auto", 10 | padding: 0, 11 | bottom: "auto", 12 | marginRight: "-50%", 13 | transform: "translate(-50%, -50%)", 14 | }, 15 | }; 16 | 17 | interface Props { 18 | open: boolean; 19 | onClose: () => void; 20 | onConfirm?: () => void; 21 | children: React.ReactNode; 22 | } 23 | 24 | typeof window !== "undefined" && ReactModal.setAppElement("#app"); 25 | 26 | const Modal: React.FC = ({ open, onClose, children }) => { 27 | return ( 28 | 29 |
30 | 38 | {children} 39 |
40 |
41 | ); 42 | }; 43 | 44 | export default Modal; 45 | -------------------------------------------------------------------------------- /components/newNFTHeader/index.tsx: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * React 4 | */ 5 | import { useEffect, useState } from 'react'; 6 | import {useRouter} from "next/router"; 7 | import {Box, Link, Text} from "@chakra-ui/react"; 8 | import {CREATE_NFT, IMPORT_NFTS} from "@/constants/routes"; 9 | 10 | /** 11 | * MyNFTWallet 12 | * @constructor 13 | */ 14 | const NewNFTHeader = () => { 15 | const router = useRouter(); 16 | 17 | // Show Loading State 18 | useEffect(() => { 19 | 20 | }, []); 21 | 22 | return ( 23 | <> 24 |
25 | router.push(CREATE_NFT, null, { scroll: false })} 31 | > 32 | Mint NFT 33 | 34 | router.push(IMPORT_NFTS, null, { scroll: false })} 45 | > 46 | Import NFT 47 | 48 |
49 | 50 | ); 51 | } 52 | 53 | export default NewNFTHeader; -------------------------------------------------------------------------------- /components/nft-importcard-opensea/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@chakra-ui/button"; 2 | import { Image } from "@chakra-ui/image"; 3 | import { Box, Center, StackProps, Text, VStack } from "@chakra-ui/layout"; 4 | import { formatEther } from "@ethersproject/units"; 5 | import React, { forwardRef } from "react"; 6 | import { FrakCard } from "../../types"; 7 | import FrakButton from "../button"; 8 | import NextLink from "next/link"; 9 | import {useState} from 'react'; 10 | import { useWeb3Context } from '../../contexts/Web3Context'; 11 | import {approveMarket, importERC721, importERC1155} from '../../utils/contractCalls'; 12 | // import { claimNFT } from '../../utils/helpers'; 13 | 14 | interface NFTItemProps extends StackProps { 15 | item: FrakCard; 16 | CTAText?: string; 17 | onCollateralRequest?: void; 18 | }; 19 | 20 | const NFTImportCardOS = forwardRef( 21 | ({ item, onClick }, ref) => { 22 | return ( 23 | 33 | 34 | 35 | 36 | 37 | {item?.name} 38 | 39 | 40 | ); 41 | } 42 | ); 43 | 44 | export default NFTImportCardOS; 45 | -------------------------------------------------------------------------------- /components/nft-item-manager/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@chakra-ui/button"; 2 | import { Image } from "@chakra-ui/image"; 3 | import { Box, Center, StackProps, Text, VStack } from "@chakra-ui/layout"; 4 | import { formatEther } from "@ethersproject/units"; 5 | import React, { forwardRef } from "react"; 6 | import { FrakCard } from "../../types"; 7 | import FrakButton from "../button"; 8 | import NextLink from "next/link"; 9 | 10 | interface NFTItemProps extends StackProps { 11 | item: FrakCard; 12 | CTAText?: string; 13 | } 14 | 15 | const NFTItemManager = forwardRef( 16 | ({ item, onClick, CTAText }, ref) => { 17 | return ( 18 | 28 | 29 | 30 | {item.countdown && ( 31 | 43 | Time Remaining 44 | 11:59:09 45 | 46 | )} 47 | 48 | {item.contributions && ( 49 |
56 | 57 | {formatEther(item.contributions).toString()} Contributed 58 | 59 |
60 | )} 61 |
62 |
63 | 64 | {item.name} 65 | 66 | 67 | 68 | Sell 69 | 70 | 71 | 72 | 73 | Manage 74 | 75 | 76 |
77 |
78 | ); 79 | } 80 | ); 81 | 82 | export default NFTItemManager; 83 | -------------------------------------------------------------------------------- /components/nft-item-opensea/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@chakra-ui/button"; 2 | import { Image } from "@chakra-ui/image"; 3 | import { Box, Center, StackProps, Text, VStack } from "@chakra-ui/layout"; 4 | import { formatEther } from "@ethersproject/units"; 5 | import React, { forwardRef } from "react"; 6 | import { FrakCard } from "../../types"; 7 | import FrakButton from "../button"; 8 | import NextLink from "next/link"; 9 | import {useState} from 'react'; 10 | import { useWeb3Context } from '../../contexts/Web3Context'; 11 | import {approveMarket, importERC721, importERC1155} from '../../utils/contractCalls'; 12 | import { claimNFT } from '../../utils/helpers'; 13 | 14 | interface NFTItemProps extends StackProps { 15 | item: FrakCard; 16 | CTAText?: string; 17 | onCollateralRequest?: void; 18 | } 19 | 20 | const NFTItemOS = forwardRef( 21 | ({ item, onClick, CTAText, onCollateralRequest }, ref) => { 22 | 23 | return ( 24 | 37 | 38 | 39 | 40 |
41 | 42 | {item.name} 43 | 44 | 45 | {item.token_schema} 46 | 47 | 52 | {CTAText} 53 | 54 | {item.collateral && 55 |
56 | onCollateralRequest()} 61 | > 62 | Claim collateral 63 | 64 |
65 | } 66 | 67 |
68 |
69 | ); 70 | } 71 | ); 72 | 73 | export default NFTItemOS; 74 | -------------------------------------------------------------------------------- /components/nftCard/index.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonProps } from "@chakra-ui/button"; 2 | import { forwardRef } from "react"; 3 | import FrakButton3 from "../button3"; 4 | import styles from "../../styles/mint-nft.module.css"; 5 | import { Box, Input, Textarea } from "@chakra-ui/react"; 6 | const NFTCard = ({ setName, setDescription, addFile, file, fileUpload=true, nftName = "" }) => { 7 | function openLocal() { 8 | document.getElementById("imageInput").files = null; 9 | document.getElementById("imageInput").click(); 10 | } 11 | 12 | return ( 13 |
14 |
24 | NAME 25 |
26 | setName(e.target.value)} 38 | /> 39 | {fileUpload ? 40 | (
41 |
52 | image 53 |
54 | 55 | openLocal()} 58 | setFunction={() => addFile()} 59 | inputPlaceholder="PNG, JPG or GIF" 60 | > 61 | {file ? "Change File" : "Choose File"} 62 | 63 | 64 |
): null} 65 |
76 | DESCRIPTION (OPTIONAL) 77 |
78 |