diff --git a/src/assets/images/nft/books/collector-message-item-background-lg.svg b/src/assets/images/nft/books/collector-message-item-background-lg.svg new file mode 100644 index 000000000..bf670be71 --- /dev/null +++ b/src/assets/images/nft/books/collector-message-item-background-lg.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/nft/books/collector-message-item-background.svg b/src/assets/images/nft/books/collector-message-item-background.svg new file mode 100644 index 000000000..86586ec7f --- /dev/null +++ b/src/assets/images/nft/books/collector-message-item-background.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/CollapsibleCard.vue b/src/components/CollapsibleCard.vue index d6cb36768..b377fcb05 100644 --- a/src/components/CollapsibleCard.vue +++ b/src/components/CollapsibleCard.vue @@ -83,10 +83,14 @@ export default { type: Boolean, default: true, }, + defaultOpen: { + type: Boolean, + default: true, + }, }, data() { return { - isOpen: true, + isOpen: this.defaultOpen, }; }, computed: { diff --git a/src/components/NFTMessage/Identity.vue b/src/components/NFTMessage/Identity.vue index b3a16ed22..7ffa19214 100644 --- a/src/components/NFTMessage/Identity.vue +++ b/src/components/NFTMessage/Identity.vue @@ -36,9 +36,12 @@ > {{ userLabel }} - + diff --git a/src/components/NFTPage/ChainDataSection/index.vue b/src/components/NFTPage/ChainDataSection/index.vue index c61b80bb4..47c3585ca 100644 --- a/src/components/NFTPage/ChainDataSection/index.vue +++ b/src/components/NFTPage/ChainDataSection/index.vue @@ -2,6 +2,7 @@ @@ -479,6 +527,10 @@ export default { customPrice: 0, isOpeningCheckoutPage: false, + + isHistoryInfoLoading: false, + hasHistoryInfoLoaded: false, + isOpeningCollectorListDialog: false, }; }, async fetch({ route, store, redirect, error, localeLocation }) { @@ -936,6 +988,7 @@ export default { shouldShowFollowButton() { return Boolean(this.iscnOwner !== this.getAddress); }, + // for WNFT populatedCollectorsWithMemo() { if (!this.populatedDisplayEvents) { return this.populatedCollectors; @@ -967,6 +1020,7 @@ export default { } return collectorsWithMemo; }, + // for collector dialog populatedBuyerWithMessage() { if (!this.populatedDisplayEvents) { return this.populatedCollectors; @@ -1001,6 +1055,62 @@ export default { } return collectorsWithBuyerMessages; }, + // for collector message list + filterCollectorsWithReplies() { + if (!this.populatedDisplayEvents || !this.populatedCollectors) { + return []; + } + const collectorsWithReplies = this.populatedCollectors + .map(collector => { + const purchaseEvent = this.populatedDisplayEvents.find( + event => + event.event === 'purchase' && event.toWallet === collector.id + ); + + const transferEvent = this.populatedDisplayEvents.find( + event => + event.event === 'transfer' && event.toWallet === collector.id + ); + + let buyerMessage = null; + let authorReply = null; + + if (purchaseEvent) { + buyerMessage = purchaseEvent.buyerMessage || null; + } else if (transferEvent) { + buyerMessage = transferEvent.buyerMessage || null; + authorReply = transferEvent.memo || null; + } + + if (!buyerMessage) { + return null; + } + + return { + ...collector, + buyerMessage, + authorReply, + }; + }) + .filter(Boolean); + + if (collectorsWithReplies && collectorsWithReplies.length) { + collectorsWithReplies.sort((a, b) => { + if (a.buyerMessage && !b.buyerMessage) { + return -1; + } + if (!a.buyerMessage && b.buyerMessage) { + return 1; + } + return 0; + }); + } + + return collectorsWithReplies; + }, + shouldShowCollectorMessage() { + return this.filterCollectorsWithReplies?.length > 3; + }, isShowBanner() { return ( this.classId === @@ -1026,6 +1136,16 @@ export default { : 'nft_edition_select_compare_button_text' ); }, + overlayClasses() { + return [ + 'h-full', + 'w-[60px]', + 'from-light-gray', + 'to-transparent', + 'hidden', + 'laptop:block', + ]; + }, }, async mounted() { try { @@ -1100,6 +1220,7 @@ export default { ]), parseNFTMetadataURL, async fetchTrimmedCollectorsInfo() { + this.isHistoryInfoLoading = true; const trimmedCollectors = this.sortedOwnerListId.slice( 0, this.trimmedCount @@ -1108,6 +1229,8 @@ export default { this.lazyGetUserInfoByAddresses(trimmedCollectors), this.updateNFTHistory({ getAllUserInfo: false }), ]); + this.isHistoryInfoLoading = false; + this.hasHistoryInfoLoaded = true; }, getPurchaseEventParams(edition) { const customPriceInDecimal = this.customPrice @@ -1140,6 +1263,17 @@ export default { ); await this.lazyGetUserInfoByAddresses(this.sortedOwnerListId); }, + async handleClickMoreCollectorMessage() { + this.isOpeningCollectorListDialog = true; + logTrackerEvent( + this, + 'NFT', + 'class_details_show_more_collector_clicked', + this.classId, + 1 + ); + await this.lazyGetUserInfoByAddresses(this.sortedOwnerListId); + }, async handleClickMoreHistory() { logTrackerEvent( this, diff --git a/src/util/ui.js b/src/util/ui.js index 5e5ffee3a..eb07f4e21 100644 --- a/src/util/ui.js +++ b/src/util/ui.js @@ -9,16 +9,15 @@ const largeNumFormatter = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2, }); -export function ellipsis(value) { - if (value) { - const len = value.length; - const dots = '...'; - if (!value) return ''; - if (value.length > 20) { - return value.substring(0, 8) + dots + value.substring(len - 6, len); - } - return value; +export function ellipsis(value, maxLength = 20, endLength = 6) { + if (!value) return ''; + const len = value.length; + const dots = '...'; + + if (len > maxLength) { + return value.substring(0, 8) + dots + value.substring(len - endLength, len); } + return value; }