From 39dd13d4f3463656bcdc7536f0ae4060454df551 Mon Sep 17 00:00:00 2001 From: Lulox Date: Thu, 19 Sep 2024 16:26:53 -0300 Subject: [PATCH] Several UI improvements, first version of a user profile --- packages/nextjs/app/layout.tsx | 2 +- .../marketplace/_components/Marketplace.tsx | 7 + .../app/marketplace/_components/NFTCard.tsx | 23 +- .../_components/marketplaceDescription.tsx | 51 ++ packages/nextjs/app/marketplace/page.tsx | 14 +- packages/nextjs/app/myNFTs/page.tsx | 81 --- .../_components/MyHoldings.tsx | 15 +- .../_components/NFTCard.tsx | 0 .../_components/index.ts | 0 packages/nextjs/app/myProfile/page.tsx | 136 +++++ packages/nextjs/app/page.tsx | 18 +- .../app/simpleMint/_components/SimpleMint.tsx | 465 +++++++++++++++++ .../simpleMint/_components/TextAreaBase.tsx | 2 +- .../_components/simpleMintDescription.tsx | 71 ++- packages/nextjs/app/simpleMint/page.tsx | 469 +----------------- packages/nextjs/components/Header.tsx | 58 +-- .../nextjs/contracts/deployedContracts.ts | 8 +- .../nextjs/utils/scaffold-eth/getMetadata.ts | 2 +- 18 files changed, 787 insertions(+), 635 deletions(-) create mode 100644 packages/nextjs/app/marketplace/_components/marketplaceDescription.tsx delete mode 100644 packages/nextjs/app/myNFTs/page.tsx rename packages/nextjs/app/{myNFTs => myProfile}/_components/MyHoldings.tsx (86%) rename packages/nextjs/app/{myNFTs => myProfile}/_components/NFTCard.tsx (100%) rename packages/nextjs/app/{myNFTs => myProfile}/_components/index.ts (100%) create mode 100644 packages/nextjs/app/myProfile/page.tsx create mode 100644 packages/nextjs/app/simpleMint/_components/SimpleMint.tsx diff --git a/packages/nextjs/app/layout.tsx b/packages/nextjs/app/layout.tsx index be1234b..eeecb26 100644 --- a/packages/nextjs/app/layout.tsx +++ b/packages/nextjs/app/layout.tsx @@ -5,7 +5,7 @@ import "~~/styles/globals.css"; import { getMetadata } from "~~/utils/scaffold-eth/getMetadata"; export const metadata = getMetadata({ - title: "Scaffold-ETH 2 App", + title: "Technai", description: "Built with 🏗 Scaffold-ETH 2", }); diff --git a/packages/nextjs/app/marketplace/_components/Marketplace.tsx b/packages/nextjs/app/marketplace/_components/Marketplace.tsx index 85c09cc..6975b7b 100644 --- a/packages/nextjs/app/marketplace/_components/Marketplace.tsx +++ b/packages/nextjs/app/marketplace/_components/Marketplace.tsx @@ -2,6 +2,9 @@ import { useEffect, useState } from "react"; import { NFTCard } from "./NFTCard"; +import { MarketplaceDescription } from "./marketplaceDescription"; +import { useAccount } from "wagmi"; +import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; import { useScaffoldContract, useScaffoldEventHistory } from "~~/hooks/scaffold-eth"; import { notification } from "~~/utils/scaffold-eth"; import { getMetadataFromIPFS } from "~~/utils/simpleNFT/ipfs-fetch"; @@ -20,6 +23,8 @@ export interface Collectible extends Partial { } export const Marketplace = () => { + const { address: isConnected, isConnecting } = useAccount(); + const [listedCollectibles, setListedCollectibles] = useState([]); // Fetch the collectible contract @@ -150,6 +155,8 @@ export const Marketplace = () => { return ( <> + +
{!isConnected || isConnecting ? : ""}
{listedCollectibles.length === 0 ? (
No NFTs found
diff --git a/packages/nextjs/app/marketplace/_components/NFTCard.tsx b/packages/nextjs/app/marketplace/_components/NFTCard.tsx index 2199114..ea984ee 100644 --- a/packages/nextjs/app/marketplace/_components/NFTCard.tsx +++ b/packages/nextjs/app/marketplace/_components/NFTCard.tsx @@ -77,7 +77,7 @@ export const NFTCard = ({ nft }: { nft: Collectible }) => { )} setActiveTab("info")} > Info @@ -131,10 +131,6 @@ export const NFTCard = ({ nft }: { nft: Collectible }) => {
NFT Image -
- # {nft.listingId ?? "N/A"}{" "} - {/* Display 'N/A' if listingId is missing */} -
{nft.animation_url && ( @@ -184,9 +180,22 @@ export const NFTCard = ({ nft }: { nft: Collectible }) => { {/* Handle missing description */}
- Owner : -
+ {nft.listingId ? ( + <> + Owner: +
+ + ) : ( + <> + Artist: +
+ + )}
+ {/*
+ Listing ID : + {nft.listingId ?? "N/A"}{" "} +
*/}
)}
diff --git a/packages/nextjs/app/marketplace/_components/marketplaceDescription.tsx b/packages/nextjs/app/marketplace/_components/marketplaceDescription.tsx new file mode 100644 index 0000000..2d35e84 --- /dev/null +++ b/packages/nextjs/app/marketplace/_components/marketplaceDescription.tsx @@ -0,0 +1,51 @@ +export const MarketplaceDescription = () => { + return ( +
+ +
+ New to NFT Marketplaces? Click here! +
+
+ {/* Responsive 2-column layout, becomes 1 column on small screens */} +
+ {/* Left column: Green highlights */} +
+

+ NFTs, or Non-Fungible Tokens,{" "} + represent ownership of a piece of content or art. +
+ Collectors can mint or trade each piece of a NFT collection. +

+

+ NFTs allow artists to earn royalties each time their work is + resold. +
+ This gives artists continuous income beyond the first sale. +

+
+ + {/* Right column: Yellow highlights */} +
+

+ Collectors can mint or{" "} + trade each piece of a NFT collection. +
+ Minting means + creating and owning a new piece of a collection + {" "} + which is tradeable +

+

+ You can choose to mint an NFT of a collection (if still + available) +
+ + or buy an NFT that was minted by someone else. + +

+
+
+
+
+ ); +}; diff --git a/packages/nextjs/app/marketplace/page.tsx b/packages/nextjs/app/marketplace/page.tsx index 040eb7f..4560ae6 100644 --- a/packages/nextjs/app/marketplace/page.tsx +++ b/packages/nextjs/app/marketplace/page.tsx @@ -1,17 +1,15 @@ -"use client"; - import { Marketplace } from "./_components/Marketplace"; import type { NextPage } from "next"; -import { useAccount } from "wagmi"; -import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; +import { getMetadata } from "~~/utils/scaffold-eth/getMetadata"; -const MarketplacePage: NextPage = () => { - const { address: isConnected, isConnecting } = useAccount(); - // const { address: connectedAddress, isConnected, isConnecting } = useAccount(); +export const metadata = getMetadata({ + title: "Marketplace", + description: "Built with 🏗 Scaffold-ETH 2", +}); +const MarketplacePage: NextPage = () => { return ( <> -
{!isConnected || isConnecting ? : ""}
); diff --git a/packages/nextjs/app/myNFTs/page.tsx b/packages/nextjs/app/myNFTs/page.tsx deleted file mode 100644 index 631d58e..0000000 --- a/packages/nextjs/app/myNFTs/page.tsx +++ /dev/null @@ -1,81 +0,0 @@ -"use client"; - -import { MyHoldings } from "./_components"; -import type { NextPage } from "next"; -import { useAccount } from "wagmi"; -import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; -import { useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth"; -import { notification } from "~~/utils/scaffold-eth"; -import { addToIPFS } from "~~/utils/simpleNFT/ipfs-fetch"; -import nftsMetadata from "~~/utils/simpleNFT/nftsMetadata"; - -const MyNFTs: NextPage = () => { - const { address: isConnected, isConnecting } = useAccount(); - // const { address: connectedAddress, isConnected, isConnecting } = useAccount(); - - const { writeContractAsync } = useScaffoldWriteContract("MockNFT"); - - const { data: tokenIdCounter } = useScaffoldReadContract({ - contractName: "MockNFT", - functionName: "tokenIdCounter", - watch: true, - }); - - const handleMintItem = async () => { - if (tokenIdCounter === undefined) { - notification.error("Token ID Counter not found."); - return; - } - - const tokenIdCounterNumber = Number(tokenIdCounter); - const currentTokenMetaData = nftsMetadata[tokenIdCounterNumber % nftsMetadata.length]; - const notificationId = notification.loading("Uploading to IPFS"); - try { - const uploadedItem = await addToIPFS(currentTokenMetaData); - - notification.remove(notificationId); - notification.success("Metadata uploaded to IPFS"); - - // Log IPFS path before sending to contract - console.log("IPFS Path:", uploadedItem.path); - - // Mint the NFT - await writeContractAsync({ - functionName: "mintItem", - args: [uploadedItem.path], - }); - - notification.success("NFT Minted Successfully"); - } catch (error) { - notification.remove(notificationId); - console.error("Error during minting:", error); - - // Log the error and notify the user - notification.error("Minting failed, please try again."); - } - }; - - return ( - <> -
-
-

- My NFTs -

-
-
-
- {!isConnected || isConnecting ? ( - - ) : ( - - )} -
- - - ); -}; - -export default MyNFTs; diff --git a/packages/nextjs/app/myNFTs/_components/MyHoldings.tsx b/packages/nextjs/app/myProfile/_components/MyHoldings.tsx similarity index 86% rename from packages/nextjs/app/myNFTs/_components/MyHoldings.tsx rename to packages/nextjs/app/myProfile/_components/MyHoldings.tsx index f2b8f2c..1ea166b 100644 --- a/packages/nextjs/app/myNFTs/_components/MyHoldings.tsx +++ b/packages/nextjs/app/myProfile/_components/MyHoldings.tsx @@ -18,7 +18,7 @@ export const MyHoldings = () => { const { address: connectedAddress } = useAccount(); const [myAllCollectibles, setMyAllCollectibles] = useState([]); const [allCollectiblesLoading, setAllCollectiblesLoading] = useState(false); - const [showOnlyMyNFTs, setShowOnlyMyNFTs] = useState(false); + // const [showOnlyMyNFTs, setShowOnlyMyNFTs] = useState(true); // When false, displays all NFTs of the MockNFT collection const { data: yourCollectibleContract } = useScaffoldContract({ contractName: "MockNFT", @@ -46,9 +46,9 @@ export const MyHoldings = () => { const tokenURI = await yourCollectibleContract.read.tokenURI([tokenId]); const owner = await yourCollectibleContract.read.ownerOf([tokenId]); - if (showOnlyMyNFTs && owner.toLowerCase() !== connectedAddress.toLowerCase()) { - continue; - } + // if (showOnlyMyNFTs && owner.toLowerCase() !== connectedAddress.toLowerCase()) { + // continue; + // } const ipfsHash = tokenURI.replace("https://ipfs.io/ipfs/", ""); @@ -73,7 +73,8 @@ export const MyHoldings = () => { }; updateMyCollectibles(); - }, [connectedAddress, showOnlyMyNFTs, myTotalBalance]); // Watching balance to update NFTs + // }, [connectedAddress, showOnlyMyNFTs, myTotalBalance]); // Watching balance to update NFTs + }, [connectedAddress, myTotalBalance]); // Watching balance to update NFTs if (allCollectiblesLoading) return ( @@ -84,7 +85,7 @@ export const MyHoldings = () => { return ( <> -
+ {/*
-
+
*/} {myAllCollectibles.length === 0 ? (
No NFTs found
diff --git a/packages/nextjs/app/myNFTs/_components/NFTCard.tsx b/packages/nextjs/app/myProfile/_components/NFTCard.tsx similarity index 100% rename from packages/nextjs/app/myNFTs/_components/NFTCard.tsx rename to packages/nextjs/app/myProfile/_components/NFTCard.tsx diff --git a/packages/nextjs/app/myNFTs/_components/index.ts b/packages/nextjs/app/myProfile/_components/index.ts similarity index 100% rename from packages/nextjs/app/myNFTs/_components/index.ts rename to packages/nextjs/app/myProfile/_components/index.ts diff --git a/packages/nextjs/app/myProfile/page.tsx b/packages/nextjs/app/myProfile/page.tsx new file mode 100644 index 0000000..477dbc8 --- /dev/null +++ b/packages/nextjs/app/myProfile/page.tsx @@ -0,0 +1,136 @@ +"use client"; + +import { useState } from "react"; +import { MyHoldings } from "./_components"; +import { NextPage } from "next"; +import { useAccount } from "wagmi"; +import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth"; +import { useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth"; +import { notification } from "~~/utils/scaffold-eth"; +import { addToIPFS } from "~~/utils/simpleNFT/ipfs-fetch"; +import nftsMetadata from "~~/utils/simpleNFT/nftsMetadata"; + +const MyNFTs: NextPage = () => { + const { address: isConnected, isConnecting } = useAccount(); + const { writeContractAsync } = useScaffoldWriteContract("MockNFT"); + + const { data: tokenIdCounter } = useScaffoldReadContract({ + contractName: "MockNFT", + functionName: "tokenIdCounter", + watch: true, + }); + + // Tab management state + const [activeTab, setActiveTab] = useState("your-nfts"); + + const handleMintItem = async () => { + if (tokenIdCounter === undefined) { + notification.error("Token ID Counter not found."); + return; + } + + const tokenIdCounterNumber = Number(tokenIdCounter); + const currentTokenMetaData = nftsMetadata[tokenIdCounterNumber % nftsMetadata.length]; + const notificationId = notification.loading("Uploading to IPFS"); + try { + const uploadedItem = await addToIPFS(currentTokenMetaData); + + notification.remove(notificationId); + notification.success("Metadata uploaded to IPFS"); + + // Log IPFS path before sending to contract + console.log("IPFS Path:", uploadedItem.path); + + // Mint the NFT + await writeContractAsync({ + functionName: "mintItem", + args: [uploadedItem.path], + }); + + notification.success("NFT Minted Successfully"); + } catch (error) { + notification.remove(notificationId); + console.error("Error during minting:", error); + + // Log the error and notify the user + notification.error("Minting failed, please try again."); + } + }; + + return ( +
+ {/* User Profile Section */} +
+ {/* Profile Picture */} +
+
+ Profile +
+
+ {/* User Bio */} +
+

John Doe

+

+ NFT collector and digital artist. Passionate about blockchain and decentralized art. +

+
+
+ + {/* Tabs Section */} +
+ + + {/* Content Based on Active Tab */} +
+ {activeTab === "your-nfts" && ( + <> +
+ {!isConnected || isConnecting ? ( + + ) : ( + + )} +
+ + + )} + + {activeTab === "nfts-on-sale" && ( +
+

You currently have no NFTs listed for sale.

+
+ )} + + {activeTab === "past-sales" && ( +
+

You have no past sales yet.

+
+ )} +
+
+
+ ); +}; + +export default MyNFTs; diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx index d466f78..183aee4 100644 --- a/packages/nextjs/app/page.tsx +++ b/packages/nextjs/app/page.tsx @@ -1,20 +1,16 @@ -"use client"; - -// import Image from "next/image"; -// import Link from "next/link"; -import MyNFTs from "./myNFTs/page"; +import Marketplace from "./marketplace/page"; import type { NextPage } from "next"; +import { getMetadata } from "~~/utils/scaffold-eth/getMetadata"; -// import { useAccount } from "wagmi"; - -// import { Address } from "~~/components/scaffold-eth"; +export const metadata = getMetadata({ + title: "Marketplace | Technai", + description: "Built with 🏗 Scaffold-ETH 2", +}); const Home: NextPage = () => { - // const { address: connectedAddress } = useAccount(); - return ( <> - + ); }; diff --git a/packages/nextjs/app/simpleMint/_components/SimpleMint.tsx b/packages/nextjs/app/simpleMint/_components/SimpleMint.tsx new file mode 100644 index 0000000..3bd5ba3 --- /dev/null +++ b/packages/nextjs/app/simpleMint/_components/SimpleMint.tsx @@ -0,0 +1,465 @@ +"use client"; + +import { useEffect, useState } from "react"; +import dynamic from "next/dynamic"; +import { TextAreaBase } from "./TextAreaBase"; +import generateTokenURI from "./generateTokenURI"; +import { SimpleMintDescription } from "./simpleMintDescription"; +import type { NextPage } from "next"; +// import useSWRMutation from "swr/mutation"; +import { useAccount, useSignTypedData } from "wagmi"; +import { InputBase } from "~~/components/scaffold-eth"; +import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth"; +import { EIP_712_DOMAIN, EIP_712_TYPES__START_COLLECTION } from "~~/utils/eip712"; +import { notification } from "~~/utils/scaffold-eth"; +import { addToIPFS } from "~~/utils/simpleNFT/ipfs-fetch"; + +// import nftsMetadata from "~~/utils/simpleNFT/nftsMetadata"; +// import { postMutationFetcher } from "~~/utils/swr"; + +const LazyReactJson = dynamic(() => import("react-json-view"), { ssr: false }); + +export const SimpleMint: NextPage = () => { + const { address: connectedAddress } = useAccount(); + const { signTypedDataAsync } = useSignTypedData(); // Hook for signing the data + + const [collectionName, setCollectionName] = useState(""); + const [collectionSymbol, setCollectionSymbol] = useState(""); + const [description, setDescription] = useState(""); + const [image, setImage] = useState(""); + const [animationUrl, setAnimationUrl] = useState(""); + const [attributes, setAttributes] = useState<{ traitType: string; value: string }[]>([]); + const [usdPrice, setUsdPrice] = useState(""); + const [maxSupply, setMaxSupply] = useState(""); + + const [yourJSON, setYourJSON] = useState({}); + const [loading, setLoading] = useState(false); + const [uploadedIpfsPath, setUploadedIpfsPath] = useState(""); + + const [isGaslessMinting, setIsGaslessMinting] = useState(false); // New toggle state + + const { writeContractAsync } = useScaffoldWriteContract("SimpleMint"); + + const handleToggle = () => { + setIsGaslessMinting(!isGaslessMinting); // Toggle between gasless and paid + }; + + // Function to handle changes in the input fields for trait type and value + const handleAttributeChange = (index: number, field: "traitType" | "value", value: string) => { + const newAttributes = [...attributes]; + newAttributes[index][field] = value; + setAttributes(newAttributes); + }; + + // Function to add a new attribute field + const addAttribute = () => { + setAttributes([...attributes, { traitType: "", value: "" }]); + }; + + // Function to remove an attribute by index + const removeAttribute = (index: number) => { + const newAttributes = attributes.filter((_, i) => i !== index); + setAttributes(newAttributes); + }; + + // Used for database: Check if this is working properly + // const { trigger: postCollectionData } = useSWRMutation("/api/collections/new", postMutationFetcher); // SWR for API call + + // Automatically update the JSON whenever the fields change + useEffect(() => { + // Function that generates the token URI and updates the JSON + const generateTokenURIString = () => { + const tokenURI = generateTokenURI(collectionName, description, image, animationUrl, attributes); + setYourJSON(JSON.parse(atob(tokenURI.split(",")[1]))); + }; + + generateTokenURIString(); + }, [collectionName, description, image, animationUrl, attributes]); + + const handleMPaidMint = async () => { + const notificationId = notification.loading("Uploading to IPFS"); + + try { + const uploadedItem = await addToIPFS(yourJSON); + notification.remove(notificationId); + notification.success("Metadata uploaded to IPFS"); + + // Log IPFS path before sending to contract + console.log("IPFS Path:", uploadedItem.path); + + if (!connectedAddress) { + throw new Error("No connected address found."); + } + + const contractResponse = await writeContractAsync({ + functionName: "startCollection", + args: [ + collectionName, + collectionSymbol, + uploadedItem.path, + connectedAddress, + BigInt(Math.floor(parseInt(usdPrice) * 1e6).toString()), + BigInt(maxSupply), + ], + }); + + if (!contractResponse) { + throw new Error("Contract response is null or undefined."); + } + + console.log("Contract Response:", contractResponse); + notification.success("Collection started successfully!"); + } catch (error) { + notification.remove(notificationId); + + // Type guard to narrow the type of 'error' + if (error instanceof Error) { + console.error("Error during minting:", error); + + if (error.message.includes("gasLimit")) { + notification.error("Minting failed due to gas limit issue, please check your network and wallet setup."); + } else { + notification.error("Minting failed, please try again."); + } + } else { + console.error("An unknown error occurred:", error); + notification.error("An unknown error occurred."); + } + } + }; + + const handleSimpleMint = async () => { + if (!connectedAddress) { + notification.error("Please connect your wallet"); + return; + } + + // Validate inputs + if (!collectionName || !collectionSymbol || !description || !image) { + notification.error("Please fill all the required fields"); + return; + } + + setLoading(true); + const notificationId = notification.loading("Uploading and Signing..."); + + try { + // 1. Upload metadata to IPFS + const uploadedItem = await addToIPFS(yourJSON); + + if (!uploadedItem || !uploadedItem.path) { + throw new Error("Failed to upload metadata to IPFS"); + } + + // 2. Generate signature using EIP-712 + const signature = await signTypedDataAsync({ + domain: EIP_712_DOMAIN, + types: EIP_712_TYPES__START_COLLECTION, + primaryType: "StartCollection", + message: { + collectionName: collectionName, + collectionSymbol: collectionSymbol, + description: description, + image: image, + // image: uploadedItem.path, // To be replaced when image can be uploaded with IPFS + animationUrl: animationUrl, + attributes: JSON.stringify(attributes), // Convert attributes to string + artist: connectedAddress, // Use 'artist' for consistency + }, + }); + + // await postCollectionData({ + // collectionName, + // collectionSymbol, // Add this field + // description, + // image, // Add this field + // attributes: JSON.stringify(attributes), // Convert attributes to string and send + // signature, + // signer: connectedAddress, + // }); + + // 3. Display success message + notification.remove(notificationId); + notification.success("Metadata uploaded and signed!"); + + // 4. Set uploaded IPFS path + setUploadedIpfsPath(uploadedItem.path); + + // Optionally log the signature and IPFS path + console.log("IPFS Path:", uploadedItem.path); + console.log("Signature:", signature); + } catch (error) { + notification.remove(notificationId); + notification.error("Error uploading or signing metadata"); + console.error("Error during upload/sign:", error); + } finally { + setLoading(false); + } + }; + + return ( +
+ + + {/*
+

NFT Preview

+
*/} + +
+ {/* Input Fields Section */} +
+
+

Enter your NFT details here

+ * required fields +
+
+
+ + Collection name * + + +
+
+ + Symbol * + + +
+
+
+ + Description * + + + +
+ +
+ + Image URL * + + +
+
+ Audio/Video URL + +
+ +
+

Attributes

+ + {/* Button to add a new attribute */} + + + {attributes.map((attr, index) => ( +
+ {/* Button to remove the attribute */} + + +
+ Trait Type: + handleAttributeChange(index, "traitType", value)} + /> +
+ +
+ Trait Value: + handleAttributeChange(index, "value", value)} + /> +
+
+ ))} +
+
+ + {/* JSON Display Section */} +
+

NFT Preview

+ + {/* Flex container for media and text */} +
+ {/* Media Section */} + {/* Media Section */} +
+ {image ? ( + NFT Preview + ) : ( +
+ No image provided +
+ )} +
+ + {/* Text Section */} +
+

+ Collection Name:{" "} + {collectionName ? ( + {collectionName} + ) : ( + Not provided + )} +

+

+ Symbol:{" "} + {collectionSymbol ? ( + {collectionSymbol} + ) : ( + Not provided + )} +

+

+ Description:{" "} + {description ? ( + {description} + ) : ( + Not provided + )} +

+ + {/* Conditionally render the attributes section only if there are valid attributes */} + {attributes.length > 0 && attributes.some(attr => attr.traitType && attr.value) && ( + <> +

+ Attributes: +

+
    + {attributes.map( + (attr, index) => + attr.traitType && + attr.value && ( +
  • + {attr.traitType}: {attr.value} +
  • + ), + )} +
+ + )} + + {/* Conditionally render a music player if there is an animationUrl */} + {animationUrl && ( + + )} +
+
+ +
+ +
+ View raw metadata +
+
+ setYourJSON(edit.updated_src)} + onAdd={add => setYourJSON(add.updated_src)} + onDelete={del => setYourJSON(del.updated_src)} + /> +
+
+ +
+
+ + USD Price * + + +
+
+ + Max Supply * + + +
+
+ +
+ {isGaslessMinting ? ( + + ) : ( + + )} + + {/* Toggle Button for Gasless Mint */} + +
+ + {uploadedIpfsPath && ( + + )} +
+
+
+ ); +}; + +// export default SimpleMint; diff --git a/packages/nextjs/app/simpleMint/_components/TextAreaBase.tsx b/packages/nextjs/app/simpleMint/_components/TextAreaBase.tsx index 694387d..95ef08d 100644 --- a/packages/nextjs/app/simpleMint/_components/TextAreaBase.tsx +++ b/packages/nextjs/app/simpleMint/_components/TextAreaBase.tsx @@ -49,7 +49,7 @@ export const TextAreaBase = string } | undefined =
{prefix}