Fixes and improvements (#28)
* Update collection creation error messages * Update minimum unit price * Update .env.example * Fix double ustars conversion for whitelist & minter unit_price * Add minimum unit price for whitelisted addresses * Fix: Invalid baseTokenURI error during collection instantiation * Collection cover image URI update * Minimum unit price update - 2 * Fix: nonfunctional existing whitelist option * Check matching asset and metadata file arrays before creating a collection * Mark minting detail inputs as required * Fix: collection creation with the specified royalty preference * Fix: whitelistType change problem * Fix creation logic * Automate number of tokens input & check per address limit * Automate number of tokens input & check per address limit - 2 * Metadata files should have .json extensions * Check royalty percentage * Upload service related changes now trigger state updates Co-authored-by: findolor <anakisci@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { NumberInput } from '../../forms/FormInput'
|
||||
|
||||
interface MintingDetailsProps {
|
||||
onChange: (data: MintingDetailsDataProps) => void
|
||||
numberOfTokens: number | undefined
|
||||
}
|
||||
|
||||
export interface MintingDetailsDataProps {
|
||||
@@ -17,7 +18,7 @@ export interface MintingDetailsDataProps {
|
||||
startTime: string
|
||||
}
|
||||
|
||||
export const MintingDetails = ({ onChange }: MintingDetailsProps) => {
|
||||
export const MintingDetails = ({ onChange, numberOfTokens }: MintingDetailsProps) => {
|
||||
const [timestamp, setTimestamp] = useState<Date | undefined>()
|
||||
|
||||
const numberOfTokensState = useNumberInputState({
|
||||
@@ -45,6 +46,7 @@ export const MintingDetails = ({ onChange }: MintingDetailsProps) => {
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (numberOfTokens) numberOfTokensState.onChange(numberOfTokens)
|
||||
const data: MintingDetailsDataProps = {
|
||||
numTokens: numberOfTokensState.value,
|
||||
unitPrice: unitPriceState.value ? (Number(unitPriceState.value) * 1_000_000).toString() : '',
|
||||
@@ -53,14 +55,14 @@ export const MintingDetails = ({ onChange }: MintingDetailsProps) => {
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [numberOfTokensState.value, unitPriceState.value, perAddressLimitState.value, timestamp])
|
||||
}, [numberOfTokens, numberOfTokensState.value, unitPriceState.value, perAddressLimitState.value, timestamp])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FormGroup subtitle="Information about your minting settings" title="Minting Details">
|
||||
<NumberInput {...numberOfTokensState} />
|
||||
<NumberInput {...unitPriceState} />
|
||||
<NumberInput {...perAddressLimitState} />
|
||||
<NumberInput {...numberOfTokensState} disabled isRequired value={numberOfTokens} />
|
||||
<NumberInput {...unitPriceState} isRequired />
|
||||
<NumberInput {...perAddressLimitState} isRequired />
|
||||
<FormControl htmlId="timestamp" isRequired subtitle="Start time for the minting" title="Start Time">
|
||||
<InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />
|
||||
</FormControl>
|
||||
|
||||
@@ -44,7 +44,7 @@ export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [royaltyPaymentAddressState.value, royaltyShareState.value])
|
||||
}, [royaltyState, royaltyPaymentAddressState.value, royaltyShareState.value])
|
||||
|
||||
return (
|
||||
<div className="py-3 px-8 rounded border-2 border-white/20">
|
||||
@@ -78,7 +78,7 @@ export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
|
||||
value="Existing"
|
||||
/>
|
||||
<label className="inline-block text-white cursor-pointer form-check-label" htmlFor="royaltyRadio2">
|
||||
New royalty
|
||||
Configure royalty details
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -98,11 +98,9 @@ export const UploadDetails = ({ onChange }: UploadDetailsProps) => {
|
||||
if (event.target.files === null) return toast.error('No files selected.')
|
||||
for (let i = 0; i < event.target.files.length; i++) {
|
||||
reader = new FileReader()
|
||||
reader.onload = async (e) => {
|
||||
reader.onload = (e) => {
|
||||
if (!e.target?.result) return toast.error('Error parsing file.')
|
||||
if (!event.target.files) return toast.error('No files selected.')
|
||||
if (!JSON.parse(await event.target.files[i].text()).attributes)
|
||||
return toast.error(`The file with name '${event.target.files[i].name}' doesn't have an attributes list!`)
|
||||
const metadataFile = new File([e.target.result], event.target.files[i].name, { type: 'application/json' })
|
||||
setMetadataFilesArray((prev) => [...prev, metadataFile])
|
||||
}
|
||||
@@ -126,16 +124,6 @@ export const UploadDetails = ({ onChange }: UploadDetailsProps) => {
|
||||
console.log(JSON.parse(await metadataFilesArray[metadataFileArrayIndex]?.text()))
|
||||
}
|
||||
|
||||
const checkAssetMetadataMatch = () => {
|
||||
const metadataFileNames = metadataFilesArray.map((file) => file.name)
|
||||
const assetFileNames = assetFilesArray.map((file) => file.name.substring(0, file.name.lastIndexOf('.')))
|
||||
// Compare the two arrays to make sure they are the same
|
||||
const areArraysEqual = metadataFileNames.every((val, index) => val === assetFileNames[index])
|
||||
if (!areArraysEqual) {
|
||||
throw new Error('Asset and metadata file names do not match.')
|
||||
}
|
||||
}
|
||||
|
||||
const videoPreviewElements = useMemo(() => {
|
||||
const tempArray: JSX.Element[] = []
|
||||
assetFilesArray.forEach((assetFile) => {
|
||||
@@ -163,7 +151,6 @@ export const UploadDetails = ({ onChange }: UploadDetailsProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
checkAssetMetadataMatch()
|
||||
const data: UploadDetailsDataProps = {
|
||||
assetFiles: assetFilesArray,
|
||||
metadataFiles: metadataFilesArray,
|
||||
@@ -176,7 +163,14 @@ export const UploadDetails = ({ onChange }: UploadDetailsProps) => {
|
||||
} catch (error: any) {
|
||||
toast.error(error.message)
|
||||
}
|
||||
}, [assetFilesArray, metadataFilesArray])
|
||||
}, [
|
||||
assetFilesArray,
|
||||
metadataFilesArray,
|
||||
uploadService,
|
||||
nftStorageApiKeyState.value,
|
||||
pinataApiKeyState.value,
|
||||
pinataSecretKeyState.value,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
setAssetFilesArray([])
|
||||
@@ -383,7 +377,7 @@ export const UploadDetails = ({ onChange }: UploadDetailsProps) => {
|
||||
)}
|
||||
>
|
||||
<input
|
||||
accept=""
|
||||
accept="application/json"
|
||||
className={clsx(
|
||||
'file:py-2 file:px-4 file:mr-4 file:bg-plumbus-light file:rounded file:border-0 cursor-pointer',
|
||||
'before:absolute before:inset-0 before:hover:bg-white/5 before:transition',
|
||||
|
||||
@@ -36,6 +36,7 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
id: 'whitelist-address',
|
||||
name: 'whitelistAddress',
|
||||
title: 'Whitelist Address',
|
||||
defaultValue: '',
|
||||
})
|
||||
|
||||
const uniPriceState = useNumberInputState({
|
||||
@@ -79,7 +80,16 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [uniPriceState.value, memberLimitState.value, perAddressLimitState.value, startDate, endDate, whitelistArray])
|
||||
}, [
|
||||
whitelistAddressState.value,
|
||||
uniPriceState.value,
|
||||
memberLimitState.value,
|
||||
perAddressLimitState.value,
|
||||
startDate,
|
||||
endDate,
|
||||
whitelistArray,
|
||||
whitelistState,
|
||||
])
|
||||
|
||||
return (
|
||||
<div className="py-3 px-8 rounded border-2 border-white/20">
|
||||
@@ -135,7 +145,11 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
|
||||
</div>
|
||||
|
||||
<Conditional test={whitelistState === 'existing'}>
|
||||
<AddressInput {...whitelistAddressState} className="pb-5" />
|
||||
<AddressInput
|
||||
{...whitelistAddressState}
|
||||
className="pb-5"
|
||||
onChange={(e) => whitelistAddressState.onChange(e.target.value)}
|
||||
/>
|
||||
</Conditional>
|
||||
|
||||
<Conditional test={whitelistState === 'new'}>
|
||||
|
||||
Reference in New Issue
Block a user