diff --git a/app/components/Navbar.vue b/app/components/Navbar.vue index ab9dca8f..9d4403de 100644 --- a/app/components/Navbar.vue +++ b/app/components/Navbar.vue @@ -64,7 +64,7 @@ function handleCreateNft() { function handleMassMint() { isCreateModalOpen.value = false - router.push('/massmint/onboarding') + router.push('/massmint') } function handleAirdrop() { diff --git a/app/components/common/Stepper.vue b/app/components/common/Stepper.vue new file mode 100644 index 00000000..4879cf9d --- /dev/null +++ b/app/components/common/Stepper.vue @@ -0,0 +1,83 @@ + + + diff --git a/app/components/massmint/MassMint.vue b/app/components/massmint/MassMint.vue index 7c58f7fd..2955aea2 100644 --- a/app/components/massmint/MassMint.vue +++ b/app/components/massmint/MassMint.vue @@ -1,19 +1,18 @@ diff --git a/app/components/massmint/MassMintUploadStep.vue b/app/components/massmint/MassMintUploadStep.vue new file mode 100644 index 00000000..5aa0818d --- /dev/null +++ b/app/components/massmint/MassMintUploadStep.vue @@ -0,0 +1,289 @@ + + + diff --git a/app/components/massmint/OnBoardingCard.vue b/app/components/massmint/OnBoardingCard.vue deleted file mode 100644 index a16418f5..00000000 --- a/app/components/massmint/OnBoardingCard.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/app/components/massmint/Onboarding.vue b/app/components/massmint/Onboarding.vue deleted file mode 100644 index d203dbde..00000000 --- a/app/components/massmint/Onboarding.vue +++ /dev/null @@ -1,196 +0,0 @@ - - - diff --git a/app/components/massmint/index.ts b/app/components/massmint/index.ts index 95e77f66..4af68fd6 100644 --- a/app/components/massmint/index.ts +++ b/app/components/massmint/index.ts @@ -1,6 +1,4 @@ export { default as MassMint } from './MassMint.vue' -export { default as OnBoarding } from './Onboarding.vue' -export { default as OnBoardingCard } from './OnBoardingCard.vue' export { default as OverviewTable } from './OverviewTable.vue' export * from './types' export { default as UploadPictures } from './upload/UploadCompressedMedia.vue' diff --git a/app/components/massmint/upload/UploadCompressedMedia.vue b/app/components/massmint/upload/UploadCompressedMedia.vue index b7b51141..77174c20 100644 --- a/app/components/massmint/upload/UploadCompressedMedia.vue +++ b/app/components/massmint/upload/UploadCompressedMedia.vue @@ -6,7 +6,7 @@ interface Props { } interface Emits { - (e: 'zipLoaded', data: { validFiles: any[], areAllFilesValid: boolean }): void + (e: 'zipLoaded', data: { validFiles: any[] }): void } withDefaults(defineProps(), { @@ -43,7 +43,6 @@ async function onFileSelected(file?: File) { const zipFilePath = URL.createObjectURL(blob) const { - allValid, loading: loadingZip, validFiles, warnings, @@ -64,7 +63,6 @@ async function onFileSelected(file?: File) { showCheckmark.value = true emit('zipLoaded', { validFiles: validFiles.value, - areAllFilesValid: allValid.value, }) URL.revokeObjectURL(zipFilePath) @@ -80,7 +78,6 @@ async function onFileSelected(file?: File) { console.error('Invalid file type.') emit('zipLoaded', { validFiles: [], - areAllFilesValid: false, }) } } diff --git a/app/components/massmint/utils.ts b/app/components/massmint/utils.ts new file mode 100644 index 00000000..33612c67 --- /dev/null +++ b/app/components/massmint/utils.ts @@ -0,0 +1,64 @@ +import type { NFT } from './types' + +export type TemplateFormat = 'json' | 'csv' | 'txt' + +export const attributesExample = [ + { value: 'white', trait_type: 'color' }, + { value: 'happy', trait_type: 'expression' }, +] as const + +/** + * Generate metadata template content for the given format and NFTs. + */ +export function generateTemplateContent(format: TemplateFormat, nfts: NFT[]): string { + if (format === 'json') { + const items = nfts.map((nft, index) => ({ + file: nft.file?.name || '', + ...(index === 0 + ? { name: 'Art #1', price: 1, description: 'Description for the Art #1', attributes: [...attributesExample] } + : { name: '', description: '', price: '', attributes: [] } + ), + })) + return JSON.stringify(items, null, 2) + } + + if (format === 'csv') { + const header = 'file,name,description,attributes,price' + const attributesCsvExample = 'color:white;expression:happy' + const rows = nfts.map((nft, index) => { + const file = nft.file?.name || '' + if (index === 0) { + return `${file},Art #1,Description for the Art #1,${attributesCsvExample},1` + } + return `${file},,,,` + }) + return [header, ...rows].join('\n') + } + + // txt + const attributesTxtExample = '[{"value": "white","trait_type": "color"},{"value": "happy","trait_type": "expression"}]' + const blocks = nfts.map((nft, index) => { + const fileName = nft.file?.name || '' + const isFirst = index === 0 + return [ + `file: ${fileName}`, + isFirst ? 'name: Art #1' : 'name: ', + isFirst ? 'description: Description for the Art #1' : 'description: ', + isFirst ? `attributes: ${attributesTxtExample}` : 'attributes: ', + isFirst ? 'price: 1' : 'price: ', + '', + ].join('\n') + }) + return blocks.join('\n') +} + +export function convertNftsToMap( + items: T[], +): Record { + return items + .map((item, i) => ({ ...item, id: i + 1 } as T & { id: number })) + .reduce((acc, nft) => { + acc[nft.id] = nft + return acc + }, {} as Record) +} diff --git a/app/composables/massmint/parsers/parseTxt.ts b/app/composables/massmint/parsers/parseTxt.ts index 9758720b..7fd9604b 100644 --- a/app/composables/massmint/parsers/parseTxt.ts +++ b/app/composables/massmint/parsers/parseTxt.ts @@ -70,8 +70,14 @@ function updateEntry(entry: Record, line: string) { entry.price = price entry.currency = currency } - else if (fieldName === 'attributes') { - entry.attributes = JSON.parse(fieldValue) + else if (fieldName === 'attributes' && fieldValue) { + try { + entry.attributes = JSON.parse(fieldValue) + } + catch { + console.error('Invalid attributes JSON in TXT metadata block') + entry.attributes = {} + } } else { entry[fieldName] = fieldValue diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index e39a0cd7..225d1037 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -401,30 +401,6 @@ "variationLoadingTimeMeans3": "Takes too long to render, no clear way to fix that, the artist needs to find a way to cut down time." }, "massmint": { - "onboarding": { - "pageTitle": "Mass Mint Onboarding", - "skip": "Skip", - "next": "Next", - "done": "Done", - "downloadTemplate": "Download file template", - "cards": { - "0": { - "title": "Prepare All Your Files", - "content": "Start your mass minting by compressing all your art files into a .ZIP for upload. Aside from your artwork, each NFT requires a name, description, and price.\n\nTo streamline the process, prepare these details in advance in a separate file. This avoids manually entering information for each NFT. Further guidance on formatting this file will follow in the next step." - }, - "1": { - "title": "How To Name Your NFTs", - "content": "", - "subtitle": "Instructions", - "instructions": "Please ensure that the file field corresponds to the image file name (e.g., set \"file\": img1.jpg in the file field if the image has a file name of \"img1.jpg\"). Note that the order of items in the description file determines the order during mass minting.", - "codeStructure": "Code Structure" - }, - "2": { - "title": "You Need To Have A Collection", - "content": "In order to use the Mass Mint feature you need to have an **NFT collection created** to which you will mint all of your NFTs. If you do not have a collection created yet, you can create one in Mass Mint.\n\nDon't have a collection? [Create One](/create/collection)" - } - } - } }, "trades": { "anyNftFrom": "Any NFT From", diff --git a/app/pages/massmint/index.vue b/app/pages/massmint/index.vue index 4f4bc4f8..fa4f0b15 100644 --- a/app/pages/massmint/index.vue +++ b/app/pages/massmint/index.vue @@ -3,18 +3,12 @@ import { MassMint } from '~/components/massmint' definePageMeta({ title: 'Mass Mint', - layout: 'default', + layout: 'no-footer', }) - -const router = useRouter() - -function handleBackToOnboarding() { - router.push('/massmint/onboarding') -} diff --git a/app/pages/massmint/onboarding.vue b/app/pages/massmint/onboarding.vue deleted file mode 100644 index 601def8e..00000000 --- a/app/pages/massmint/onboarding.vue +++ /dev/null @@ -1,9 +0,0 @@ - - -