125125 </div >
126126 </div >
127127 </NeoField >
128+
129+ <NeoField
130+ v-if =" isModalActive"
131+ :label =" $t('mint.collection.permission.label')"
132+ >
133+ <div class =" w-full flex flex-col gap-4" >
134+ <div class =" flex items-center justify-between" >
135+ <p >
136+ {{ $t('mint.mintType') }}
137+ </p >
138+ <NeoSelect
139+ v-model =" selectedMintingType"
140+ >
141+ <option
142+ v-for =" menu in COLLECTION_MINTING_TYPES_OPTIONS"
143+ :key =" menu.value"
144+ :value =" menu.value"
145+ >
146+ {{ menu.text }}
147+ </option >
148+ </NeoSelect >
149+ </div >
150+
151+ <div >
152+ <div class =" flex justify-between capitalize" >
153+ <p >{{ $t(hasMintingPrice ? 'mint.collection.permission.pricePlaceholder' : 'mint.collection.permission.noPriceSet') }}</p >
154+ <NeoSwitch
155+ v-if =" isHolderOfMintingTypeSelected"
156+ v-model =" hasMintingPrice"
157+ position =" left"
158+ />
159+ </div >
160+ <div
161+ v-if =" hasMintingPrice"
162+ class =" flex focus-within:!border-border-color border border-k-shade h-12 mt-3"
163+ >
164+ <input
165+ v-model =" mintingPrice"
166+ type =" number"
167+ step =" 0.01"
168+ min =" 0.0001"
169+ pattern =" [0-9]+([\.,][0-9]+)?"
170+ class =" indent-2.5 border-none outline-none w-20 bg-background-color text-text-color w-full"
171+ :placeholder =" $t('mint.collection.permission.pricePlaceholder')"
172+ >
173+ <div class =" px-3 flex items-center" >
174+ {{ chainSymbol }}
175+ </div >
176+ </div >
177+ <div
178+ v-if =" isHolderOfMintingTypeSelected"
179+ class =" mt-4"
180+ >
181+ <p class =" mb-2" >
182+ {{ $t('mint.collection.permission.holderOfCollection') }}
183+ </p >
184+ <CollectionSearchInput
185+ :collection-id =" holderOfCollectionId"
186+ @update:collection =" holderOfCollectionId = $event?.collection_id"
187+ />
188+ </div >
189+ </div >
190+
191+ <div class =" flex flex-col w-full" >
192+ <div
193+ v-if =" permissionSettingWarningMessage"
194+ class =" flex items-center gap-2 bg-yellow-50 border border-yellow-200 rounded-md p-3 !mt-2"
195+ >
196+ <NeoIcon
197+ icon =" warning"
198+ class =" text-yellow-500"
199+ size =" small"
200+ />
201+
202+ <p class =" text-sm text-yellow-700" >
203+ {{ permissionSettingWarningMessage }}
204+ </p >
205+ </div >
206+ </div >
207+ </div >
208+ </NeoField >
128209 </form >
129210
130211 <div class =" flex flex-col !mt-6" >
142223</template >
143224
144225<script setup lang="ts">
145- import { NeoButton , NeoField , NeoInput , NeoModal , NeoSwitch } from ' @kodadot1/brick'
226+ import { NeoButton , NeoField , NeoInput , NeoModal , NeoSwitch , NeoSelect , NeoIcon } from ' @kodadot1/brick'
146227import ModalBody from ' @/components/shared/modals/ModalBody.vue'
147- import type { UpdateCollection } from ' @/composables/transaction/types'
228+ import { type UpdateCollection , type CollectionMintSetting , CollectionMintSettingType } from ' @/composables/transaction/types'
148229
149230export type CollectionEditMetadata = {
150231 name: string
@@ -153,16 +234,21 @@ export type CollectionEditMetadata = {
153234 imageType: string
154235 banner? : string
155236 max: number | null
237+ mintingSettings: CollectionMintSetting
156238}
157239
240+ const COLLECTION_MINTING_TYPES_OPTIONS = ([CollectionMintSettingType .Issuer , CollectionMintSettingType .Public , CollectionMintSettingType .HolderOf ]).map (type => ({ value: type , text: type }))
241+
158242const emit = defineEmits ([' submit' ])
159243const props = defineProps <{
160244 modelValue: boolean
161245 collection: CollectionEditMetadata
162246 min? : number
163247}>()
164248
249+ const { $i18n } = useNuxtApp ()
165250const isModalActive = useVModel (props , ' modelValue' )
251+ const { chainSymbol, decimals, withDecimals } = useChain ()
166252
167253const name = ref <string >()
168254const description = ref <string >()
@@ -171,13 +257,22 @@ const banner = ref<File>()
171257const imageUrl = ref <string >()
172258const bannerUrl = ref <string >()
173259const unlimited = ref (true )
260+ const hasMintingPrice = ref (false )
261+ const mintingPrice = ref <number | null >(null )
174262
263+ const selectedMintingType = ref <CollectionMintSettingType | null >(null )
175264const min = computed (() => props .min || 1 )
176265const max = ref <number | null >(null )
177266
178267const nameChanged = computed (() => props .collection .name !== name .value )
179268const hasImageChanged = computed (() => (! imageUrl .value && Boolean (props .collection .image )) || Boolean (image .value ))
180269const originalLogoImageUrl = computed (() => sanitizeIpfsUrl (props .collection .image ))
270+ const mintTypeChanged = computed (() => selectedMintingType .value !== props .collection .mintingSettings .mintType )
271+ const mintPriceChanged = computed (() => mintingPrice .value !== originalMintPrice .value )
272+ const originalMintPrice = computed (() => props .collection .mintingSettings .price ? Number (props .collection .mintingSettings .price ) / (10 ** decimals .value ) : null )
273+ const originalHolderOfCollectionId = computed (() => props .collection .mintingSettings .holderOf )
274+ const holderOfCollectionId = ref <string | undefined >(originalHolderOfCollectionId .value )
275+ const isHolderOfMintingTypeSelected = computed (() => selectedMintingType .value === CollectionMintSettingType .HolderOf )
181276
182277const disabled = computed (() => {
183278 const hasImage = imageUrl .value
@@ -186,10 +281,17 @@ const disabled = computed(() => {
186281 const descriptionChanged = props .collection .description !== description .value
187282 const hasBannerChanged = (! bannerUrl .value && Boolean (props .collection .banner )) || Boolean (banner .value )
188283 const hasMaxChanged = max .value !== props .collection .max
284+ const holderOfCollectionIdChanged = holderOfCollectionId .value !== originalHolderOfCollectionId .value
285+ const invalidPublicCollection = selectedMintingType .value === ' Public' && ! mintingPrice .value
286+
287+ const invalidHolderOfCollection = isHolderOfMintingTypeSelected .value && ! holderOfCollectionId .value
189288
190- return ! hasImage || ! isNameFilled || (! nameChanged .value && ! descriptionChanged && ! hasImageChanged .value && ! hasBannerChanged && ! hasMaxChanged )
289+ return ! hasImage || ! isNameFilled || invalidHolderOfCollection || invalidPublicCollection
290+ || (! nameChanged .value && ! descriptionChanged && ! hasImageChanged .value && ! hasBannerChanged && ! hasMaxChanged && ! mintTypeChanged .value && ! mintPriceChanged .value && ! holderOfCollectionIdChanged )
191291})
192292
293+ const permissionSettingWarningMessage = computed (() => selectedMintingType .value && permissionSettingCheckingMap [selectedMintingType .value ]?.())
294+
193295const initLogoImage = () => {
194296 imageUrl .value = originalLogoImageUrl .value
195297 image .value = undefined
@@ -203,6 +305,11 @@ const editCollection = async () => {
203305 imageType: props .collection .imageType ,
204306 banner: bannerUrl .value ? banner .value || props .collection .banner : undefined ,
205307 max: max .value ,
308+ mintingSettings: {
309+ mintType: selectedMintingType .value ,
310+ price: hasMintingPrice .value ? String (withDecimals (mintingPrice .value || 0 )) : null ,
311+ holderOf: holderOfCollectionId .value || originalHolderOfCollectionId .value ,
312+ },
206313 } as UpdateCollection )
207314}
208315
@@ -215,6 +322,55 @@ watch(isModalActive, (value) => {
215322 initLogoImage ()
216323 unlimited .value = ! props .collection .max
217324 max .value = props .collection .max
325+
326+ // permission
327+ selectedMintingType .value = props .collection .mintingSettings .mintType
328+ hasMintingPrice .value = Boolean (props .collection .mintingSettings .price )
329+ mintingPrice .value = originalMintPrice .value || null
330+ holderOfCollectionId .value = originalHolderOfCollectionId .value
331+ }
332+ }, {
333+ immediate: true ,
334+ })
335+ const mintTypeChangeHandlerMap: Record <CollectionMintSettingType , () => void > = {
336+ [CollectionMintSettingType .Issuer ]: () => {
337+ hasMintingPrice .value = false
338+ mintingPrice .value = null
339+ },
340+ [CollectionMintSettingType .Public ]: () => {
341+ hasMintingPrice .value = true
342+ mintingPrice .value = null
343+ },
344+ [CollectionMintSettingType .HolderOf ]: () => {
345+ hasMintingPrice .value = false
346+ mintingPrice .value = null
347+ holderOfCollectionId .value = undefined
348+ },
349+ }
350+
351+ const permissionSettingCheckingMap: Record <CollectionMintSettingType , () => string | undefined > = {
352+ [CollectionMintSettingType .Issuer ]: () => {
353+ if (mintingPrice .value ) {
354+ return $i18n .t (' mint.collection.permission.issuerWarning' )
355+ }
356+ },
357+ [CollectionMintSettingType .Public ]: () => {
358+ if (! mintingPrice .value || mintingPrice .value <= 0 ) {
359+ return $i18n .t (' mint.collection.permission.publicWarning' )
360+ }
361+ return $i18n .t (' mint.collection.permission.publicWithPriceWarning' )
362+ },
363+ [CollectionMintSettingType .HolderOf ]: () => {
364+ if (! holderOfCollectionId .value ) {
365+ return $i18n .t (' mint.collection.permission.holderOfIdWarning' )
366+ }
367+ return $i18n .t (' mint.collection.permission.holderOfWarning' )
368+ },
369+ }
370+
371+ watch (selectedMintingType , (type , oldType ) => {
372+ if (oldType && type && mintTypeChangeHandlerMap [type ]) {
373+ mintTypeChangeHandlerMap [type ]()
218374 }
219375})
220376
0 commit comments