Skip to content

Commit

Permalink
Many UI improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
luloxi committed Sep 22, 2024
1 parent 65c2d60 commit e2b48ea
Show file tree
Hide file tree
Showing 22 changed files with 115 additions and 126 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ Visit your app on: `http://localhost:3000`. You can interact with your smart con

<details><summary>See completed tasks</summary>

### Simple Mint
### NFT Creation

-**Add music to NFTs metadata** and **integrate with frontend** (Reference: [OpenSea metadata-standards](https://docs.opensea.io/docs/metadata-standards))
-**Create a contract for SimpleMint and SimpleMintNFT**
-**Create NFT factory and NFT contract**
-**Page for minting** that takes inputs for the metadata of the NFT (Reference: [scaffold-class](https://github.com/luloxi/scaffold-class))
-**Display NFT being built as a preview** before minting (display the NFT and the metadata)
-**Add an option to start a collection paying gas** on the Simple Mint page, with a toggle to switch between gasless and paying gas
Expand Down Expand Up @@ -88,7 +88,7 @@ Visit your app on: `http://localhost:3000`. You can interact with your smart con

## Phase 3

### Simple Mint
### NFT Creation

-**Simple minting function** for artists to upload their metadata to IPFS and sign a EIP 712 message, and then wait for an investor (first minter) to pay for the contract creation transaction.
- **Implement a database to store the signatures** that allows first minters to start a collection (Reference: [grants.buidlguidl.com](https://github.com/BuidlGuidl/grants.buidlguidl.com))
Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
FIRESTORE_EMULATOR_HOST=localhost:8080

# Setup you project id for firebase
FIREBASE_PROJECT_ID="technai-v1"
FIREBASE_PROJECT_ID="DARTE-v1"

# Setup api-key for admin
ADMIN_API_KEY="admin-api-key"
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

import { useEffect, useState } from "react";
import { AttributesForm } from "./_components/AttributesForm";
import { Description } from "./_components/Description";
import { JSONViewer } from "./_components/JSONViewer";
import { MediaPreview } from "./_components/MediaPreview";
import { MetadataForm } from "./_components/MetadataForm";
import { MintingForm } from "./_components/MintingButtons";
import { RestoreDescriptionButton } from "./_components/RestoreDescriptionButton";
import generateTokenURI from "./_components/generateTokenURI";
import { SimpleMintDescription } from "./_components/simpleMintDescription";
import type { NextPage } from "next";
import { InputBase } from "~~/components/scaffold-eth";

export const SimpleMint: NextPage = () => {
export const Create: NextPage = () => {
const [collectionName, setCollectionName] = useState("");
const [collectionSymbol, setCollectionSymbol] = useState("");
const [description, setDescription] = useState("");
Expand All @@ -21,26 +21,23 @@ export const SimpleMint: NextPage = () => {
const [usdPrice, setUsdPrice] = useState("");
const [maxSupply, setMaxSupply] = useState("");
const [yourJSON, setYourJSON] = useState<object>({});
const [uploadedIpfsPath, setUploadedIpfsPath] = useState(""); // For minting JSON IPFS path
const [uploadedImageIpfsPath, setUploadedImageIpfsPath] = useState(""); // NEW: For image IPFS path
const [descriptionVisible, setDescriptionVisible] = useState(true);
const [enableDebug, setEnableDebug] = useState(false);
// const [enableDebug, setEnableDebug] = useState(false);

useEffect(() => {
const savedVisibility = localStorage.getItem("simpleMintDescriptionVisible");
const savedVisibility = localStorage.getItem("CreateDescriptionVisible");
setDescriptionVisible(savedVisibility !== "false");
}, []);

const handleRestore = () => {
setDescriptionVisible(true);
localStorage.setItem("simpleMintDescriptionVisible", "true");
localStorage.setItem("CreateDescriptionVisible", "true");
};

const resetForm = () => {
setYourJSON({});
setUploadedIpfsPath("");
setUploadedImageIpfsPath(""); // Ensure this is reset
// reset all state except the description
setUploadedImageIpfsPath("");
setCollectionName("");
setCollectionSymbol("");
setDescription("");
Expand All @@ -62,7 +59,7 @@ export const SimpleMint: NextPage = () => {

return (
<>
{descriptionVisible && <SimpleMintDescription />}
{descriptionVisible && <Description />}
<div className="w-full md:w-2/3 md:mx-auto px-0">
<div className="flex flex-col md:flex-row items-start flex-grow">
<div className="w-full px-8 mt-4 bg-base-100 py-6 rounded-lg ">
Expand All @@ -72,7 +69,7 @@ export const SimpleMint: NextPage = () => {
</div>

{/* Metadata and Attributes Forms */}
<div className="flex flex-col gap-3 md:flex-row items-start space-x-4 mb-4">
<div className="flex flex-col gap-3 md:flex-row items-center justify-center space-x-4 mb-4">
<div className="text-left flex-1">
<MetadataForm
collectionName={collectionName}
Expand Down Expand Up @@ -123,11 +120,10 @@ export const SimpleMint: NextPage = () => {
usdPrice={usdPrice}
maxSupply={maxSupply}
yourJSON={yourJSON}
setUploadedIpfsPath={setUploadedIpfsPath} // This manages the metadata IPFS path
resetForm={resetForm}
/>

{uploadedIpfsPath && enableDebug && (
{/* {uploadedIpfsPath && enableDebug && (
<div className="mt-4">
<a href={`https://ipfs.io/ipfs/${uploadedIpfsPath}`} target="_blank" rel="noreferrer">
{`https://ipfs.io/ipfs/${uploadedIpfsPath}`}
Expand All @@ -141,14 +137,14 @@ export const SimpleMint: NextPage = () => {
{`https://ipfs.io/ipfs/${uploadedImageIpfsPath}`}
</a>
</div>
)}
<div className="flex flex-col justify-center items-center mt-6 gap-3">
)} */}
{/* <div className="flex flex-col justify-center items-center mt-6 gap-3">
<div className="flex items-center">
<button className="cool-button mt-4" onClick={() => setEnableDebug(!enableDebug)}>
Debug IPFS uploads
</button>
</div>
</div>
</div> */}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { useEffect, useState } from "react";

export const SimpleMintDescription = () => {
export const Description = () => {
const [isVisible, setIsVisible] = useState(true);

useEffect(() => {
const savedVisibility = localStorage.getItem("simpleMintDescriptionVisible");
const savedVisibility = localStorage.getItem("CreateDescriptionVisible");
if (savedVisibility === "false") {
setIsVisible(false);
}
}, []);

const handleClose = () => {
setIsVisible(false);
localStorage.setItem("simpleMintDescriptionVisible", "false");
localStorage.setItem("CreateDescriptionVisible", "false");
};

if (!isVisible) return null;
Expand All @@ -21,14 +21,14 @@ export const SimpleMintDescription = () => {
<div className="relative self-center md:w-full collapse bg-base-300">
<input type="checkbox" className="collapse-checkbox" />
<div className="collapse-title text-center text-xl font-medium pointer-events-auto">
New to Simple Mint? <strong className="text-green-500">Click here!</strong>
New to NFT creation? <strong className="text-green-500">Click here!</strong>
</div>
<div className="collapse-content">
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-center">
<div className="flex flex-col">
<p>
Simple Mint allows you to <strong className="text-green-600">upload your art and create an NFT</strong> on
a blockchain.
This tool allows you to <strong className="text-green-600">upload your art and create an NFT</strong> on a
blockchain.
<br />
NFTs, or Non-Fungible Tokens,{" "}
<strong className="text-green-600">represent ownership of a piece of content or art</strong>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export const MediaPreview: React.FC<MediaPreviewProps> = ({ image, animationUrl,

return (
<div
className={`relative flex items-center justify-center w-60 h-60 rounded-lg shadow-lg ${
dragActive ? "bg-blue-100 border-2 border-blue-500" : "bg-gray-200"
className={`relative flex items-center justify-center w-60 h-72 rounded-lg shadow-lg ${
dragActive ? "bg-blue-100 border-2 border-blue-600" : "bg-gray-200"
} ${previewImage ? "" : "bg-gray-200"}`}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ interface MintingFormProps {
usdPrice: string;
maxSupply: string;
yourJSON: object;
setUploadedIpfsPath: (path: string) => void;
resetForm: () => void;
}

Expand All @@ -29,7 +28,6 @@ export const MintingForm: React.FC<MintingFormProps> = ({
usdPrice,
maxSupply,
yourJSON,
setUploadedIpfsPath,
resetForm,
}) => {
const { address: connectedAddress } = useAccount();
Expand Down Expand Up @@ -68,7 +66,6 @@ export const MintingForm: React.FC<MintingFormProps> = ({

try {
const ipfsPath = await uploadToIPFS();
setUploadedIpfsPath(ipfsPath);

const contractResponse = await writeContractAsync({
functionName: "startCollection",
Expand Down Expand Up @@ -110,7 +107,6 @@ export const MintingForm: React.FC<MintingFormProps> = ({

try {
const ipfsPath = await uploadToIPFS();
setUploadedIpfsPath(ipfsPath);

const signature = await signTypedDataAsync({
domain: EIP_712_DOMAIN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const RestoreDescriptionButton = ({ handleRestore }: { handleRestore: ()
return (
<div className="flex justify-center my-4">
<button onClick={handleRestore} className="bg-green-500 text-white px-4 py-2 rounded-full">
Restore Simple Mint Info
Restore Create instructions
</button>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { SimpleMint } from "./SimpleMint";
import { Create } from "./Create";
import type { NextPage } from "next";
import { getMetadata } from "~~/utils/scaffold-eth/getMetadata";

export const metadata = getMetadata({
title: "Simple Mint",
title: "Create",
description: "Built with 🏗 Scaffold-ETH 2",
});

const SimpleMintPage: NextPage = () => {
const CreatePage: NextPage = () => {
return (
<>
<SimpleMint />
<Create />
</>
);
};

export default SimpleMintPage;
export default CreatePage;
91 changes: 44 additions & 47 deletions packages/nextjs/app/marketplace/_components/NFTCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,37 +109,36 @@ export const NFTCard = ({ nft }: { nft: Collectible }) => {
width={300} // Same as the original container width
height={300} // Adjust this to maintain the aspect ratio of the image
/>
</figure>

{/* Hover-triggered collapse section */}
<div
className="absolute top-0 left-0 right-0 h-8 flex justify-center items-center bg-base-100 cursor-pointer transition-opacity opacity-0 group-hover:opacity-100"
onClick={() => setIsCollapsed(!isCollapsed)}
>
<div className={`transition-transform ${isCollapsed ? "" : ""}`}>
{isCollapsed ? "▼ Expand" : "▲ Collapse"} {/* Arrow toggles up/down */}
{/* Hover-triggered collapse section */}
<div
className="absolute bottom-0 left-0 right-0 h-8 flex justify-center items-center bg-base-100 cursor-pointer transition-opacity opacity-0 group-hover:opacity-100"
onClick={() => setIsCollapsed(!isCollapsed)}
>
<div className={`transition-transform ${isCollapsed ? "" : ""}`}>
{isCollapsed ? "▼ Expand" : "▲ Collapse"} {/* Arrow toggles up/down */}
</div>
</div>
</div>
</figure>

{!isCollapsed && (
<div className="tabs flex justify-center gap-3">
<div className="tabs flex justify-center gap-3 border-b-4 border-base-200">
{nft.listingId ? (
<a
className={`tab ${activeTab === "buyNFT" ? "bg-red-300 dark:bg-red-800" : ""}`}
className={`tab ${activeTab === "buyNFT" ? "bg-red-800 text-white" : ""}`}
onClick={() => setActiveTab("buyNFT")}
>
Buy NFT
</a>
) : (
<a
className={`tab ${activeTab === "mintNFT" ? "bg-green-300 dark:bg-green-800" : ""}`}
className={`tab ${activeTab === "mintNFT" ? "bg-green-800 text-white" : ""}`}
onClick={() => setActiveTab("mintNFT")}
>
Mint NFT
</a>
)}
<a
className={`tab ${activeTab === "info" ? "bg-blue-300 dark:bg-blue-900" : ""}`}
className={`tab ${activeTab === "info" ? "bg-blue-900 text-white" : ""}`}
onClick={() => setActiveTab("info")}
>
Info
Expand All @@ -149,40 +148,38 @@ export const NFTCard = ({ nft }: { nft: Collectible }) => {

{/* Tab Content */}
{!isCollapsed && activeTab === "mintNFT" && (
<div>
<div className="card-body space-y-3">
{/* Display price and buy button only if price is available */}
{nft.price && nft.payableCurrency && (
<div className="flex flex-row justify-around my-2 space-y-1">
<div>
<div className="flex space-x-3 mt-1 items-center">
<span className="font-semibold">Max Supply: </span>
<span>{nft.maxTokenId}</span>
</div>
<div className="flex flex-row items-center gap-2">
<span className="text-lg">
<b>{formattedPrice}</b> {nft.payableCurrency}
</span>
</div>
<div className="card-body space-y-3">
{/* Display price and buy button only if price is available */}
{nft.price && nft.payableCurrency && (
<div className="flex flex-row justify-around my-2 space-y-1">
<div>
<div className="flex space-x-3 mt-1 items-center">
<span className="font-semibold">Max Supply: </span>
<span>{nft.maxTokenId}</span>
</div>
<div className="flex flex-row items-center gap-2">
<span className="text-lg">
<b>{formattedPrice}</b> {nft.payableCurrency}
</span>
</div>

{/* Conditionally render the Allow button */}
{requiresApproval ? (
<div className="card-actions justify-end">
<button className="cool-button" onClick={handleApproveUSDC}>
Allow USDC
</button>
</div>
) : (
<div className="card-actions justify-end">
<button className="cool-button" onClick={handleBuyNFT}>
Buy NFT
</button>
</div>
)}
</div>
)}
</div>

{/* Conditionally render the Allow button */}
{requiresApproval ? (
<div className="card-actions justify-end">
<button className="cool-button" onClick={handleApproveUSDC}>
Allow USDC
</button>
</div>
) : (
<div className="card-actions justify-end">
<button className="cool-button" onClick={handleBuyNFT}>
Mint
</button>
</div>
)}
</div>
)}
</div>
)}

Expand Down Expand Up @@ -210,7 +207,7 @@ export const NFTCard = ({ nft }: { nft: Collectible }) => {
) : (
<div className="card-actions justify-end">
<button className="cool-button" onClick={handleBuyNFT}>
Buy NFT
Buy
</button>
</div>
)}
Expand Down
Loading

0 comments on commit e2b48ea

Please sign in to comment.