From c396913b09ade7f1f2a4825e8ed7f5bd8e17ae40 Mon Sep 17 00:00:00 2001 From: WaDadidou Date: Wed, 27 Mar 2024 14:38:38 +0100 Subject: [PATCH] fix: complete launchpad create collection --- packages/components/inputs/SelectInput.tsx | 2 +- .../SelectFileUploader.type.ts | 1 + .../SelectFileUploader.web.tsx | 24 +-- .../hooks/launchpad/useCreateCollection.ts | 141 ++++++++++++++++ packages/networks/features.ts | 16 +- packages/networks/teritori-testnet/index.ts | 15 +- packages/networks/types.ts | 1 + .../Launchpad/CreateCollection.type.ts | 84 +++++----- .../Launchpad/LaunchpadCreateScreen.tsx | 115 +++++++++---- .../components/ConfigureRoyaltyDetails.tsx | 30 ++-- .../components/ExistingWhitelist.tsx | 19 +-- .../Launchpad/components/LaunchpadSteper.tsx | 3 +- .../Launchpad/components/NewWhitelist.tsx | 55 +++--- .../dropdowns/DropdownProps.type.ts | 22 --- .../dropdowns/SelectionDropdown.tsx | 133 --------------- .../inputs/TextInputLaunchpadRequired.tsx | 2 + .../selectInputs/MultipleSelectInput.tsx} | 26 ++- .../selectInputs/SelectInputLaunchpad.tsx | 158 ++++++++++++++++++ .../LaunchpadAdditional.tsx | 109 ++++++------ .../LaunchpadAssetsAndMetadata.tsx} | 16 +- .../LaunchpadBasic.tsx | 75 ++++++--- .../LaunchpadDetails.tsx | 118 ++++++------- .../LaunchpadMinting.tsx | 76 ++++----- .../LaunchpadTeamAndInvestment.tsx} | 58 +++---- packages/screens/RiotGame/RiotGameScreen.tsx | 77 +++++---- packages/utils/backend.ts | 2 +- 26 files changed, 808 insertions(+), 570 deletions(-) create mode 100644 packages/hooks/launchpad/useCreateCollection.ts delete mode 100644 packages/screens/Launchpad/components/dropdowns/DropdownProps.type.ts delete mode 100644 packages/screens/Launchpad/components/dropdowns/SelectionDropdown.tsx rename packages/screens/Launchpad/components/{dropdowns/MultipleSelectionDropdown.tsx => inputs/selectInputs/MultipleSelectInput.tsx} (86%) create mode 100644 packages/screens/Launchpad/components/inputs/selectInputs/SelectInputLaunchpad.tsx rename packages/screens/Launchpad/components/{ => launchpadCreateSteps}/LaunchpadAdditional.tsx (50%) rename packages/screens/Launchpad/components/{LaunchpadAssetsandMetadata.tsx => launchpadCreateSteps/LaunchpadAssetsAndMetadata.tsx} (76%) rename packages/screens/Launchpad/components/{ => launchpadCreateSteps}/LaunchpadBasic.tsx (51%) rename packages/screens/Launchpad/components/{ => launchpadCreateSteps}/LaunchpadDetails.tsx (50%) rename packages/screens/Launchpad/components/{ => launchpadCreateSteps}/LaunchpadMinting.tsx (58%) rename packages/screens/Launchpad/components/{LaunchpadTeamandInvestment.tsx => launchpadCreateSteps/LaunchpadTeamAndInvestment.tsx} (75%) diff --git a/packages/components/inputs/SelectInput.tsx b/packages/components/inputs/SelectInput.tsx index 3644d7039f..2c8cbe5628 100644 --- a/packages/components/inputs/SelectInput.tsx +++ b/packages/components/inputs/SelectInput.tsx @@ -35,7 +35,7 @@ import { SpacerColumn, SpacerRow } from "../spacer"; export type SelectInputItem = { label: string; - value: string; + value: string | boolean; iconComponent?: ReactElement; }; diff --git a/packages/components/selectFileUploader/SelectFileUploader.type.ts b/packages/components/selectFileUploader/SelectFileUploader.type.ts index d9a4240e74..9fd538d7a4 100644 --- a/packages/components/selectFileUploader/SelectFileUploader.type.ts +++ b/packages/components/selectFileUploader/SelectFileUploader.type.ts @@ -5,6 +5,7 @@ import { LocalFileData } from "../../utils/types/files"; export interface SelectFileUploaderProps { onUpload: (files: LocalFileData[]) => void; + files?: LocalFileData[]; label?: string; style?: StyleProp; isImageCover?: boolean; diff --git a/packages/components/selectFileUploader/SelectFileUploader.web.tsx b/packages/components/selectFileUploader/SelectFileUploader.web.tsx index 65f93c0855..60ad053939 100644 --- a/packages/components/selectFileUploader/SelectFileUploader.web.tsx +++ b/packages/components/selectFileUploader/SelectFileUploader.web.tsx @@ -24,6 +24,7 @@ export const SelectFileUploader: FC = ({ label, style, onUpload, + files, // multiple is not used at true for now, needs to refactor in parents multiple, mimeTypes, @@ -37,7 +38,8 @@ export const SelectFileUploader: FC = ({ }) => { const { setToastError } = useFeedbacks(); const hiddenFileInput = useRef(null); - const [files, setFiles] = useState([]); + const [localFiles, setLocalFiles] = useState([]); + const filesToUse = (!localFiles.length ? files : localFiles) || []; const handleFiles = async (files: File[]) => { const _files = multiple ? files : [files[0]]; @@ -64,7 +66,7 @@ export const SelectFileUploader: FC = ({ const formattedFiles = await Promise.all(supportedFiles.map(formatFile)); - setFiles(formattedFiles); + setLocalFiles(formattedFiles); onUpload(formattedFiles); }; @@ -142,21 +144,23 @@ export const SelectFileUploader: FC = ({ alignItems: "center", justifyContent: "center", height: - files.length > 0 && !multiple ? fileHeight : containerHeight, + filesToUse.length > 0 && !multiple + ? fileHeight + : containerHeight, borderRadius: 12, }} > - {files.length > 0 && !multiple ? ( + {filesToUse.length > 0 && !multiple ? ( <> { - setFiles([]); + setLocalFiles([]); onUpload([]); }} style={{ top: 12, right: 12 }} /> = ({ flex: 1, width: "100%", height: - files.length > 0 && !multiple + filesToUse.length > 0 && !multiple ? fileHeight : containerHeight, alignItems: "center", @@ -180,7 +184,7 @@ export const SelectFileUploader: FC = ({ borderWidth: 1, }} > - {files.length > 0 && multiple ? ( + {filesToUse.length > 0 && multiple ? ( = ({ - {files.length} files selected + {filesToUse.length} files selected = ({ - Select files + {`Select file${multiple ? "s" : ""}`} { + const selectedWallet = useSelectedWallet(); + const userIPFSKey = useSelector(selectNFTStorageAPI); + const { pinataPinFileToIPFS } = useIpfs(); + + return useCallback( + async (collectionFormValues: CreateCollectionFormValues) => { + if (!selectedWallet) return; + + const network = mustGetCosmosNetwork(selectedWallet.networkId); + + const signingComswasmClient = await getKeplrSigningCosmWasmClient( + network.id, + ); + const cosmwasmLaunchpadFeature = getNetworkFeature( + network.id, + NetworkFeature.NFTLaunchpad, + ); + + if (!cosmwasmLaunchpadFeature) return; + + const client = new NftLaunchpadClient( + signingComswasmClient, + selectedWallet.address, + cosmwasmLaunchpadFeature.launchpadContractAddress, + ); + + try { + const pinataJWTKey = + userIPFSKey || + (await generateIpfsKey(network.id, selectedWallet.userId)); + if (!pinataJWTKey) { + console.error("upload file err : No Pinata JWT"); + // setToastError({ + // title: "File upload failed", + // message: "No Pinata JWT", + // }); + return; + } + const fileIpfsHash = await pinataPinFileToIPFS({ + pinataJWTKey, + file: collectionFormValues.coverImage, + } as PinataFileProps); + + client.submitCollection({ + collection: { + name: collectionFormValues.name || "", + desc: collectionFormValues.description || "", + symbol: collectionFormValues.symbol || "", + external_link: collectionFormValues.externalLink || "", + + website_link: collectionFormValues.websiteLink || "", + twitter_profile: collectionFormValues.twitterProfileUrl || "", + twitter_followers_count: + collectionFormValues.nbTwitterFollowers || 0, + contact_discord_name: collectionFormValues.discordName || "", + contact_email: collectionFormValues.email || "", + project_type: collectionFormValues.projectTypes?.join() || "", + project_desc: collectionFormValues.projectDescription || "", + + tokens_count: collectionFormValues.nbTokens || 0, + unit_price: collectionFormValues.unitPrice || "", + limit_per_address: collectionFormValues.perAddressLimit || 0, + start_time: collectionFormValues.startTime || 0, + + team_desc: collectionFormValues.teamDescription || "", + team_link: collectionFormValues.teamLink || "", + partners: collectionFormValues.partnersDescription || "", + + investment_desc: collectionFormValues.investDescription || "", + investment_link: collectionFormValues.investLink || "", + roadmap_link: collectionFormValues.roadmapLink || "", + + artwork_desc: collectionFormValues.artworkDescription || "", + expected_supply: collectionFormValues.expectedSupply || 0, + expected_public_mint_price: + collectionFormValues.expectedPublicMintPrice || 0, + expected_mint_date: collectionFormValues.expectedMintDate || 0, + + // TODO: + // nftApiKey: collectionFormValues.nftApiKey || "", + + cover_img_uri: fileIpfsHash || "", + is_applied_previously: + collectionFormValues.isPreviouslyApplied || false, + is_project_derivative: + collectionFormValues.isDerivativeProject || false, + is_ready_for_mint: collectionFormValues.isReadyForMint || false, + is_dox: collectionFormValues.isDox || false, + escrow_mint_proceeds_period: + collectionFormValues.escrowMintProceedsPeriod || 0, + dao_whitelist_count: collectionFormValues.daoWhitelistCount || 0, + + // TODO: collection of whitelists + + whitelist_mint_infos: [], + + royalty_address: collectionFormValues.royaltyAddress || "", + royalty_percentage: collectionFormValues.royaltyPercentage || 0, + + target_network: network.id, + denom: cosmwasmLaunchpadFeature.defaultMintDenom, + deployed_address: "None", + merkle_root: "None", + whitepaper_link: "None", + base_token_uri: "None", + }, + }); + + // const amount = await tnsClient.mintPrice({ tokenId }); + // return { + // denom: info.native_denom, + // amount: amount?.toString() || "0", + // invalid: false, + // }; + } catch (e) { + // if (e instanceof Error && e.message.includes("Token Name Invalid")) { + // return { denom: info.native_denom, amount: "0", invalid: true }; + // } + // throw e; + } + }, + [], + ); +}; diff --git a/packages/networks/features.ts b/packages/networks/features.ts index 5066c58840..31b325f45b 100644 --- a/packages/networks/features.ts +++ b/packages/networks/features.ts @@ -29,6 +29,18 @@ type CosmWasmSocialFeed = { feedContractAddress: string; }; -export const allFeatureObjects = [zodCosmWasmPremiumFeed]; +const zodCosmWasmLaunchpad = z.object({ + type: z.literal(NetworkFeature.NFTLaunchpad), + launchpadContractAddress: z.string(), + defaultMintDenom: z.string(), + // allowedMintDenoms: z.array(z.string()), // for future +}); + +export type CosmWasmLaunchpad = z.infer; + +export const allFeatureObjects = [zodCosmWasmPremiumFeed, zodCosmWasmLaunchpad]; -export type NetworkFeatureObject = CosmWasmPremiumFeed | CosmWasmSocialFeed; +export type NetworkFeatureObject = + | CosmWasmPremiumFeed + | CosmWasmSocialFeed + | CosmWasmLaunchpad; diff --git a/packages/networks/teritori-testnet/index.ts b/packages/networks/teritori-testnet/index.ts index 14eb1e4344..1b1f294968 100644 --- a/packages/networks/teritori-testnet/index.ts +++ b/packages/networks/teritori-testnet/index.ts @@ -1,5 +1,9 @@ import { teritoriTestnetCurrencies } from "./currencies"; -import { CosmWasmPremiumFeed, NetworkFeature } from "../features"; +import { + CosmWasmLaunchpad, + CosmWasmPremiumFeed, + NetworkFeature, +} from "../features"; import { NetworkInfo, NetworkKind } from "../types"; const nameServiceContractAddress = @@ -12,7 +16,12 @@ const premiumFeedFeature: CosmWasmPremiumFeed = { mintDenom: "utori", }; -const launchpadContractAddress = "tori164jjtp4c032arq30dzpgn2uujwavm777ug7we5evlvf0c26007jqetqdv3"; +const cosmwasmLaunchpadFeature: CosmWasmLaunchpad = { + type: NetworkFeature.NFTLaunchpad, + launchpadContractAddress: + "tori164jjtp4c032arq30dzpgn2uujwavm777ug7we5evlvf0c26007jqetqdv3", + defaultMintDenom: "utori", +}; const riotContractAddressGen0 = "tori1hzz0s0ucrhdp6tue2lxk3c03nj6f60qy463we7lgx0wudd72ctmstg4wkc"; @@ -37,7 +46,7 @@ export const teritoriTestnetNetwork: NetworkInfo = { NetworkFeature.CosmWasmPremiumFeed, NetworkFeature.NFTMarketplaceLeaderboard, ], - featureObjects: [premiumFeedFeature], + featureObjects: [premiumFeedFeature, cosmwasmLaunchpadFeature], currencies: teritoriTestnetCurrencies, txExplorer: "https://explorer.teritori.com/teritori-testnet/tx/$hash", accountExplorer: diff --git a/packages/networks/types.ts b/packages/networks/types.ts index 6cc93c45b7..2d8e61185e 100644 --- a/packages/networks/types.ts +++ b/packages/networks/types.ts @@ -72,6 +72,7 @@ export type CosmosNetworkInfo = NetworkInfoBase & { daoVotingCw4CodeId?: number; daoFactoryContractAddress?: string; coreDAOAddress?: string; + launchpadContractAddress?: string; }; export type EthereumNetworkInfo = NetworkInfoBase & { diff --git a/packages/screens/Launchpad/CreateCollection.type.ts b/packages/screens/Launchpad/CreateCollection.type.ts index 94e6093e24..d089853e79 100644 --- a/packages/screens/Launchpad/CreateCollection.type.ts +++ b/packages/screens/Launchpad/CreateCollection.type.ts @@ -1,65 +1,61 @@ -export interface NewCollectionAssetsFormValues { - nftApiKey?: string; -} +import { WhitelistMintInfo } from "@/api/launchpad/v1/launchpad"; +import { Uint128 } from "@/contracts-clients/nft-launchpad"; +import { LocalFileData } from "@/utils/types/files"; export interface ExistingBaseUrlFormValues { baseTokenUri?: string; coverImageUrl?: string; } -export interface NewCollectionBasicFormValues { +export interface CreateCollectionFormValues { name?: string; description?: string; symbol?: string; externalLink?: string; -} -export interface NewCollectionDetailsFormValues { websiteLink?: string; twitterProfileUrl?: string; - twitterFollowers: string; + nbTwitterFollowers?: number; discordName?: string; email?: string; - projectType?: string; - projectDesciption?: string; -} - -export interface NewCollectionMintFormValues { - token?: string; - unitPrice?: string; - perAddressLimit: string; - startTime?: string; -} -export interface TeamandInvestmentFormValues { - teamDesciption?: string; + projectTypes?: string[]; + projectDescription?: string; + nbTokens?: number; + unitPrice?: Uint128; + perAddressLimit?: number; + startTime?: number; + teamDescription?: string; teamLink?: string; - partner?: string; - investDesciption?: string; + partnersDescription?: string; + investDescription?: string; investLink?: string; - roadmap?: string; -} - -export interface NewCollectionAdditionalFormValues { - artwork?: string; - collectionSupply?: string; - mintPrice?: string; - mintDate?: string; - whitelistSpotPercentage?: string; -} - -export interface ExistingWhitelistDetailsFormValues { - whitelistAddress: string; + roadmapLink?: string; + artworkDescription?: string; + expectedSupply?: number; + expectedPublicMintPrice?: number; + expectedMintDate?: number; + nftApiKey?: string; + coverImage?: LocalFileData; + isPreviouslyApplied?: boolean; + isDerivativeProject?: boolean; + isReadyForMint?: boolean; + isDox?: boolean; + escrowMintProceedsPeriod?: number; + daoWhitelistCount?: number; + whitelistMintInfos: WhitelistMintInfo[]; + royaltyAddress?: string; + royaltyPercentage?: number; } -export interface NewWhitelistDetailsFormValues { - unitPrice: string; - memberLimit: string; - perAddresaLimit: string; - startTime: string; - endTime: string; +export interface CreateCollectionWhitelist { + addressesCount?: number; + denom?: string; + endTime?: number; + perAddressLimit?: number; + merkleRoot?: string; + startTime?: number; + unitPrice?: Uint128; } - -export interface NewConfigureRoyaltyDetailsFormValues { - PaymentAddress: string; - SharePercentage: string; +export interface NewCollectionAssetsFormValues { + nftApiKey?: string; } export interface NewMetadataDetailsFormValues { diff --git a/packages/screens/Launchpad/LaunchpadCreateScreen.tsx b/packages/screens/Launchpad/LaunchpadCreateScreen.tsx index 59de032397..6d0b489e78 100644 --- a/packages/screens/Launchpad/LaunchpadCreateScreen.tsx +++ b/packages/screens/Launchpad/LaunchpadCreateScreen.tsx @@ -1,38 +1,60 @@ -import React, { useState } from "react"; +import React, { FC, useState } from "react"; +import { useForm, UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { LaunchpadAdditional } from "./components/LaunchpadAdditional"; -import { LaunchpadAssetsandMetadata } from "./components/LaunchpadAssetsandMetadata"; -import { LaunchpadBasic } from "./components/LaunchpadBasic"; -import { LaunchpadDetails } from "./components/LaunchpadDetails"; -import { LaunchpadMinting } from "./components/LaunchpadMinting"; -import { LaunchpadSteper } from "./components/LaunchpadSteper"; -import { LaunchpadTeamandInvestment } from "./components/LaunchpadTeamandInvestment"; - import { BrandText } from "@/components/BrandText"; import { ScreenContainer } from "@/components/ScreenContainer"; import { PrimaryButton } from "@/components/buttons/PrimaryButton"; import { SecondaryButton } from "@/components/buttons/SecondaryButton"; import { SpacerColumn } from "@/components/spacer"; +import { useCreateCollection } from "@/hooks/launchpad/useCreateCollection"; import { NetworkFeature } from "@/networks"; +import { CreateCollectionFormValues } from "@/screens/Launchpad/CreateCollection.type"; +import { LaunchpadSteper } from "@/screens/Launchpad/components/LaunchpadSteper"; +import { LaunchpadAdditional } from "@/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAdditional"; +import { LaunchpadAssetsAndMetadata } from "@/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAssetsAndMetadata"; +import { LaunchpadBasic } from "@/screens/Launchpad/components/launchpadCreateSteps/LaunchpadBasic"; +import { LaunchpadDetails } from "@/screens/Launchpad/components/launchpadCreateSteps/LaunchpadDetails"; +import { LaunchpadMinting } from "@/screens/Launchpad/components/launchpadCreateSteps/LaunchpadMinting"; +import { LaunchpadTeamAndInvestment } from "@/screens/Launchpad/components/launchpadCreateSteps/LaunchpadTeamAndInvestment"; import { ScreenFC, useAppNavigation } from "@/utils/navigation"; import { neutral33 } from "@/utils/style/colors"; import { layout } from "@/utils/style/layout"; +import { LocalFileData } from "@/utils/types/files"; -const StepContent = ({ step }: { step: number }) => { +const StepContent: FC<{ + step: number; + createCollectionForm: UseFormReturn; + onChangeCoverImage: (file: LocalFileData) => void; +}> = ({ step, createCollectionForm, onChangeCoverImage }) => { switch (step) { case 1: - return ; + return ( + + ); case 2: - return ; + return ; case 3: - return ; + return ( + + ); case 4: - return ; + return ( + + ); case 5: - return ; + return ; case 6: - return ; + return ( + + ); default: return <>; } @@ -49,12 +71,24 @@ const stepOptions = [ export const LaunchpadCreateScreen: ScreenFC<"LaunchpadCreate"> = () => { const navigation = useAppNavigation(); - + const createCollectionForm = useForm({ + mode: "all", + }); + const createCollection = useCreateCollection(); + const [coverImage, setCoverImage] = useState(); const [selectedStep, setSelectedStep] = useState(1); const [isLoading, setLoading] = useState(false); - const onSubmit = () => { + const onSubmit = async () => { setLoading(true); + + try { + await createCollection(createCollectionForm.getValues()); + setLoading(false); + } catch (e) { + console.error("Error creating a NFT collection"); + setLoading(false); + } setTimeout(() => { setLoading(false); }, 1000); @@ -66,7 +100,7 @@ export const LaunchpadCreateScreen: ScreenFC<"LaunchpadCreate"> = () => { noMargin noScroll={false} footerChildren={<>} - forceNetworkFeatures={[NetworkFeature.SocialFeed]} + forceNetworkFeatures={[NetworkFeature.NFTLaunchpad]} headerChildren={Launchpad Submission Form} onBackPress={() => navigation.navigate("LaunchpadApply")} > @@ -88,7 +122,11 @@ export const LaunchpadCreateScreen: ScreenFC<"LaunchpadCreate"> = () => { }} > - + setCoverImage(file)} + /> = () => { }} /> )} - { - if (stepOptions.length === selectedStep) { - onSubmit(); - } else { - setSelectedStep(selectedStep + 1); + + {stepOptions.length === selectedStep ? ( + + onPress={() => { + createCollectionForm.handleSubmit(onSubmit); + }} + /> + ) : ( + setSelectedStep(selectedStep + 1)} + /> + )} diff --git a/packages/screens/Launchpad/components/ConfigureRoyaltyDetails.tsx b/packages/screens/Launchpad/components/ConfigureRoyaltyDetails.tsx index a860034455..880f84e23f 100644 --- a/packages/screens/Launchpad/components/ConfigureRoyaltyDetails.tsx +++ b/packages/screens/Launchpad/components/ConfigureRoyaltyDetails.tsx @@ -1,12 +1,12 @@ import React from "react"; -import { useForm } from "react-hook-form"; +import { UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { TextInputLaunchpadRequiredSublabel } from "./inputs/TextInputLaunchpadRequiredSublabel"; -import { NewConfigureRoyaltyDetailsFormValues } from "../CreateCollection.type"; +import { CreateCollectionFormValues } from "../CreateCollection.type"; import { BrandText } from "@/components/BrandText"; import { SpacerColumn } from "@/components/spacer"; +import { TextInputLaunchpadRequired } from "@/screens/Launchpad/components/inputs/TextInputLaunchpadRequired"; import { neutral55, neutral77 } from "@/utils/style/colors"; import { fontSemibold13, @@ -14,15 +14,9 @@ import { fontSemibold20, } from "@/utils/style/fonts"; -export const ConfigureRoyaltyDetails: React.FC = () => { - const { control } = useForm({ - defaultValues: { - PaymentAddress: "", - SharePercentage: "", - }, - mode: "onBlur", - }); - +export const ConfigureRoyaltyDetails: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { return ( @@ -33,10 +27,10 @@ export const ConfigureRoyaltyDetails: React.FC = () => { - + label="Payment Address " placeHolder="teritori123456789qwertyuiopasdfghjklzxcvbnm" - name="PaymentAddress" + name="royaltyAddress" sublabel={ @@ -44,13 +38,13 @@ export const ConfigureRoyaltyDetails: React.FC = () => { } - control={control} + control={createCollectionForm.control} /> - + label="Share Percentage " placeHolder="8%" - name="SharePercentage" + name="royaltyPercentage" sublabel={ @@ -58,7 +52,7 @@ export const ConfigureRoyaltyDetails: React.FC = () => { } - control={control} + control={createCollectionForm.control} /> ); diff --git a/packages/screens/Launchpad/components/ExistingWhitelist.tsx b/packages/screens/Launchpad/components/ExistingWhitelist.tsx index 107a6dcb96..bc152c043c 100644 --- a/packages/screens/Launchpad/components/ExistingWhitelist.tsx +++ b/packages/screens/Launchpad/components/ExistingWhitelist.tsx @@ -1,20 +1,15 @@ import React from "react"; -import { useForm } from "react-hook-form"; +import { UseFormReturn } from "react-hook-form"; import { View } from "react-native"; import { TextInputLaunchpadRequired } from "./inputs/TextInputLaunchpadRequired"; -import { ExistingWhitelistDetailsFormValues } from "../CreateCollection.type"; +import { CreateCollectionFormValues } from "../CreateCollection.type"; import { SpacerColumn } from "@/components/spacer"; -export const ExistingWhitelist: React.FC = () => { - const { control } = useForm({ - defaultValues: { - whitelistAddress: "", - }, - mode: "onBlur", - }); - +export const ExistingWhitelist: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { return ( { > - + label="Whitelist Address" placeHolder="teritori123456789qwertyuiopasdfghjklzxcvbnm" name="whitelistAddress" - control={control} + control={createCollectionForm.control} /> ); diff --git a/packages/screens/Launchpad/components/LaunchpadSteper.tsx b/packages/screens/Launchpad/components/LaunchpadSteper.tsx index 1e490f0d2f..60286177fc 100644 --- a/packages/screens/Launchpad/components/LaunchpadSteper.tsx +++ b/packages/screens/Launchpad/components/LaunchpadSteper.tsx @@ -1,8 +1,7 @@ import React from "react"; import { TouchableOpacity, View } from "react-native"; -import ChevronRightSvg from "../../../../assets/icons/chevron-right.svg"; - +import ChevronRightSvg from "@/assets/icons/chevron-right.svg"; import { BrandText } from "@/components/BrandText"; import { SVG } from "@/components/SVG"; import { PrimaryBox } from "@/components/boxes/PrimaryBox"; diff --git a/packages/screens/Launchpad/components/NewWhitelist.tsx b/packages/screens/Launchpad/components/NewWhitelist.tsx index c9a7d0b1e0..b40e08777d 100644 --- a/packages/screens/Launchpad/components/NewWhitelist.tsx +++ b/packages/screens/Launchpad/components/NewWhitelist.tsx @@ -1,14 +1,17 @@ import React from "react"; -import { useForm } from "react-hook-form"; +import { useForm, UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { TextInputLaunchpadRequiredSublabel } from "./inputs/TextInputLaunchpadRequiredSublabel"; -import { NewWhitelistDetailsFormValues } from "../CreateCollection.type"; +import { + CreateCollectionFormValues, + CreateCollectionWhitelist, +} from "../CreateCollection.type"; import { BrandText } from "@/components/BrandText"; import { SelectFileUploader } from "@/components/selectFileUploader"; import { Separator } from "@/components/separators/Separator"; import { SpacerColumn } from "@/components/spacer"; +import { TextInputLaunchpadRequired } from "@/screens/Launchpad/components/inputs/TextInputLaunchpadRequired"; import { IMAGE_MIME_TYPES } from "@/utils/mime"; import { ARTICLE_THUMBNAIL_IMAGE_MAX_HEIGHT } from "@/utils/social-feed"; import { neutral55, neutral77 } from "@/utils/style/colors"; @@ -18,19 +21,19 @@ import { fontSemibold20, } from "@/utils/style/fonts"; import { layout } from "@/utils/style/layout"; +import { LocalFileData } from "@/utils/types/files"; -export const NewWhitelist: React.FC = () => { - const { control } = useForm({ - defaultValues: { - unitPrice: "", - memberLimit: "", - perAddresaLimit: "", - startTime: "", - endTime: "", - }, +export const NewWhitelist: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { + const { control } = useForm({ mode: "onBlur", }); + const onUploadWhitelistFile = (files: LocalFileData[]) => { + // TODO: Parse addresses from the TXT file and createCollectionForm.setValue("whitelistAddresses", blabla) + }; + return ( @@ -40,7 +43,8 @@ export const NewWhitelist: React.FC = () => { Information about your minting settings - + + label="Unit Price " placeHolder="0" name="unitPrice" @@ -54,24 +58,10 @@ export const NewWhitelist: React.FC = () => { control={control} /> - - label="Member Limit " - placeHolder="0" - name="memberLimit" - sublabel={ - - - Maximum number of whitelisted addresses - - - } - control={control} - /> - - + label="Per Address Limit" placeHolder="0" - name="perAddresaLimit" + name="perAddressLimit" sublabel={ @@ -82,7 +72,7 @@ export const NewWhitelist: React.FC = () => { control={control} /> - + label="Start Time " placeHolder="0" name="startTime" @@ -96,7 +86,7 @@ export const NewWhitelist: React.FC = () => { control={control} /> - + label="End Time " placeHolder="0" name="endTime" @@ -118,6 +108,7 @@ export const NewWhitelist: React.FC = () => { TXT file that contains the whitelisted addresses + { width: 416, }} containerHeight={48} - onUpload={(files) => {}} + onUpload={onUploadWhitelistFile} mimeTypes={IMAGE_MIME_TYPES} /> diff --git a/packages/screens/Launchpad/components/dropdowns/DropdownProps.type.ts b/packages/screens/Launchpad/components/dropdowns/DropdownProps.type.ts deleted file mode 100644 index 1a60de0b94..0000000000 --- a/packages/screens/Launchpad/components/dropdowns/DropdownProps.type.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ViewStyle } from "react-native"; - -export interface SelectionDropdownProps { - style?: ViewStyle; - onDropdownClosed?: () => void; - dropdownOptions: string[]; - placeHolder?: string; - setItem: (item: string) => void; - item?: string; - label: string; -} - -export interface MultipleSelectionDropdownProps { - style?: ViewStyle; - onDropdownClosed?: () => void; - dropdownOptions: string[]; - placeHolder?: string; - setItems: (item: string) => void; - items: string[]; - label: string; - sublabel?: React.ReactElement; -} diff --git a/packages/screens/Launchpad/components/dropdowns/SelectionDropdown.tsx b/packages/screens/Launchpad/components/dropdowns/SelectionDropdown.tsx deleted file mode 100644 index e6e9154a00..0000000000 --- a/packages/screens/Launchpad/components/dropdowns/SelectionDropdown.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import React from "react"; -import { TouchableOpacity, View } from "react-native"; - -import chevronDownSVG from "./../../../../../assets/icons/chevron-down.svg"; -import chevronUpSVG from "./../../../../../assets/icons/chevron-up.svg"; -import { SelectionDropdownProps } from "./DropdownProps.type"; - -import { BrandText } from "@/components/BrandText"; -import { SVG } from "@/components/SVG"; -import { PrimaryBox } from "@/components/boxes/PrimaryBox"; -import { TertiaryBox } from "@/components/boxes/TertiaryBox"; -import { Label } from "@/components/inputs/TextInputCustom"; -import { Separator } from "@/components/separators/Separator"; -import { SpacerColumn } from "@/components/spacer"; -import { useDropdowns } from "@/hooks/useDropdowns"; -import { - neutral17, - neutral44, - neutral55, - neutral77, - secondaryColor, -} from "@/utils/style/colors"; -import { fontMedium14, fontSemibold14 } from "@/utils/style/fonts"; -import { layout } from "@/utils/style/layout"; - -export const SelectionDropdown = ({ - style, - dropdownOptions, - placeHolder, - item, - label, - setItem, -}: SelectionDropdownProps) => { - const [isDropdownOpen, setDropdownState, ref] = useDropdowns(); - - return ( - - - - - - setDropdownState()} - > - - {item ? item : placeHolder} - - - - - - {isDropdownOpen && ( - - {dropdownOptions.map((item, index) => ( - { - setDropdownState(false); - setItem(item); - }} - key={index} - style={{ - paddingTop: layout.spacing_x1_5, - width: "100%", - }} - > - - {item} - - - {dropdownOptions.length - 1 !== index && ( - <> - - - - )} - - ))} - - )} - - - ); -}; diff --git a/packages/screens/Launchpad/components/inputs/TextInputLaunchpadRequired.tsx b/packages/screens/Launchpad/components/inputs/TextInputLaunchpadRequired.tsx index 81cace33b9..8e06e2f9dd 100644 --- a/packages/screens/Launchpad/components/inputs/TextInputLaunchpadRequired.tsx +++ b/packages/screens/Launchpad/components/inputs/TextInputLaunchpadRequired.tsx @@ -20,6 +20,7 @@ export const TextInputLaunchpadRequired = ({ name, label, placeHolder, + sublabel, required = true, }: TextInputCustomProps) => { return ( @@ -27,6 +28,7 @@ export const TextInputLaunchpadRequired = ({ required={required} label={label} placeHolder={placeHolder} + sublabel={sublabel} name={name} control={control} /> diff --git a/packages/screens/Launchpad/components/dropdowns/MultipleSelectionDropdown.tsx b/packages/screens/Launchpad/components/inputs/selectInputs/MultipleSelectInput.tsx similarity index 86% rename from packages/screens/Launchpad/components/dropdowns/MultipleSelectionDropdown.tsx rename to packages/screens/Launchpad/components/inputs/selectInputs/MultipleSelectInput.tsx index 71fe7a422c..a46165e308 100644 --- a/packages/screens/Launchpad/components/dropdowns/MultipleSelectionDropdown.tsx +++ b/packages/screens/Launchpad/components/inputs/selectInputs/MultipleSelectInput.tsx @@ -1,11 +1,10 @@ -import React from "react"; -import { TouchableOpacity, View } from "react-native"; +import React, { FC } from "react"; +import { TouchableOpacity, View, ViewStyle } from "react-native"; -import chevronDownSVG from "./../../../../../assets/icons/chevron-down.svg"; -import chevronUpSVG from "./../../../../../assets/icons/chevron-up.svg"; -import { MultipleSelectionDropdownProps } from "./DropdownProps.type"; -import { CheckboxDappStore } from "../../../DAppStore/components/CheckboxDappStore"; +import { CheckboxDappStore } from "../../../../DAppStore/components/CheckboxDappStore"; +import chevronDownSVG from "@/assets/icons/chevron-down.svg"; +import chevronUpSVG from "@/assets/icons/chevron-up.svg"; import { BrandText } from "@/components/BrandText"; import { SVG } from "@/components/SVG"; import { PrimaryBox } from "@/components/boxes/PrimaryBox"; @@ -24,7 +23,18 @@ import { import { fontMedium14, fontSemibold14 } from "@/utils/style/fonts"; import { layout } from "@/utils/style/layout"; -export const MultipleSelectionDropdown = ({ +interface Props { + style?: ViewStyle; + onDropdownClosed?: () => void; + dropdownOptions: string[]; + placeHolder?: string; + setItems: (item: string) => void; + items: string[]; + label: string; + sublabel?: React.ReactElement; +} + +export const MultipleSelectInput: FC = ({ style, dropdownOptions, placeHolder, @@ -32,7 +42,7 @@ export const MultipleSelectionDropdown = ({ label, setItems, sublabel, -}: MultipleSelectionDropdownProps) => { +}) => { const [isDropdownOpen, setDropdownState, ref] = useDropdowns(); return ( diff --git a/packages/screens/Launchpad/components/inputs/selectInputs/SelectInputLaunchpad.tsx b/packages/screens/Launchpad/components/inputs/selectInputs/SelectInputLaunchpad.tsx new file mode 100644 index 0000000000..30735613d8 --- /dev/null +++ b/packages/screens/Launchpad/components/inputs/selectInputs/SelectInputLaunchpad.tsx @@ -0,0 +1,158 @@ +import React, { FC, useState } from "react"; +import { TouchableOpacity, View, ViewStyle } from "react-native"; + +import chevronDownSVG from "@/assets/icons/chevron-down.svg"; +import chevronUpSVG from "@/assets/icons/chevron-up.svg"; +import { BrandText } from "@/components/BrandText"; +import { SVG } from "@/components/SVG"; +import { PrimaryBox } from "@/components/boxes/PrimaryBox"; +import { TertiaryBox } from "@/components/boxes/TertiaryBox"; +import { CustomPressable } from "@/components/buttons/CustomPressable"; +import { Label } from "@/components/inputs/TextInputCustom"; +import { Separator } from "@/components/separators/Separator"; +import { SpacerColumn } from "@/components/spacer"; +import { useDropdowns } from "@/hooks/useDropdowns"; +import { + neutral17, + neutral44, + neutral55, + neutral77, + secondaryColor, +} from "@/utils/style/colors"; +import { fontMedium14, fontSemibold14 } from "@/utils/style/fonts"; +import { layout } from "@/utils/style/layout"; + +interface Props { + style?: ViewStyle; + onDropdownClosed?: () => void; + dropdownOptions: string[]; + placeHolder?: string; + setItem: (item: string) => void; + item?: string; + label: string; +} + +export const SelectInputLaunchpad: FC = ({ + style, + dropdownOptions, + placeHolder, + item, + label, + setItem, +}) => { + const [isDropdownOpen, setDropdownState, ref] = useDropdowns(); + const [hovered, setHovered] = useState(false); + + return ( + + setHovered(true)} + onHoverOut={() => setHovered(false)} + onPress={() => setDropdownState()} + > + + + + + setDropdownState()} + > + + {item ? item : placeHolder} + + + + + + {isDropdownOpen && ( + + {dropdownOptions.map((item, index) => ( + { + setDropdownState(false); + setItem(item); + }} + key={index} + style={{ + paddingTop: layout.spacing_x1_5, + width: "100%", + }} + > + + {item} + + + {dropdownOptions.length - 1 !== index && ( + <> + + + + )} + + ))} + + )} + + + + ); +}; diff --git a/packages/screens/Launchpad/components/LaunchpadAdditional.tsx b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAdditional.tsx similarity index 50% rename from packages/screens/Launchpad/components/LaunchpadAdditional.tsx rename to packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAdditional.tsx index 98cfd9ca71..4fdd2f115e 100644 --- a/packages/screens/Launchpad/components/LaunchpadAdditional.tsx +++ b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAdditional.tsx @@ -1,11 +1,10 @@ -import React, { useState } from "react"; -import { useForm } from "react-hook-form"; +import React from "react"; +import { UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { SelectionDropdown } from "./dropdowns/SelectionDropdown"; -import { TextInputLaunchpadRequired } from "./inputs/TextInputLaunchpadRequired"; -import { TextInputLaunchpadRequiredSublabel } from "./inputs/TextInputLaunchpadRequiredSublabel"; -import { NewCollectionAdditionalFormValues } from "../CreateCollection.type"; +import { CreateCollectionFormValues } from "../../CreateCollection.type"; +import { TextInputLaunchpadRequired } from "../inputs/TextInputLaunchpadRequired"; +import { SelectInputLaunchpad } from "../inputs/selectInputs/SelectInputLaunchpad"; import { BrandText } from "@/components/BrandText"; import { SpacerColumn } from "@/components/spacer"; @@ -16,23 +15,14 @@ import { fontSemibold20, } from "@/utils/style/fonts"; -export const LaunchpadAdditional: React.FC = () => { - const dropdownOptions = ["Yes", "No"]; - - const [isReadyForMint, setIsReadyForMint] = useState(""); - const [isEscrowMintProceeds, setIsEscrowMintProceeds] = useState(""); - const [isDox, setIsDox] = useState(""); - - const { control } = useForm({ - defaultValues: { - artwork: "", - collectionSupply: "", - mintPrice: "", - mintDate: "", - whitelistSpotPercentage: "", - }, - mode: "onBlur", - }); +export const LaunchpadAdditional: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { + const isReadyForMint = createCollectionForm.watch("isReadyForMint"); + const escrowMintProceedsPeriod = createCollectionForm.watch( + "escrowMintProceedsPeriod", + ); + const isDox = createCollectionForm.watch("isDox"); return ( @@ -44,8 +34,8 @@ export const LaunchpadAdditional: React.FC = () => { - - label="Please describe your artwork: " + + label="Please describe your artworkDescription: " sublabel={ @@ -60,27 +50,35 @@ export const LaunchpadAdditional: React.FC = () => { } placeHolder="Describe here..." - name="artwork" - control={control} + name="artworkDescription" + control={createCollectionForm.control} multiline /> - { + createCollectionForm.setValue("isReadyForMint", item === "Yes"); + }} label="Is your collection ready for the mint?" /> - + label="What is your expected collection supply?" placeHolder="Type here..." - name="collectionSupply" - control={control} + name="expectedSupply" + control={createCollectionForm.control} /> - + label="What is your expected public sale mint price?" sublabel={ @@ -90,40 +88,47 @@ export const LaunchpadAdditional: React.FC = () => { } placeHolder="0" - name="mintPrice" - control={control} + name="expectedPublicMintPrice" + control={createCollectionForm.control} /> - + label="What is your expected mint date? " placeHolder="dd.mm.yyyy | hh:mm PM" - name="mintDate" - control={control} + name="expectedMintDate" + control={createCollectionForm.control} /> - { + createCollectionForm.setValue( + "escrowMintProceedsPeriod", + parseInt(item, 10), + ); + }} + label="If selected for the launchpad, You will escrow mint proceeds for this time period:" style={{ zIndex: 2 }} /> - { + createCollectionForm.setValue("isDox", item === "Yes"); + }} label="Are you dox or have you planned to dox?" style={{ zIndex: 1 }} /> - + label="We'd love to offer TeritoriDAO members 10% of your whitelist supply if your project is willing. Please let us know how many whitelist spots you'd be willing to allocate our DAO: " placeHolder="0" - name="whitelistSpotPercentage" - control={control} + name="daoWhitelistCount" + control={createCollectionForm.control} /> diff --git a/packages/screens/Launchpad/components/LaunchpadAssetsandMetadata.tsx b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAssetsAndMetadata.tsx similarity index 76% rename from packages/screens/Launchpad/components/LaunchpadAssetsandMetadata.tsx rename to packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAssetsAndMetadata.tsx index b51515d79a..119f4913e8 100644 --- a/packages/screens/Launchpad/components/LaunchpadAssetsandMetadata.tsx +++ b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadAssetsAndMetadata.tsx @@ -1,16 +1,18 @@ import React, { useState } from "react"; +import { UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { AssetsTab } from "./AssetsTab"; -import { UriTab } from "./UriTab"; +import { AssetsTab } from "../AssetsTab"; +import { UriTab } from "../UriTab"; import { BrandText } from "@/components/BrandText"; import { SpacerColumn } from "@/components/spacer"; import { Tabs } from "@/components/tabs/Tabs"; +import { CreateCollectionFormValues } from "@/screens/Launchpad/CreateCollection.type"; import { neutral77, primaryColor } from "@/utils/style/colors"; import { fontSemibold14, fontSemibold28 } from "@/utils/style/fonts"; -const AssetsandMetadataTabItems = { +const AssetsAndMetadataTabItems = { assets: { name: "Upload assets & metadata", }, @@ -19,9 +21,11 @@ const AssetsandMetadataTabItems = { }, }; -export const LaunchpadAssetsandMetadata: React.FC = () => { +export const LaunchpadAssetsAndMetadata: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { const [selectedTab, setSelectedTab] = - useState("assets"); + useState("assets"); return ( { { - const { control } = useForm({ - defaultValues: { - name: "", - description: "", - symbol: "", - externalLink: "", - }, - mode: "onBlur", - }); +export const LaunchpadBasic: React.FC<{ + createCollectionForm: UseFormReturn; + onChangeCoverImage: (file: LocalFileData) => void; +}> = ({ createCollectionForm, onChangeCoverImage }) => { + const coverImage = createCollectionForm.watch("coverImage"); return ( @@ -58,28 +56,48 @@ export const LaunchpadBasic: React.FC = () => { - + {/**/} + {/* noBrokenCorners*/} + {/* variant="labelOutside"*/} + {/* control={control}*/} + {/* label="Organization's name"*/} + {/* placeHolder="Type organization's name here"*/} + {/* name="organizationName"*/} + {/* rules={{ required: true }}*/} + {/*/>*/} + + label="Name" placeHolder="My Awesome Collection" name="name" - control={control} + control={createCollectionForm.control} + // control={control} + onChangeText={(e) => { + console.log("eeee", e); + }} + onChange={(e) => { + console.log("eeee", e); + }} /> - + label="Description" placeHolder="My Awesome Collection Description" name="description" - control={control} + control={createCollectionForm.control} + // control={control} /> - + label="Symbol" placeHolder="Symbol" name="symbol" - control={control} + control={createCollectionForm.control} + // control={control} /> { width: 416, }} containerHeight={48} - onUpload={(files) => {}} + onUpload={(files) => { + createCollectionForm.setValue("coverImage", files[0]); + }} mimeTypes={IMAGE_MIME_TYPES} /> - + {/*>*/} + {/* {({ onPress }) => (*/} + {/* aaa*/} + {/* )}*/} + {/**/} + + label="External Link" placeHolder="https://collection..." name="externalLink" - control={control} - required={false} + control={createCollectionForm.control} + // control={control} /> diff --git a/packages/screens/Launchpad/components/LaunchpadDetails.tsx b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadDetails.tsx similarity index 50% rename from packages/screens/Launchpad/components/LaunchpadDetails.tsx rename to packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadDetails.tsx index 35335407d6..3e42950ec0 100644 --- a/packages/screens/Launchpad/components/LaunchpadDetails.tsx +++ b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadDetails.tsx @@ -1,12 +1,11 @@ -import React, { useState } from "react"; -import { useForm } from "react-hook-form"; +import React from "react"; +import { UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { MultipleSelectionDropdown } from "./dropdowns/MultipleSelectionDropdown"; -import { SelectionDropdown } from "./dropdowns/SelectionDropdown"; -import { TextInputLaunchpadRequired } from "./inputs/TextInputLaunchpadRequired"; -import { TextInputLaunchpadRequiredSublabel } from "./inputs/TextInputLaunchpadRequiredSublabel"; -import { NewCollectionDetailsFormValues } from "../CreateCollection.type"; +import { CreateCollectionFormValues } from "../../CreateCollection.type"; +import { TextInputLaunchpadRequired } from "../inputs/TextInputLaunchpadRequired"; +import { MultipleSelectInput } from "../inputs/selectInputs/MultipleSelectInput"; +import { SelectInputLaunchpad } from "../inputs/selectInputs/SelectInputLaunchpad"; import { BrandText } from "@/components/BrandText"; import { SpacerColumn } from "@/components/spacer"; @@ -18,26 +17,12 @@ import { } from "@/utils/style/fonts"; import { layout } from "@/utils/style/layout"; -export const LaunchpadDetails: React.FC = () => { - const dropdownOptions = ["Yes", "No"]; - const projectOptions = ["PFP", "Utility", "Metaverse", "P2E", "Other"]; - - const [isDerivativeProject, setIsDerivativeProject] = useState(""); - const [isPreviouslyApplied, setIsPreviouslyApplied] = useState(""); - const [projectTypes, setProjectTypes] = useState([]); - - const { control } = useForm({ - defaultValues: { - websiteLink: "", - twitterProfileUrl: "", - twitterFollowers: "", - discordName: "", - email: "", - projectDesciption: "", - projectType: "", - }, - mode: "onBlur", - }); +export const LaunchpadDetails: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { + const isDerivativeProject = createCollectionForm.watch("isDerivativeProject"); + const isPreviouslyApplied = createCollectionForm.watch("isPreviouslyApplied"); + const projectTypes = createCollectionForm.watch("projectTypes") || []; return ( @@ -49,65 +34,75 @@ export const LaunchpadDetails: React.FC = () => { - + label="Website Link" placeHolder="https://website..." name="websiteLink" - control={control} + control={createCollectionForm.control} required={false} /> - + required label="Twitter Profile " placeHolder="https://twitter..." name="twitterProfileUrl" - control={control} + control={createCollectionForm.control} /> - + required label="How many Twitter followers does your project have? " placeHolder="10,000" - name="twitterFollowers" - control={control} + name="nbTwitterFollowers" + control={createCollectionForm.control} /> - + required label="Discord name of your main contact: " placeHolder="nickname#0000" name="discordName" - control={control} + control={createCollectionForm.control} /> - + required label="Main contact email address: " placeHolder="contact@email.com" name="email" - control={control} + control={createCollectionForm.control} /> - { + createCollectionForm.setValue( + "isDerivativeProject", + item === "Yes", + ); + }} label="Is your project a derivative project?" style={{ zIndex: 3 }} /> - { - if (projectTypes.includes(item)) { - setProjectTypes(projectTypes.filter((data) => data !== item)); - } else { - setProjectTypes([...projectTypes, item]); - } + const selectedProjectTypes = projectTypes.includes(item) + ? projectTypes.filter((data) => data !== item) + : [...projectTypes, item]; + createCollectionForm.setValue("projectTypes", selectedProjectTypes); }} label="Project type:" sublabel={ @@ -120,7 +115,7 @@ export const LaunchpadDetails: React.FC = () => { style={{ zIndex: 2 }} /> - + label="Describe your project: " sublabel={ @@ -136,15 +131,26 @@ export const LaunchpadDetails: React.FC = () => { } placeHolder="Describe here..." - name="projectDesciption" - control={control} + name="projectDescription" + control={createCollectionForm.control} /> - { + createCollectionForm.setValue( + "isPreviouslyApplied", + item === "Yes", + ); + }} label="Have you previously applied for the same project before?" style={{ zIndex: 1 }} /> diff --git a/packages/screens/Launchpad/components/LaunchpadMinting.tsx b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadMinting.tsx similarity index 58% rename from packages/screens/Launchpad/components/LaunchpadMinting.tsx rename to packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadMinting.tsx index 783321b345..15ad64b155 100644 --- a/packages/screens/Launchpad/components/LaunchpadMinting.tsx +++ b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadMinting.tsx @@ -1,14 +1,13 @@ import React, { useState } from "react"; -import { useForm } from "react-hook-form"; +import { UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { ConfigureRoyaltyDetails } from "./ConfigureRoyaltyDetails"; -import { ExistingWhitelist } from "./ExistingWhitelist"; -import { NavBar } from "./NavBar"; -import { NewWhitelist } from "./NewWhitelist"; -import { TextInputLaunchpadRequired } from "./inputs/TextInputLaunchpadRequired"; -import { TextInputLaunchpadRequiredSublabel } from "./inputs/TextInputLaunchpadRequiredSublabel"; -import { NewCollectionMintFormValues } from "../CreateCollection.type"; +import { CreateCollectionFormValues } from "../../CreateCollection.type"; +import { ConfigureRoyaltyDetails } from "../ConfigureRoyaltyDetails"; +import { ExistingWhitelist } from "../ExistingWhitelist"; +import { NavBar } from "../NavBar"; +import { NewWhitelist } from "../NewWhitelist"; +import { TextInputLaunchpadRequired } from "../inputs/TextInputLaunchpadRequired"; import { BrandText } from "@/components/BrandText"; import { SpacerColumn } from "@/components/spacer"; @@ -21,42 +20,33 @@ import { import { layout } from "@/utils/style/layout"; const CreateWhitelistTabItems = { - nowhitelist: { + noWhitelist: { name: "No whitelist", }, - existinghitelist: { + existingWhitelist: { name: "Existing whitelist", }, - newhitelist: { + newWhitelist: { name: "New whitelist", }, }; const CreateRoyaltyTabItems = { - noroyalty: { + noRoyalty: { name: "No royalty", }, - configureroyaltydetails: { + configureRoyaltyDetails: { name: "Configure royalty details", }, }; -export const LaunchpadMinting: React.FC = () => { - const { control } = useForm({ - defaultValues: { - token: "", - unitPrice: "", - perAddressLimit: "", - startTime: "", - }, - mode: "onBlur", - }); - +export const LaunchpadMinting: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { const [selectedWhitelistTab, setSelectedWhitelistTab] = - useState("nowhitelist"); - + useState("noWhitelist"); const [selectedRoyaltyTab, setSelectedRoyaltyTab] = - useState("noroyalty"); + useState("noRoyalty"); return ( { - + label="Number of Tokens " placeHolder="0" - name="token" - control={control} + name="nbTokens" + control={createCollectionForm.control} /> - + label="Unit Price" sublabel={ @@ -92,10 +82,10 @@ export const LaunchpadMinting: React.FC = () => { } placeHolder="0" name="unitPrice" - control={control} + control={createCollectionForm.control} /> - + label="Per Address Limit " sublabel={ @@ -106,14 +96,14 @@ export const LaunchpadMinting: React.FC = () => { } placeHolder="0" name="perAddressLimit" - control={control} + control={createCollectionForm.control} /> - + label="Start Time " placeHolder="--.--.---- --:--" name="startTime" - control={control} + control={createCollectionForm.control} /> { onSelect={setSelectedWhitelistTab} /> - {selectedWhitelistTab === "existinghitelist" && } - {selectedWhitelistTab === "newhitelist" && } + {selectedWhitelistTab === "existingWhitelist" && ( + + )} + {selectedWhitelistTab === "newWhitelist" && ( + + )} { onSelect={setSelectedRoyaltyTab} /> - {selectedRoyaltyTab === "configureroyaltydetails" && ( - + {selectedRoyaltyTab === "configureRoyaltyDetails" && ( + )} diff --git a/packages/screens/Launchpad/components/LaunchpadTeamandInvestment.tsx b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadTeamAndInvestment.tsx similarity index 75% rename from packages/screens/Launchpad/components/LaunchpadTeamandInvestment.tsx rename to packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadTeamAndInvestment.tsx index cc0ddf8e59..b7b06faf86 100644 --- a/packages/screens/Launchpad/components/LaunchpadTeamandInvestment.tsx +++ b/packages/screens/Launchpad/components/launchpadCreateSteps/LaunchpadTeamAndInvestment.tsx @@ -1,12 +1,12 @@ import React from "react"; -import { useForm } from "react-hook-form"; +import { UseFormReturn } from "react-hook-form"; import { View } from "react-native"; -import { TextInputLaunchpadRequiredSublabel } from "./inputs/TextInputLaunchpadRequiredSublabel"; -import { TeamandInvestmentFormValues } from "../CreateCollection.type"; +import { CreateCollectionFormValues } from "../../CreateCollection.type"; import { BrandText } from "@/components/BrandText"; import { SpacerColumn } from "@/components/spacer"; +import { TextInputLaunchpadRequired } from "@/screens/Launchpad/components/inputs/TextInputLaunchpadRequired"; import { neutral55, neutral77 } from "@/utils/style/colors"; import { fontSemibold13, @@ -14,19 +14,9 @@ import { fontSemibold20, } from "@/utils/style/fonts"; -export const LaunchpadTeamandInvestment: React.FC = () => { - const { control } = useForm({ - defaultValues: { - teamDesciption: "", - teamLink: "", - partner: "", - investDesciption: "", - investLink: "", - roadmap: "", - }, - mode: "onBlur", - }); - +export const LaunchpadTeamAndInvestment: React.FC<{ + createCollectionForm: UseFormReturn; +}> = ({ createCollectionForm }) => { return ( @@ -37,7 +27,7 @@ export const LaunchpadTeamandInvestment: React.FC = () => { - + label="Describe your team: " sublabel={ @@ -60,11 +50,11 @@ export const LaunchpadTeamandInvestment: React.FC = () => { } placeHolder="Describe here..." - name="teamDesciption" - control={control} + name="teamDescription" + control={createCollectionForm.control} /> - + required={false} label="Team links and attachments " sublabel={ @@ -76,11 +66,11 @@ export const LaunchpadTeamandInvestment: React.FC = () => { } placeHolder="Type here..." - name="teamDesciption" - control={control} + name="teamLink" + control={createCollectionForm.control} /> - + label="Do you have any partners on the project? " sublabel={ @@ -90,11 +80,11 @@ export const LaunchpadTeamandInvestment: React.FC = () => { } placeHolder="Type here..." - name="partner" - control={control} + name="partnersDescription" + control={createCollectionForm.control} /> - + label="What have you invested in this project so far? " sublabel={ @@ -113,11 +103,11 @@ export const LaunchpadTeamandInvestment: React.FC = () => { } placeHolder="Type here..." - name="investDesciption" - control={control} + name="investDescription" + control={createCollectionForm.control} /> - + required={false} label="Investment links and attachments " sublabel={ @@ -130,22 +120,22 @@ export const LaunchpadTeamandInvestment: React.FC = () => { } placeHolder="Type here..." name="investLink" - control={control} + control={createCollectionForm.control} /> - + label="Whitepaper and roadmap: " sublabel={ - Please provide any relevant links regarding your whitepaper and + Please provide any relevant link regarding your white paper and roadmap. You can also post a google drive link. } placeHolder="Type here..." - name="roadmap" - control={control} + name="roadmapLink" + control={createCollectionForm.control} /> diff --git a/packages/screens/RiotGame/RiotGameScreen.tsx b/packages/screens/RiotGame/RiotGameScreen.tsx index ebba6ccbb2..de2247225e 100644 --- a/packages/screens/RiotGame/RiotGameScreen.tsx +++ b/packages/screens/RiotGame/RiotGameScreen.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React from "react"; import { FlatList, StyleSheet, useWindowDimensions, View } from "react-native"; import { CenterSection } from "./component/CenterSection"; @@ -6,15 +6,15 @@ import { GameBgCard } from "./component/GameBgCard"; import { GameBgOverlay } from "./component/GameBgOverlay"; import { RiotGameHeader } from "./component/RiotGameHeader"; +import { Metadata, WhitelistMintInfo } from "@/api/launchpad/v1/launchpad"; +import { PrimaryButton } from "@/components/buttons/PrimaryButton"; import { useAppNavigation } from "@/hooks/navigation/useAppNavigation"; +import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; +import useSelectedWallet from "@/hooks/useSelectedWallet"; +import { mustGetLauchpadClient } from "@/utils/backend"; import { gameBgData } from "@/utils/game"; import { neutral00 } from "@/utils/style/colors"; import { headerHeight } from "@/utils/style/layout"; -import { mustGetLauchpadClient } from "@/utils/backend"; -import { useSelectedNetworkId } from "@/hooks/useSelectedNetwork"; -import useSelectedWallet from "@/hooks/useSelectedWallet"; -import { Metadata, WhitelistMintInfo } from "@/api/launchpad/v1/launchpad"; -import { PrimaryButton } from "@/components/buttons/PrimaryButton"; export const RiotGameScreen = () => { const navigation = useAppNavigation(); @@ -32,12 +32,12 @@ export const RiotGameScreen = () => { }; const updateWhitelists = async () => { - let client = mustGetLauchpadClient(networkId); - let whitelists: WhitelistMintInfo[] = [ + const client = mustGetLauchpadClient(networkId); + const whitelists: WhitelistMintInfo[] = [ { addresses: ["addr1", "addr2", "addr3", "addr4", "add5"], unitPrice: 1_000_000, - denom: 'utori', + denom: "utori", limitPerAddress: 2, addressesCount: 5, startTime: Date.now(), @@ -46,20 +46,25 @@ export const RiotGameScreen = () => { { addresses: ["address2"], unitPrice: 2_000_000, - denom: 'utori', + denom: "utori", limitPerAddress: 2, addressesCount: 1, startTime: Date.now(), endTime: Date.now(), - } - ] + }, + ]; - let res = await client.UpdateCollectionWhitelists({sender: selectedWallet?.address, networkId: networkId, projectId: 1, whitelistMintInfos: whitelists}) - console.log(res) - } + const res = await client.UpdateCollectionWhitelists({ + sender: selectedWallet?.address, + networkId, + projectId: 1, + whitelistMintInfos: whitelists, + }); + console.log(res); + }; - const uploadMetadata = async () => { - let client = mustGetLauchpadClient(networkId); + const uploadMetadata = async () => { + const client = mustGetLauchpadClient(networkId); const nft0 = { image: "image0", @@ -68,8 +73,8 @@ export const RiotGameScreen = () => { description: "", name: "nft #0", attributes: [ - {traitType: "type0", value: "value0"}, - {traitType: "type1", value: "value1"}, + { traitType: "type0", value: "value0" }, + { traitType: "type1", value: "value1" }, ], backgroundColor: "", animationUrl: "", @@ -84,45 +89,43 @@ export const RiotGameScreen = () => { externalUrl: "", description: "", name: "nft #1", - attributes: [ - {traitType: "type1", value: "value1"}, - ], + attributes: [{ traitType: "type1", value: "value1" }], backgroundColor: "", animationUrl: "", youtubeUrl: "", royaltyPercentage: 5, royaltyPaymentAddress: "", - } + }; - let metadatas: Metadata[] = [nft0, nft1]; + const metadatas: Metadata[] = [nft0, nft1]; const resp = await client.UpdateTokensMetadatas({ sender: selectedWallet?.address, projectId: 1, networkId, - metadatas - }) - console.log(resp) - } + metadatas, + }); + console.log(resp); + }; - const getTokenMetadata = async () => { - let client = mustGetLauchpadClient(networkId); + const getTokenMetadata = async () => { + const client = mustGetLauchpadClient(networkId); const resp = await client.TokenMetadata({ sender: selectedWallet?.address, projectId: 1, networkId, tokenId: 1, - }) - console.log(resp) - } + }); + console.log(resp); + }; return ( - - - - + + + + { throw new Error(`failed to get feed client for network '${networkId}'`); } return client; -}; \ No newline at end of file +};