kodadot/nft-gallery

View on GitHub
components/collection/drop/modal/shared/SuccessfulDrop.vue

Summary

Maintainability
Test Coverage
<template>
  <SuccessfulModalBody
    :tx-hash="txHash"
    :share="share"
    :status="status"
    :action-buttons="actionButtons"
  >
    <SuccessfulItemsMedia
      :header="{
        single: $t('drops.youSuccessfullyClaimedNft', [1]),
        multiple: $t('drops.amountMintedSuccessfully', [items.length]),
      }"
      :items="items"
    />
  </SuccessfulModalBody>
</template>

<script setup lang="ts">
import type { Prefix } from '@kodadot1/static'
import type { MintedNFT, MintingSession } from '../../types'
import type { ItemMedia } from '@/components/common/successfulModal/SuccessfulItemsMedia.vue'
import type { ShareProp } from '@/components/common/successfulModal/SuccessfulModalBody.vue'
import type { TransactionStatus } from '@/composables/useTransactionStatus'
import { listVisible } from '@/utils/config/permission.config'

const emit = defineEmits(['list'])
const props = defineProps<{
  mintingSession: MintingSession
  canListNfts: boolean
  status: TransactionStatus
}>()

const { $i18n } = useNuxtApp()
const { toast } = useToast()
const { urlPrefix } = usePrefix()
const { accountId } = useAuth()
const { getCollectionFrameUrl } = useSocialShare()
const { toMintNFTs } = storeToRefs(useDropStore())

const cantList = computed(() => !props.canListNfts)
const txHash = computed(() => props.mintingSession.txHash ?? '')
const singleMint = computed(() => props.mintingSession.items.length === 1)
const mintedNft = computed<MintedNFT | undefined>(
  () => props.mintingSession.items[0],
)

const itemMedias = props.mintingSession.items.map(item => ({
  id: item.id,
  name: item.name,
  image: item.image,
  collection: item.collection.id,
  collectionName: item.collection.name,
  mimeType: item.mimeType,
  metadata: item.metadata,
}))
const items = ref<ItemMedia[]>(itemMedias)

onMounted(async () => {
  toast('Successfully minted token. There is a 1 minute indexer and worker delay for this action to appear in the website.', { position: 'top-right', duration: 15000 })

  // update serial number in nft.name asynchronously
  const metadatas = await Promise.all(
    items.value.map(item => $fetch<{ name?: string }>(item.metadata)),
  )

  items.value.forEach((_, index) => {
    const metadata = metadatas[index]
    if (metadata.name) {
      items.value[index].name = metadata.name
      toMintNFTs.value[index].name = metadata.name
    }
  })
})

const nftPath = computed(
  () => mintedNft.value
    ? pickByVm({
      SUB: `/${mintedNft.value.chain}/gallery/${mintedNft.value.collection.id}-${mintedNft.value.id}`,
      EVM: `/${mintedNft.value.chain}/gallery/${mintedNft.value.id}`,
    }, { prefix: mintedNft.value.chain as Prefix })
    : '',
)
const nftFullUrl = computed(() => `${window.location.origin}${nftPath.value}`)
const userProfilePath = computed(
  () => `/${urlPrefix.value}/u/${accountId.value}`,
)

const getItemSn = (name: string) => `#${name.split('#')[1]}`

const sharingTxt = computed(() =>
  singleMint.value
    ? $i18n.t('sharing.dropNft', [getItemSn(items.value[0].name)])
    : $i18n.t('sharing.dropNfts', [
      items.value.map(item => getItemSn(item.name)).join(', '),
    ]),
)

const share = computed<ShareProp>(() => ({
  text: sharingTxt.value,
  url: nftFullUrl.value,
  withCopy: singleMint.value,
  social: {
    farcaster: {
      embeds: [
        getCollectionFrameUrl(
          urlPrefix.value,
          mintedNft.value?.collection.id as string,
        ),
      ],
    },
  },
}))

const viewButton = computed(() => ({
  label: $i18n.t('viewNft', props.mintingSession.items.length),
  onClick: handleViewNft,
}))

const listButton = computed(() => ({
  label: $i18n.t('listNft', props.mintingSession.items.length),
  onClick: listNft,
  disabled: cantList.value,
}))

const actionButtons = computed(() =>
  listVisible(urlPrefix.value)
    ? {
        secondary: viewButton.value,
        primary: listButton.value,
      }
    : { primary: viewButton.value },
)

const handleViewNft = () => {
  window.open(
    singleMint.value ? nftPath.value : userProfilePath.value,
    '_blank',
  )
}

const listNft = () => {
  emit('list')
}

watch(
  () => props.canListNfts,
  (canListNft) => {
    if (canListNft) {
      toast($i18n.t('drops.canList'))
    }
  },
)
</script>