@@ -15,16 +15,46 @@ import {
1515 CheckIcon ,
1616 ChevronDownIcon ,
1717 ChevronUpIcon ,
18+ Loader2 ,
1819} from "lucide-react" ;
1920import { useState } from "react" ;
2021import { useForm } from "react-hook-form" ;
2122import * as z from "zod" ;
22- import { Fieldset } from "components/contract-components/contract-deploy-form/common" ;
23- import { FileInput } from "components/shared/FileInput" ;
24- import { BasisPointsInput } from "components/inputs/BasisPointsInput" ;
25- import { SolidityInput } from "contract-ui/components/solidity-inputs" ;
23+ import Link from "next/link" ;
24+ import Image from "next/image" ;
25+ import { Card , CardContent } from "@/components/ui/card" ;
26+ import {
27+ FormField ,
28+ FormItem ,
29+ FormLabel ,
30+ FormControl ,
31+ FormMessage ,
32+ FormDescription ,
33+ } from "@/components/ui/form" ;
34+ import {
35+ Tooltip ,
36+ TooltipContent ,
37+ TooltipProvider ,
38+ TooltipTrigger ,
39+ } from "@/components/ui/tooltip" ;
2640import { Form } from "@/components/ui/form" ;
2741import { NetworkSelectorButton } from "components/selects/NetworkSelectorButton" ;
42+ import { useActiveAccount , useSwitchActiveWalletChain } from "thirdweb/react" ;
43+ import { deployContractfromDeployMetadata } from "thirdweb/deploys" ;
44+ import { useThirdwebClient } from "@/constants/thirdweb.client" ;
45+ import { defineChain } from "thirdweb/chains" ;
46+ import { toast } from "sonner" ;
47+ import { useDashboardRouter } from "@/lib/DashboardRouter" ;
48+ import { upload } from "thirdweb/storage" ;
49+ import { Fieldset } from "components/contract-components/contract-deploy-form/common" ;
50+ import { FileInput } from "components/shared/FileInput" ;
51+ import {
52+ Select ,
53+ SelectContent ,
54+ SelectItem ,
55+ SelectTrigger ,
56+ SelectValue ,
57+ } from "@/components/ui/select" ;
2858
2959// Form schemas
3060const collectionInfoSchema = z . object ( {
@@ -85,18 +115,20 @@ const StepIndicator = ({
85115) ;
86116
87117export default function CreateNFTPage ( ) {
88- const [ step , setStep ] = useState < number > ( 1 ) ;
89- const [ collectionInfo , setCollectionInfo ] = useState < CollectionInfoValues > ( ) ;
90- const [ mintSettings , setMintSettings ] = useState < MintSettingsValues > ( {
91- price : "0.1" ,
92- supply : "10000" ,
93- initialMint : "1" ,
94- royaltyPercentage : "0" ,
95- royaltyAddress : "" ,
96- collectionType : "new" ,
97- platformFeeBps : "250" ,
98- } ) ;
118+ const [ currentStep , setCurrentStep ] = useState ( 1 ) ;
119+ const [ collectionInfo , setCollectionInfo ] =
120+ useState < CollectionInfoValues | null > ( null ) ;
121+ const [ mintSettings , setMintSettings ] = useState < MintSettingsValues | null > (
122+ null
123+ ) ;
99124 const [ showRoyaltySettings , setShowRoyaltySettings ] = useState ( false ) ;
125+ const [ isDeploying , setIsDeploying ] = useState ( false ) ;
126+ const router = useDashboardRouter ( ) ;
127+ const params = router . params ;
128+ const activeAccount = useActiveAccount ( ) ;
129+ const switchChain = useSwitchActiveWalletChain ( ) ;
130+ const thirdwebClient = useThirdwebClient ( ) ;
131+ const connectedAddress = activeAccount ?. address ;
100132
101133 // Forms
102134 const collectionInfoForm = useForm < CollectionInfoValues > ( {
@@ -127,17 +159,17 @@ export default function CreateNFTPage() {
127159 // Step handlers
128160 const onCollectionInfoSubmit = ( data : CollectionInfoValues ) => {
129161 setCollectionInfo ( data ) ;
130- setStep ( 2 ) ;
162+ setCurrentStep ( 2 ) ;
131163 } ;
132164
133165 const onMintSettingsSubmit = ( data : MintSettingsValues ) => {
134166 setMintSettings ( data ) ;
135- setStep ( 3 ) ;
167+ setCurrentStep ( 3 ) ;
136168 } ;
137169
138170 const goBack = ( ) => {
139- if ( step > 1 ) {
140- setStep ( step - 1 ) ;
171+ if ( currentStep > 1 ) {
172+ setCurrentStep ( currentStep - 1 ) ;
141173 }
142174 } ;
143175
@@ -151,7 +183,7 @@ export default function CreateNFTPage() {
151183 < div className = "w-1/2 flex items-center" >
152184 < div
153185 className = { `h-0.5 w-full ${
154- step > 1 ? "bg-primary/20" : "bg-muted"
186+ currentStep > 1 ? "bg-primary/20" : "bg-muted"
155187 } `}
156188 style = { { marginLeft : "25px" , marginRight : "25px" } }
157189 />
@@ -160,16 +192,16 @@ export default function CreateNFTPage() {
160192 < div className = "w-1/2 flex items-center" >
161193 < div
162194 className = { `h-0.5 w-full ${
163- step > 2 ? "bg-primary/20" : "bg-muted"
195+ currentStep > 2 ? "bg-primary/20" : "bg-muted"
164196 } `}
165197 style = { { marginLeft : "25px" , marginRight : "25px" } }
166198 />
167199 </ div >
168200 </ div >
169201
170- < StepIndicator step = { 1 } currentStep = { step } label = "Basic Info" />
171- < StepIndicator step = { 2 } currentStep = { step } label = "Options" />
172- < StepIndicator step = { 3 } currentStep = { step } label = "Overview" />
202+ < StepIndicator step = { 1 } currentStep = { currentStep } label = "Basic Info" />
203+ < StepIndicator step = { 2 } currentStep = { currentStep } label = "Options" />
204+ < StepIndicator step = { 3 } currentStep = { currentStep } label = "Overview" />
173205 </ div >
174206 </ div >
175207 ) ;
@@ -578,7 +610,11 @@ export default function CreateNFTPage() {
578610 < div >
579611 < h3 className = "text-lg font-medium mb-4 flex justify-between" >
580612 Basic Info
581- < Button variant = "ghost" size = "sm" onClick = { ( ) => setStep ( 1 ) } >
613+ < Button
614+ variant = "ghost"
615+ size = "sm"
616+ onClick = { ( ) => setCurrentStep ( 1 ) }
617+ >
582618 Edit
583619 </ Button >
584620 </ h3 >
@@ -641,7 +677,11 @@ export default function CreateNFTPage() {
641677 < div >
642678 < h3 className = "text-lg font-medium mb-4 flex justify-between" >
643679 Options
644- < Button variant = "ghost" size = "sm" onClick = { ( ) => setStep ( 2 ) } >
680+ < Button
681+ variant = "ghost"
682+ size = "sm"
683+ onClick = { ( ) => setCurrentStep ( 2 ) }
684+ >
645685 Edit
646686 </ Button >
647687 </ h3 >
@@ -719,11 +759,19 @@ export default function CreateNFTPage() {
719759 < Button
720760 type = "button"
721761 className = "bg-primary hover:bg-primary/90"
722- onClick = { ( ) =>
723- alert ( "NFT Collection creation would be processed here" )
724- }
762+ onClick = { deployNFTCollection }
763+ disabled = { isDeploying }
725764 >
726- Deploy Collection < CheckIcon className = "ml-2 h-4 w-4" />
765+ { isDeploying ? (
766+ < >
767+ < Loader2 className = "mr-2 h-4 w-4 animate-spin" /> Deploying
768+ Collection...
769+ </ >
770+ ) : (
771+ < >
772+ Deploy Collection < CheckIcon className = "ml-2 h-4 w-4" />
773+ </ >
774+ ) }
727775 </ Button >
728776 </ div >
729777 </ div >
@@ -733,7 +781,7 @@ export default function CreateNFTPage() {
733781
734782 // Render the appropriate step
735783 const renderCurrentStep = ( ) => {
736- switch ( step ) {
784+ switch ( currentStep ) {
737785 case 1 :
738786 return renderStep1 ( ) ;
739787 case 2 :
@@ -745,5 +793,110 @@ export default function CreateNFTPage() {
745793 }
746794 } ;
747795
796+ // Add this after the existing functions
797+ const deployNFTCollection = async ( ) => {
798+ if ( ! collectionInfo || ! mintSettings || ! activeAccount || ! thirdwebClient ) {
799+ toast . error ( "Missing required information. Please check your inputs." ) ;
800+ return ;
801+ }
802+
803+ setIsDeploying ( true ) ;
804+
805+ try {
806+ // Make sure we have the necessary URL parts
807+ const pathParts = window . location . pathname . split ( "/" ) ;
808+ const teamSlug = pathParts [ 2 ] ;
809+ const projectSlug = pathParts [ 3 ] ;
810+
811+ if ( ! teamSlug || ! projectSlug ) {
812+ throw new Error ( "Invalid URL structure" ) ;
813+ }
814+
815+ console . log ( "Collection info:" , collectionInfo ) ;
816+ console . log ( "Mint settings:" , mintSettings ) ;
817+
818+ // Make sure we have all required collection properties
819+ if (
820+ ! collectionInfo . name ||
821+ ! collectionInfo . symbol ||
822+ ! collectionInfo . chain
823+ ) {
824+ throw new Error ( "Missing required collection information" ) ;
825+ }
826+
827+ // Get wallet chain
828+ const chainId = parseInt ( collectionInfo . chain , 10 ) ;
829+ const walletChain = isNaN ( chainId )
830+ ? defineChain ( { name : collectionInfo . chain . toLowerCase ( ) } )
831+ : defineChain ( { chainId } ) ;
832+
833+ console . log ( "Using chain:" , walletChain ) ;
834+
835+ // Switch network if needed
836+ await switchChain ( { chain : walletChain } ) ;
837+
838+ // Handle collection image
839+ let imageUri = "" ;
840+ if ( collectionInfo . image ) {
841+ try {
842+ const imageFile = await fetch ( collectionInfo . image ) . then ( ( r ) =>
843+ r . blob ( )
844+ ) ;
845+ imageUri = await upload ( {
846+ client : thirdwebClient ,
847+ data : [ imageFile ] ,
848+ } ) ;
849+ } catch ( err ) {
850+ console . error ( "Error uploading image:" , err ) ;
851+ }
852+ }
853+
854+ // Prepare initialization parameters
855+ const initializeParams = {
856+ name : collectionInfo . name ,
857+ symbol : collectionInfo . symbol ,
858+ description : collectionInfo . description || "" ,
859+ primary_sale_recipient :
860+ mintSettings . royaltyAddress || activeAccount . address ,
861+ fee_recipient : mintSettings . royaltyAddress || activeAccount . address ,
862+ seller_fee_basis_points :
863+ parseInt ( mintSettings . royaltyPercentage || "0" ) * 100 ,
864+ } ;
865+
866+ console . log ( "Deploying with parameters:" , initializeParams ) ;
867+
868+ // Deploy the contract
869+ const contractAddress = await deployContractfromDeployMetadata ( {
870+ client : thirdwebClient ,
871+ signer : activeAccount ,
872+ contractMetadata : {
873+ name : collectionInfo . name ,
874+ description : collectionInfo . description || "" ,
875+ image : imageUri ,
876+ external_link : "" ,
877+ } ,
878+ publishMetadata : {
879+ name : "NFTCollection" ,
880+ publisherAddress : activeAccount . address ,
881+ } ,
882+ constructorParams : initializeParams ,
883+ } ) ;
884+
885+ toast . success ( "NFT Collection deployed successfully!" ) ;
886+
887+ // Navigate to the collection's page
888+ router . push (
889+ `/team/${ teamSlug } /${ projectSlug } /contracts/${ contractAddress } `
890+ ) ;
891+ } catch ( error ) {
892+ console . error ( "Error deploying NFT collection:" , error ) ;
893+ toast . error (
894+ `Failed to deploy NFT collection: ${ error instanceof Error ? error . message : "Unknown error" } `
895+ ) ;
896+ } finally {
897+ setIsDeploying ( false ) ;
898+ }
899+ } ;
900+
748901 return < div className = "w-full py-8" > { renderCurrentStep ( ) } </ div > ;
749902}
0 commit comments