Skip to content

Commit

Permalink
✨ Prioritize cross-sell items in the recommendation list (#1908)
Browse files Browse the repository at this point in the history
* 🔧 Add cross sell items

* 🎨 Add check to disable cross-sell feature

* ✨ Prioritize cross-sell items in the recommendation list

* ♻️ Update recommendation list using cross-sell mixin

* 🔧 Add cross sell items

* ♻️ Simplify recommendation list
  • Loading branch information
AuroraHuang22 authored Oct 22, 2024
1 parent 0f055e8 commit aaca319
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 18 deletions.
42 changes: 28 additions & 14 deletions src/components/NFTPage/Recommendation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,15 @@
<script>
import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
import { DEFAULT_RECOMMENDATIONS_LIST } from '~/constant';
import {
DEFAULT_RECOMMENDATIONS_LIST,
CROSS_SELL_PRODUCT_IDS_MAP,
} from '~/constant';
import bookstoreMixin from '~/mixins/bookstore';
import nftOrCollection from '~/mixins/nft-or-collection';
import walletMixin from '~/mixins/wallet';
import crossSellMixin from '~/mixins/cross-sell';
import { mapActions, mapGetters } from 'vuex';
const DISPLAY_ITEM_COUNT = 5;
Expand All @@ -112,7 +116,7 @@ export default {
Swiper,
SwiperSlide,
},
mixins: [bookstoreMixin, nftOrCollection, walletMixin],
mixins: [bookstoreMixin, nftOrCollection, walletMixin, crossSellMixin],
props: {
classId: {
type: String,
Expand Down Expand Up @@ -188,18 +192,6 @@ export default {
this.getNFTClassFeaturedSetByAddress(this.productOwner) || new Set();
const hiddenSet =
this.getNFTClassHiddenSetByAddress(this.productOwner) || new Set();
const userCollected = this.getAddress
? this.getCollectedNFTClassesByAddress(this.getAddress)
: [];
if (userCollected?.length) {
recommendedList = recommendedList.filter(
item =>
!userCollected.some(
collectedItem => collectedItem.classId === item.classId
)
);
}
recommendedList = recommendedList.filter(item => {
const isNotHidden = !hiddenSet.has(item.classId);
Expand Down Expand Up @@ -237,6 +229,28 @@ export default {
});
}
recommendedList = [
...this.crossSellProductIds?.map(classId => ({ classId })),
...recommendedList,
];
recommendedList = Array.from(
new Map(recommendedList.map(item => [item.classId, item])).values()
);
const userCollected = this.getAddress
? this.getCollectedNFTClassesByAddress(this.getAddress)
: [];
if (userCollected?.length) {
recommendedList = recommendedList.filter(
item =>
!userCollected.some(
collectedItem => collectedItem.classId === item.classId
)
);
}
return recommendedList.slice(0, DISPLAY_ITEM_COUNT);
},
swiperOptions() {
Expand Down
16 changes: 16 additions & 0 deletions src/constant/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,13 +311,29 @@ export const CROSS_SELL_PRODUCT_IDS_MAP = IS_TESTNET
'likenft1rfd3pp4q4hvuha8xpl8wzzf7uwannv0wm05s7jz34828e4qjnyzsfd9srz',
],
likenft154xhw0qyds5pgvsyc7379lnkyvwqkvv2zvmmh2gn5qrewljeqwys2sju6x: [
'likenft17zq3r5t2qwfatle04sz680vl3ka0l8wfeu4n5jv26mnvawnfqs4qd773ny',
'likenft1mppyvyuvvft62yc66saee28q8nyl6xuh8vg332d8y9fn6gz9qtssj4trzl',
],
likenft1ekvx3en9l0640kv9fd5n5hvltwyfl443ymyu2cnhmalvjfy0cdcqqa3l6h: [
'likenft16cns9jk7cathhpe62v6jpyxam6z8ltdk3jw08xpmkrz53s3cknxqulpd0u',
],
likenft17zq3r5t2qwfatle04sz680vl3ka0l8wfeu4n5jv26mnvawnfqs4qd773ny: [
'likenft154xhw0qyds5pgvsyc7379lnkyvwqkvv2zvmmh2gn5qrewljeqwys2sju6x',
],
likenft1l2v3qdv4qj0pyv2tmme42dv0962csaxxhezk04jr9s2rved08s4s4x6633: [
'likenft1434x9tl07ysrjq9lvxv0thgn0zt2fxwhntefd249lawrznw08lrskr3jfp',
],
likenft1434x9tl07ysrjq9lvxv0thgn0zt2fxwhntefd249lawrznw08lrskr3jfp: [
'likenft1l2v3qdv4qj0pyv2tmme42dv0962csaxxhezk04jr9s2rved08s4s4x6633',
],
};

export const DISABLED_CROSS_SELL_POPUP_LIST = [
'likenft17zq3r5t2qwfatle04sz680vl3ka0l8wfeu4n5jv26mnvawnfqs4qd773ny', // 坐監情緒學
'likenft1434x9tl07ysrjq9lvxv0thgn0zt2fxwhntefd249lawrznw08lrskr3jfp', // 來一場散步學
'likenft1l2v3qdv4qj0pyv2tmme42dv0962csaxxhezk04jr9s2rved08s4s4x6633', // 鯨魚之城
];

export const AFFILIATION_CHANNEL_LEGACY_STRINGS = {
'Muddy Water': '@muddydirtywater',
bchai: '@edmondyu',
Expand Down
17 changes: 13 additions & 4 deletions src/mixins/cross-sell.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { mapGetters } from 'vuex';
import {
CROSS_SELL_PRODUCT_PROBABILITY,
CROSS_SELL_PRODUCT_IDS_MAP,
DISABLED_CROSS_SELL_POPUP_LIST,
IS_TESTNET,
} from '~/constant';

Expand All @@ -11,9 +12,6 @@ export default {
return {
isCrossSellDialogOpen: false,
crossSellProductIndex: 0,
isEnableCrossSell: IS_TESTNET
? true
: Math.random() < CROSS_SELL_PRODUCT_PROBABILITY,
};
},
computed: {
Expand Down Expand Up @@ -44,8 +42,19 @@ export default {
!this.getShoppingCartBookProductQuantity(this.crossSellProductId)
);
},
isCrossSellEnabled() {
const shouldAttemptCrossSell = IS_TESTNET
? true
: Math.random() < CROSS_SELL_PRODUCT_PROBABILITY;

const isCrossSellBlocked = [this.classId, this.collectionId].some(id =>
DISABLED_CROSS_SELL_POPUP_LIST.includes(id)
);

return shouldAttemptCrossSell && !isCrossSellBlocked;
},
shouldCrossSell() {
return this.isEnableCrossSell && this.hasCrossSell;
return this.isCrossSellEnabled && this.hasCrossSell;
},
},
watch: {
Expand Down

0 comments on commit aaca319

Please sign in to comment.