@anker-in/campaign-ui 0.5.0-beta.4 → 0.5.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/cjs/components/credits/context/hooks/useCountries.js +1 -1
  2. package/dist/cjs/components/credits/context/hooks/useCountries.js.map +3 -3
  3. package/dist/cjs/components/memberPopup/MemberPopup.js +1 -1
  4. package/dist/cjs/components/memberPopup/MemberPopup.js.map +3 -3
  5. package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.d.ts +10 -0
  6. package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.js +2 -0
  7. package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.js.map +7 -0
  8. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/index.js +1 -1
  9. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/index.js.map +3 -3
  10. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.d.ts +11 -0
  11. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js +2 -0
  12. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js.map +7 -0
  13. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeModal.js +1 -1
  14. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeModal.js.map +2 -2
  15. package/dist/cjs/components/memberPopup/panels/EarnCredits/index.js +1 -1
  16. package/dist/cjs/components/memberPopup/panels/EarnCredits/index.js.map +2 -2
  17. package/dist/cjs/components/memberPopup/panels/Referral/index.js +1 -1
  18. package/dist/cjs/components/memberPopup/panels/Referral/index.js.map +2 -2
  19. package/dist/cjs/components/memberPopup/type.d.ts +14 -2
  20. package/dist/cjs/components/memberPopup/type.js +1 -1
  21. package/dist/cjs/components/memberPopup/type.js.map +2 -2
  22. package/dist/esm/components/credits/context/hooks/useCountries.js +1 -1
  23. package/dist/esm/components/credits/context/hooks/useCountries.js.map +3 -3
  24. package/dist/esm/components/memberPopup/MemberPopup.js +1 -1
  25. package/dist/esm/components/memberPopup/MemberPopup.js.map +3 -3
  26. package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.d.ts +10 -0
  27. package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.js +2 -0
  28. package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.js.map +7 -0
  29. package/dist/esm/components/memberPopup/panels/ConsumeCredits/index.js +1 -1
  30. package/dist/esm/components/memberPopup/panels/ConsumeCredits/index.js.map +3 -3
  31. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.d.ts +11 -0
  32. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js +2 -0
  33. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js.map +7 -0
  34. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeModal.js +1 -1
  35. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeModal.js.map +2 -2
  36. package/dist/esm/components/memberPopup/panels/EarnCredits/index.js +1 -1
  37. package/dist/esm/components/memberPopup/panels/EarnCredits/index.js.map +2 -2
  38. package/dist/esm/components/memberPopup/panels/Referral/index.js +1 -1
  39. package/dist/esm/components/memberPopup/panels/Referral/index.js.map +2 -2
  40. package/dist/esm/components/memberPopup/type.d.ts +14 -2
  41. package/dist/esm/components/memberPopup/type.js +1 -1
  42. package/dist/esm/components/memberPopup/type.js.map +2 -2
  43. package/package.json +1 -1
  44. package/src/components/credits/context/hooks/useCountries.ts +1 -2
  45. package/src/components/memberPopup/MemberPopup.tsx +17 -13
  46. package/src/components/memberPopup/panels/ActivitiesSubscribePanel.tsx +198 -0
  47. package/src/components/memberPopup/panels/ConsumeCredits/index.tsx +39 -14
  48. package/src/components/memberPopup/panels/EarnCredits/index.tsx +94 -64
  49. package/src/components/memberPopup/panels/Referral/index.tsx +1 -1
  50. package/src/components/memberPopup/type.ts +10 -1
  51. package/src/components/memberPopup/panels/EarnCredits/SubscribeModal.tsx +0 -144
  52. package/src/components/memberPopup/panels/EarnCredits/SubscribePanel.tsx +0 -147
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/memberPopup/type.ts"],
4
- "sourcesContent": ["import type { AuthCodeActivateCopy } from '../registration/authCodeActivate/type'\nimport type { CreditInfoResponse } from '../credits/context/response'\nimport type { DTC_TASK_TYPE } from '../credits/context/const'\n\nexport type { AuthCodeActivateCopy }\n\n// \u2500\u2500\u2500 \u9762\u677F\u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum MemberPopupPanelType {\n EarnCredits = 'EARN_CREDITS',\n ConsumeCredits = 'CONSUME_CREDITS',\n Referral = 'REFERRAL',\n CompleteProfile = 'COMPLETE_PROFILE',\n Subscribe = 'SUBSCRIBE',\n SubscribeEmail = 'SUBSCRIBE_EMAIL',\n RedeemCoupon = 'REDEEM_COUPON',\n Activate = 'ACTIVATE',\n}\n\n// \u2500\u2500\u2500 item action \u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum MemberPopupActionType {\n ExternalLink = 'EXTERNAL_LINK',\n OpenEarnCredits = 'OPEN_EARN_CREDITS',\n OpenConsumeCredits = 'OPEN_CONSUME_CREDITS',\n OpenReferral = 'OPEN_REFERRAL',\n OpenSubscribe = 'OPEN_SUBSCRIBE',\n}\n\n// \u2500\u2500\u2500 EarnCredits \u4EFB\u52A1\u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum EarnCreditsTaskType {\n Activate = 'activate',\n CompleteProfile = 'completeProfile',\n Subscribe = 'subscribe',\n Shop = 'shop',\n}\n\n// \u2500\u2500\u2500 ConsumeCredits item \u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum ConsumeCreditsItemType {\n Coupon = 'COUPON',\n RedeemAndBuy = 'REDEEM_AND_BUY',\n}\n\n// \u2500\u2500\u2500 \u901A\u7528 link\uFF08\u7EDF\u4E00\u4E00\u79CD\u7C7B\u578B\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type MemberPopupLink = {\n type: MemberPopupActionType\n label: string\n url?: string // \u4EC5 ExternalLink \u65F6\u4F7F\u7528\n}\n\n// \u2500\u2500\u2500 list item \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type MemberPopupItem = {\n title: string\n description?: string\n links: MemberPopupLink[]\n}\n\n// \u2500\u2500 \u4E3B\u7EC4\u4EF6 Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum MemberPopupPageScope {\n /** \u5168\u5C40\u5C55\u793A */\n Global = 'GLOBAL',\n /** \u4EC5\u5728\u7279\u5B9A\u9875\u9762\u5C55\u793A */\n Include = 'INCLUDE',\n /** \u5728\u7279\u5B9A\u9875\u9762\u4E0D\u5C55\u793A */\n Exclude = 'EXCLUDE',\n}\n\nexport type MemberPopupPageConfig = {\n scope: MemberPopupPageScope\n /** \u9875\u9762\u8DEF\u5F84\u5217\u8868\uFF0C\u652F\u6301\u7CBE\u786E\u5339\u914D\u548C\u524D\u7F00\u5339\u914D\uFF08\u5982 \"/products\" \u4F1A\u5339\u914D \"/products/xxx\"\uFF09 */\n pages: string[]\n}\n\nexport type MemberPopupCopy = {\n triggerImg: { url: string; alt?: string }\n title?: string\n subtitle?: string\n list: MemberPopupItem[]\n footer?: {\n loginHint: string\n loginLabel: string\n joinLabel: string\n shopLabel: string\n shopUrl?: string\n }\n subscribe?: SubscribeModalCopy\n earnCredits?: EarnCreditsCopy\n consumeCredits?: ConsumeCreditsopy\n referral?: ReferralCopy\n /** \u9875\u9762\u8986\u76D6\u8303\u56F4\u914D\u7F6E\uFF0C\u9ED8\u8BA4\u5168\u5C40\u5C55\u793A */\n pageConfig?: MemberPopupPageConfig\n}\n\n// \u2500\u2500\u2500 EarnCredits Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type EarnCreditsCopy = {\n title?: string\n subtitle?: string\n balanceLabel?: string\n comingSoonLabel?: string\n creditUnit?: string\n joinNow: string\n completed: string\n activate: string\n completeProfileLabel: string\n subscribeLabel: string\n shopNow: string\n goShopLink?: string\n list: {\n id: EarnCreditsTaskType\n title: string\n description: string\n credits?: string\n }[]\n // \u5B50\u5F39\u7A97\u6587\u6848\n authCodeActivate: AuthCodeActivateCopy\n completeProfile: CompleteProfileCopy\n subscribe: SubscribeModalCopy\n}\n\nexport type CompleteProfileCopy = {\n title: string\n subtitle?: string\n firstName: string\n lastName: string\n email: string\n phone: string\n birthday: string\n country: string\n save: string\n cancel: string\n edit: string\n required: string\n}\n\nexport type SubscribeModalCopy = {\n title: string\n desc?: string\n placeholder: string\n policy?: string\n successTips?: string\n dealsType?: string\n buttonLabel?: string\n single_brand_subscribe?: boolean\n genre?: string\n sub_brand_type?: string\n}\n\n// \u2500\u2500\u2500 ConsumeCredits Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type ConsumeCreditsopy = {\n title?: string\n subtitle?: string\n soldOut: string\n unlockRewards: string\n btnRedeem: string\n insufficientCredits?: string\n pointUnit?: string\n off?: string\n imageMapping?: {\n [key in ConsumeCreditsItemType]?: { url: string }\n }\n list: ConsumeCreditsItem[]\n redeemModal: RedeemCouponModalCopy\n creditsPage?: { label: string; url: string }\n}\n\nexport type ConsumeCreditsItem = {\n redeemId: string | number\n title: string\n description?: string\n image: { url: string; alt?: string }\n type: ConsumeCreditsItemType\n product?: { handle: string; sku: string }\n price?: number\n value?: string\n rules?: string[]\n}\n\nexport type RedeemCouponModalCopy = {\n confirmTitle: string\n confirmButton: string\n commonError: string\n redeemLimitError: string\n inventoryNotEnough: string\n creditsNotEnough: string\n crossSiteError: string\n successTitle: string\n successDesc: string\n successButton: string\n successButtonUrl?: string\n}\n\n// \u2500\u2500\u2500 Referral Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type ReferralCopy = {\n title?: string\n description?: string\n cashAvailableLabel: string\n cashPendingLabel: string\n creditUnit?: string\n referralLinksLabel?: string\n referralLinkBaseUrl?: string\n copyLabel?: string\n copiedLabel?: string\n howToTitle?: string\n howToDescription?: string\n learnMoreLabel?: string\n learnMoreUrl?: string\n image?: { url: string; alt?: string }\n ctaButton: string\n ctaUrl?: string\n loginTitle?: string\n loginDescription?: string\n loginCtaLabel?: string\n}\n\n// \u2500\u2500\u2500 Provider Context \u7C7B\u578B \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type AlpcConfig = {\n brand: string\n locale: string\n appName: string\n apiBaseUrl?: string\n}\n\nexport type MemberPopupContextValue = {\n profile: any\n isLoadingProfile: boolean\n creditInfo?: CreditInfoResponse\n fetchCreditInfo: (userId: string) => void\n openSignUpPopup: () => void\n openSignInPopup: () => void\n taskIdToTypeMapping?: Record<string, DTC_TASK_TYPE>\n alpcConfig: AlpcConfig\n}\n"],
5
- "mappings": "AAOO,IAAKA,OACVA,EAAA,YAAc,eACdA,EAAA,eAAiB,kBACjBA,EAAA,SAAW,WACXA,EAAA,gBAAkB,mBAClBA,EAAA,UAAY,YACZA,EAAA,eAAiB,kBACjBA,EAAA,aAAe,gBACfA,EAAA,SAAW,WARDA,OAAA,IAYAC,OACVA,EAAA,aAAe,gBACfA,EAAA,gBAAkB,oBAClBA,EAAA,mBAAqB,uBACrBA,EAAA,aAAe,gBACfA,EAAA,cAAgB,iBALNA,OAAA,IASAC,OACVA,EAAA,SAAW,WACXA,EAAA,gBAAkB,kBAClBA,EAAA,UAAY,YACZA,EAAA,KAAO,OAJGA,OAAA,IAQAC,OACVA,EAAA,OAAS,SACTA,EAAA,aAAe,iBAFLA,OAAA,IAoBAC,OAEVA,EAAA,OAAS,SAETA,EAAA,QAAU,UAEVA,EAAA,QAAU,UANAA,OAAA",
4
+ "sourcesContent": ["import type { AuthCodeActivateCopy } from '../registration/authCodeActivate/type'\nimport type { CreditInfoResponse } from '../credits/context/response'\nimport type { DTC_TASK_TYPE } from '../credits/context/const'\n\nexport type { AuthCodeActivateCopy }\n\n// \u2500\u2500\u2500 \u9762\u677F\u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum MemberPopupPanelType {\n EarnCredits = 'EARN_CREDITS',\n ConsumeCredits = 'CONSUME_CREDITS',\n Referral = 'REFERRAL',\n CompleteProfile = 'COMPLETE_PROFILE',\n Subscribe = 'SUBSCRIBE',\n SubscribeEmail = 'SUBSCRIBE_EMAIL',\n RedeemCoupon = 'REDEEM_COUPON',\n Activate = 'ACTIVATE',\n}\n\n// \u2500\u2500\u2500 item action \u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum MemberPopupActionType {\n ExternalLink = 'EXTERNAL_LINK',\n OpenEarnCredits = 'OPEN_EARN_CREDITS',\n OpenConsumeCredits = 'OPEN_CONSUME_CREDITS',\n OpenReferral = 'OPEN_REFERRAL',\n OpenSubscribe = 'OPEN_SUBSCRIBE',\n}\n\n// \u2500\u2500\u2500 EarnCredits \u4EFB\u52A1\u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum EarnCreditsTaskType {\n Activate = 'activate',\n CompleteProfile = 'completeProfile',\n Subscribe = 'subscribe',\n Shop = 'shop',\n}\n\n// \u2500\u2500\u2500 ConsumeCredits item \u7C7B\u578B\u679A\u4E3E \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum ConsumeCreditsItemType {\n Coupon = 'COUPON',\n RedeemAndBuy = 'REDEEM_AND_BUY',\n GiftCard = 'GIFT_CARD',\n Product = 'PRODUCT',\n}\n\n// \u2500\u2500\u2500 \u901A\u7528 link\uFF08\u7EDF\u4E00\u4E00\u79CD\u7C7B\u578B\uFF09 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type MemberPopupLink = {\n type: MemberPopupActionType\n label: string\n url?: string // \u4EC5 ExternalLink \u65F6\u4F7F\u7528\n}\n\n// \u2500\u2500\u2500 list item \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type MemberPopupItem = {\n title: string\n description?: string\n links: MemberPopupLink[]\n}\n\n// \u2500\u2500 \u4E3B\u7EC4\u4EF6 Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport enum MemberPopupPageScope {\n /** \u5168\u5C40\u5C55\u793A */\n Global = 'GLOBAL',\n /** \u4EC5\u5728\u7279\u5B9A\u9875\u9762\u5C55\u793A */\n Include = 'INCLUDE',\n /** \u5728\u7279\u5B9A\u9875\u9762\u4E0D\u5C55\u793A */\n Exclude = 'EXCLUDE',\n}\n\nexport type MemberPopupPageConfig = {\n scope: MemberPopupPageScope\n /** \u9875\u9762\u8DEF\u5F84\u5217\u8868\uFF0C\u652F\u6301\u7CBE\u786E\u5339\u914D\u548C\u524D\u7F00\u5339\u914D\uFF08\u5982 \"/products\" \u4F1A\u5339\u914D \"/products/xxx\"\uFF09 */\n pages: string[]\n}\n\nexport type MemberPopupCopy = {\n triggerImg: { url: string; alt?: string }\n title?: string\n subtitle?: string\n list: MemberPopupItem[]\n footer?: {\n loginHint: string\n loginLabel: string\n joinLabel: string\n shopLabel: string\n shopUrl?: string\n }\n activitiesSubscribe?: SubscribeModalCopy\n earnCredits?: EarnCreditsCopy\n consumeCredits?: ConsumeCreditsopy\n referral?: ReferralCopy\n /** \u9875\u9762\u8986\u76D6\u8303\u56F4\u914D\u7F6E\uFF0C\u9ED8\u8BA4\u5168\u5C40\u5C55\u793A */\n pageConfig?: MemberPopupPageConfig\n}\n\n// \u2500\u2500\u2500 EarnCredits Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type EarnCreditsCopy = {\n title?: string\n subtitle?: string\n balanceLabel?: string\n comingSoonLabel?: string\n creditUnit?: string\n joinNow: string\n completed: string\n activate: string\n completeProfileLabel: string\n subscribeLabel: string\n shopNow: string\n goShopLink?: string\n list: {\n id: EarnCreditsTaskType\n title: string\n description: string\n credits?: string\n }[]\n // \u5B50\u5F39\u7A97\u6587\u6848\n authCodeActivate: AuthCodeActivateCopy\n completeProfile: CompleteProfileCopy\n subscribe: SubscribeModalCopy\n}\n\nexport type CompleteProfileCopy = {\n title: string\n subtitle?: string\n firstName: string\n lastName: string\n email: string\n phone: string\n birthday: string\n country: string\n save: string\n cancel: string\n edit: string\n required: string\n}\n\nexport type SubscribeModalCopy = {\n title: string\n desc?: string\n placeholder: string\n policy?: string\n successTips?: string\n dealsType?: string\n buttonLabel?: string\n single_brand_subscribe?: boolean\n genre?: string\n sub_brand_type?: string\n promo?: {\n title?: string\n description?: string\n learnMoreLabel?: string\n learnMoreUrl?: string\n image?: { url: string; alt?: string }\n }\n}\n\n// \u2500\u2500\u2500 ConsumeCredits Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type ConsumeCreditsopy = {\n title?: string\n subtitle?: string\n soldOut: string\n unlockRewards: string\n btnRedeem: string\n insufficientCredits?: string\n pointUnit?: string\n off?: string\n imageMapping?: {\n [key in ConsumeCreditsItemType]?: { url: string }\n }\n list: ConsumeCreditsItem[]\n redeemModal: RedeemCouponModalCopy\n creditsPage?: { label: string; url: string }\n}\n\nexport type ConsumeCreditsItem = {\n redeemId: string | number\n title: string\n description?: string\n image: { url: string; alt?: string }\n type: ConsumeCreditsItemType\n product?: { handle: string; sku: string }\n price?: number\n value?: string\n rules?: string[]\n}\n\nexport type RedeemCouponModalCopy = {\n confirmTitle: string\n confirmButton: string\n commonError: string\n redeemLimitError: string\n inventoryNotEnough: string\n creditsNotEnough: string\n crossSiteError: string\n successTitle: string\n successDesc: string\n successButton: string\n successButtonUrl?: string\n}\n\n// \u2500\u2500\u2500 Referral Copy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type ReferralCopy = {\n title?: string\n description?: string\n cashAvailableLabel: string\n cashPendingLabel: string\n creditUnit?: string\n referralLinksLabel?: string\n referralLinkBaseUrl?: string\n copyLabel?: string\n copiedLabel?: string\n howToTitle?: string\n howToDescription?: string\n learnMoreLabel?: string\n learnMoreUrl?: string\n image?: { url: string; alt?: string }\n ctaButton: string\n ctaUrl?: string\n loginTitle?: string\n loginDescription?: string\n loginCtaLabel?: string\n}\n\n// \u2500\u2500\u2500 Provider Context \u7C7B\u578B \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type AlpcConfig = {\n brand: string\n locale: string\n appName: string\n apiBaseUrl?: string\n}\n\nexport type MemberPopupContextValue = {\n profile: any\n isLoadingProfile: boolean\n creditInfo?: CreditInfoResponse\n fetchCreditInfo: (userId: string) => void\n openSignUpPopup: () => void\n openSignInPopup: () => void\n taskIdToTypeMapping?: Record<string, DTC_TASK_TYPE>\n alpcConfig: AlpcConfig\n}\n"],
5
+ "mappings": "AAOO,IAAKA,OACVA,EAAA,YAAc,eACdA,EAAA,eAAiB,kBACjBA,EAAA,SAAW,WACXA,EAAA,gBAAkB,mBAClBA,EAAA,UAAY,YACZA,EAAA,eAAiB,kBACjBA,EAAA,aAAe,gBACfA,EAAA,SAAW,WARDA,OAAA,IAYAC,OACVA,EAAA,aAAe,gBACfA,EAAA,gBAAkB,oBAClBA,EAAA,mBAAqB,uBACrBA,EAAA,aAAe,gBACfA,EAAA,cAAgB,iBALNA,OAAA,IASAC,OACVA,EAAA,SAAW,WACXA,EAAA,gBAAkB,kBAClBA,EAAA,UAAY,YACZA,EAAA,KAAO,OAJGA,OAAA,IAQAC,OACVA,EAAA,OAAS,SACTA,EAAA,aAAe,iBACfA,EAAA,SAAW,YACXA,EAAA,QAAU,UAJAA,OAAA,IAsBAC,OAEVA,EAAA,OAAS,SAETA,EAAA,QAAU,UAEVA,EAAA,QAAU,UANAA,OAAA",
6
6
  "names": ["MemberPopupPanelType", "MemberPopupActionType", "EarnCreditsTaskType", "ConsumeCreditsItemType", "MemberPopupPageScope"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anker-in/campaign-ui",
3
- "version": "0.5.0-beta.04",
3
+ "version": "0.5.0-beta.05",
4
4
  "description": "Campaign UI components and utilities for Anker projects",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -20,8 +20,7 @@ function useCountries({ shopifyStoreDomain }: { shopifyStoreDomain: string }) {
20
20
  })
21
21
  const res: any = await response.json()
22
22
 
23
- // 新接口直接返回国家数组 [{ id, name, code }]
24
- let shipsToCountries: ShippingCountry[] = res?.data || res || []
23
+ let shipsToCountries: ShippingCountry[] = res?.data?.data || []
25
24
 
26
25
  // 字母顺序排序
27
26
  shipsToCountries = shipsToCountries.sort((a, b) => {
@@ -21,7 +21,7 @@ const EarnCredits = lazy(() => import('./panels/EarnCredits'))
21
21
  const ConsumeCredits = lazy(() => import('./panels/ConsumeCredits'))
22
22
  const Referral = lazy(() => import('./panels/Referral'))
23
23
  const CompleteProfile = lazy(() => import('./panels/EarnCredits/CompleteProfilePanel'))
24
- const Subscribe = lazy(() => import('./panels/EarnCredits/SubscribePanel'))
24
+ const ActivitiesSubscribe = lazy(() => import('./panels/ActivitiesSubscribePanel'))
25
25
  const SubscribeEmail = lazy(() => import('./panels/EarnCredits/SubscribeEmailPanel'))
26
26
  const Activate = lazy(() => import('./panels/EarnCredits/ActivatePanel'))
27
27
  const RedeemCoupon = lazy(() => import('./panels/ConsumeCredits/RedeemCouponPanel'))
@@ -55,6 +55,7 @@ function MemberPopupContent({ copy, bottomOffset }: MemberPopupContentProps) {
55
55
  const [isSubscribeSuccess, setIsSubscribeSuccess] = useState(false)
56
56
  const [isActivateSuccess, setIsActivateSuccess] = useState(false)
57
57
  const [isProfileCompleteSuccess, setIsProfileCompleteSuccess] = useState(false)
58
+ const [isSubscribeFormHidden, setIsSubscribeFormHidden] = useState(false)
58
59
 
59
60
  const currentView = viewStack[viewStack.length - 1] ?? null
60
61
 
@@ -106,21 +107,26 @@ function MemberPopupContent({ copy, bottomOffset }: MemberPopupContentProps) {
106
107
  function handleClose() {
107
108
  setIsOpen(false)
108
109
  setViewStack([])
110
+ setIsSubscribeFormHidden(false)
109
111
  }
110
112
 
111
113
  return (
112
114
  <ViewStackContext.Provider value={{ pushView, popView }}>
113
115
  {isOpen && <div className="fixed inset-0 z-[998]" onClick={handleClose} />}
114
- <div className="fixed right-0 z-[999] flex flex-col items-end pr-[16px]" style={{ bottom: bottomOffset }}>
116
+ <div
117
+ className="fixed right-0 z-[999] flex flex-row items-end pr-[16px] md:flex-col md:items-end md:right-0 md:w-screen md:pr-0 md:pl-0"
118
+ style={{ bottom: bottomOffset }}
119
+ >
115
120
  {isOpen && (
116
121
  <div
117
122
  className={cn(
118
- 'relative mb-[8px] flex w-[420px] max-w-[calc(100vw-32px)] min-h-[600px] flex-col overflow-hidden bg-white shadow-[0_8px_32px_rgba(0,0,0,0.16)] cmp-md:w-[358px] cmp-sm:w-[258px]',
123
+ 'relative mr-[8px] flex w-[420px] max-w-[calc(100vw-32px)] min-h-[500px] flex-col overflow-hidden bg-white shadow-[0_8px_32px_rgba(0,0,0,0.16)] md:mr-0 md:mb-[8px] md:mx-[16px] md:w-[calc(100vw-32px)] md:max-w-[400px]',
119
124
  rounded ? 'rounded-[12px]' : 'rounded-none'
120
125
  )}
126
+ style={{ maxHeight: 'min(80vh, 606px)' }}
121
127
  onClick={e => e.stopPropagation()}
122
128
  >
123
- <div className="absolute right-[-8px] top-[24px] size-0 border-y-8 border-l-8 border-y-transparent border-l-white" />
129
+ <div className="absolute right-[-8px] top-[24px] size-0 border-y-8 border-l-8 border-y-transparent border-l-white md:bottom-[-8px] md:left-auto md:right-[29px] md:top-auto md:border-x-8 md:border-b-transparent md:border-t-white" />
124
130
  <div className="flex items-center justify-end pl-[10px] pr-[16px] pb-[8px] pt-[16px]">
125
131
  {currentView !== null && (
126
132
  <button
@@ -140,10 +146,7 @@ function MemberPopupContent({ copy, bottomOffset }: MemberPopupContentProps) {
140
146
  </button>
141
147
  </div>
142
148
 
143
- <div
144
- className="flex flex-1 flex-col gap-[12px] overflow-y-auto p-[16px]"
145
- style={{ maxHeight: 'min(calc(80vh - 118px), 606px)' }}
146
- >
149
+ <div className="flex flex-1 flex-col gap-[12px] overflow-y-auto p-[16px]">
147
150
  {currentView === null && (
148
151
  <>
149
152
  {(copy.title || copy.subtitle) && (
@@ -196,12 +199,13 @@ function MemberPopupContent({ copy, bottomOffset }: MemberPopupContentProps) {
196
199
  onSuccess={currentView.props?.onSuccess}
197
200
  />
198
201
  )}
199
- {currentView.type === MemberPopupPanelType.Subscribe && copy.subscribe && (
200
- <Subscribe
201
- copy={copy.subscribe}
202
+ {currentView.type === MemberPopupPanelType.Subscribe && copy.activitiesSubscribe && (
203
+ <ActivitiesSubscribe
204
+ copy={copy.activitiesSubscribe}
202
205
  email={profile?.email}
203
- onClose={popView}
204
206
  onSuccess={currentView.props?.onSuccess}
207
+ hideForm={isSubscribeFormHidden}
208
+ onHideForm={() => setIsSubscribeFormHidden(true)}
205
209
  />
206
210
  )}
207
211
  {currentView.type === MemberPopupPanelType.SubscribeEmail && copy.earnCredits && (
@@ -270,7 +274,7 @@ function MemberPopupContent({ copy, bottomOffset }: MemberPopupContentProps) {
270
274
  )}
271
275
 
272
276
  <button
273
- className="flex cursor-pointer items-center justify-center rounded-full bg-white shadow-lg"
277
+ className="flex cursor-pointer items-center justify-center rounded-full bg-white shadow-lg md:ml-auto md:mr-[16px]"
274
278
  onClick={() => setIsOpen(prev => !prev)}
275
279
  aria-label={copy.triggerImg.alt ?? 'Open member popup'}
276
280
  >
@@ -0,0 +1,198 @@
1
+ import { useCallback, useEffect, useState } from 'react'
2
+ import { Button, Checkbox, Picture, Text } from '@anker-in/headless-ui'
3
+ import { classNames as cn, useHeadlessContext } from '@anker-in/lib'
4
+ import Cookies from 'js-cookie'
5
+ import { parse } from 'query-string'
6
+ import { emailValidate } from '../../credits/context/utils'
7
+ import { useMemberPopupContext } from '../context/provider'
8
+ import type { SubscribeModalCopy } from '../type'
9
+ import { ROUNDED_BRANDS } from '../../../constants'
10
+
11
+ type Props = {
12
+ onSuccess?: () => void
13
+ copy: SubscribeModalCopy
14
+ email?: string
15
+ hideForm: boolean
16
+ onHideForm: () => void
17
+ }
18
+
19
+ function getAdCookie() {
20
+ if (typeof window === 'undefined') return { register_source: '' }
21
+ const { search, href } = window.location
22
+ const query = parse(search)
23
+ return {
24
+ fbuy_ref_code: Cookies.get('fbuy_ref_code'),
25
+ ref: Cookies.get('ref_ads'),
26
+ inviter_code: query.ic ?? query.inviter_code ?? Cookies.get('inviter_code'),
27
+ register_source: query.redirect ?? Cookies.get('reg_source') ?? href,
28
+ }
29
+ }
30
+
31
+ async function getRecaptchaToken(sitekey: string): Promise<string> {
32
+ if (typeof window === 'undefined' || !window?.grecaptcha?.execute) return ''
33
+ if (!sitekey) return ''
34
+ try {
35
+ return await window.grecaptcha.execute(sitekey, { action: 'activity' })
36
+ } catch {
37
+ return ''
38
+ }
39
+ }
40
+
41
+ export default function ActivitiesSubscribeModal({
42
+ onSuccess,
43
+ copy,
44
+ email: initialEmail,
45
+ hideForm,
46
+ onHideForm,
47
+ }: Props) {
48
+ const { alpcConfig } = useMemberPopupContext()
49
+ const { locale } = alpcConfig
50
+ const { brand: headlessBrand, storeDomain, recaptchaSitekey } = useHeadlessContext()
51
+ const rounded = ROUNDED_BRANDS.includes(headlessBrand)
52
+ const [policy, setPolicy] = useState(false)
53
+ const [email, setEmail] = useState(initialEmail ?? '')
54
+ const [errorMessage, setErrorMessage] = useState('')
55
+ const [successMessage, setSuccessMessage] = useState('')
56
+ const [loading, setLoading] = useState(false)
57
+
58
+ useEffect(() => {
59
+ if (initialEmail) setEmail(initialEmail)
60
+ }, [initialEmail])
61
+
62
+ const handleSubmit = useCallback(async () => {
63
+ setErrorMessage('')
64
+ if (!email) return setErrorMessage('Please fill in your email')
65
+ if (!emailValidate(email)) return setErrorMessage('Invalid email address')
66
+ if (!policy) return setErrorMessage('Please agree to the policy')
67
+
68
+ setLoading(true)
69
+ const { register_source } = getAdCookie()
70
+ const recaptchaToken = await getRecaptchaToken(recaptchaSitekey || '')
71
+ try {
72
+ const response = await fetch('/api/multipass/rainbowbridge/activities', {
73
+ method: 'POST',
74
+ headers: {
75
+ 'Content-Type': 'application/json',
76
+ 'current-language': locale,
77
+ 'X-Recaptcha-Token': recaptchaToken,
78
+ },
79
+ body: JSON.stringify({
80
+ email,
81
+ register_source,
82
+ shopify_domain: storeDomain,
83
+ single_brand_subscribe: copy.single_brand_subscribe ?? true,
84
+ genre: copy.genre ?? copy.dealsType ?? '',
85
+ sub_brand_type: copy.sub_brand_type ?? '',
86
+ }),
87
+ })
88
+ const result = await response.json()
89
+ if (!result.errors) {
90
+ setSuccessMessage(copy.successTips ?? 'Subscribed successfully!')
91
+ onSuccess?.()
92
+ setTimeout(() => {
93
+ onHideForm()
94
+ setSuccessMessage('')
95
+ }, 3000)
96
+ } else {
97
+ setErrorMessage(result.errors ?? 'Error occurred')
98
+ }
99
+ } catch {
100
+ setErrorMessage('Network error')
101
+ } finally {
102
+ setLoading(false)
103
+ }
104
+ }, [email, policy, locale, storeDomain, copy, onSuccess, onHideForm])
105
+
106
+ return (
107
+ <div className="flex flex-col gap-[16px] text-center">
108
+ {!hideForm && (
109
+ <>
110
+ <Text className="text-[22px] font-bold" html={copy.title} />
111
+ {copy.desc && <Text className="text-left text-[16px] font-semibold text-[#1f2021]" html={copy.desc} />}
112
+ <div
113
+ className={cn(
114
+ 'flex h-[52px] w-full overflow-hidden md:flex-col md:h-auto md:gap-[16px]',
115
+ rounded ? 'rounded-[2px]' : 'rounded-none'
116
+ )}
117
+ >
118
+ <input
119
+ className={cn(
120
+ 'h-[46px] w-full border px-[14px] text-[16px] outline-none placeholder:text-[#999]',
121
+ errorMessage ? 'border-[#f84d4f]' : 'border-[#d8d8d8]',
122
+ rounded ? 'rounded-[4px]' : 'rounded-none'
123
+ )}
124
+ placeholder={copy.placeholder}
125
+ value={email}
126
+ onChange={e => {
127
+ setErrorMessage('')
128
+ setEmail(e.target.value.trim())
129
+ }}
130
+ />
131
+ <Button
132
+ variant="primary"
133
+ loading={loading}
134
+ className={cn(
135
+ '!h-full !min-w-0 !px-[24px] md:!h-[46px]',
136
+ rounded ? '!rounded-l-none !rounded-r-[2px] md:!rounded-[2px]' : '!rounded-none'
137
+ )}
138
+ onClick={handleSubmit}
139
+ >
140
+ {copy.buttonLabel ?? 'Subscribe'}
141
+ </Button>
142
+ </div>
143
+ <div className="flex w-full items-start gap-[8px]">
144
+ <Checkbox checked={policy} onCheckedChange={() => setPolicy(v => !v)} className="border-[#1d1d1f]" />
145
+ <label
146
+ className="text-left text-[14px] font-semibold text-[#777] [&_a]:underline"
147
+ dangerouslySetInnerHTML={{ __html: copy.policy ?? '' }}
148
+ />
149
+ </div>
150
+ {errorMessage && (
151
+ <div className="text-left text-[16px] font-semibold text-[#f84d4f]">
152
+ <Text html={errorMessage} />
153
+ </div>
154
+ )}
155
+ <div className="text-left text-[16px] font-semibold text-[#52c41a]">
156
+ <Text html={successMessage} />
157
+ </div>
158
+ </>
159
+ )}
160
+
161
+ {copy.promo && (
162
+ <div className="flex flex-col text-left">
163
+ <div className="flex flex-col gap-[8px]">
164
+ {copy.promo?.title && (
165
+ <h3 className="text-[20px] font-[700] leading-[1.2] text-[#080a0f]">{copy.promo?.title}</h3>
166
+ )}
167
+ {copy.promo.description && (
168
+ <p className="text-[14px] leading-[1.5] text-[#1e2024]">{copy.promo.description}</p>
169
+ )}
170
+ {copy.promo.learnMoreLabel && copy.promo.learnMoreUrl && (
171
+ <a
172
+ href={copy.promo.learnMoreUrl}
173
+ target="_blank"
174
+ rel="noopener noreferrer"
175
+ className="flex items-center gap-[4px] text-[14px] font-[700] text-[#080a0f] underline"
176
+ >
177
+ {copy.promo.learnMoreLabel}
178
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
179
+ <path
180
+ d="M5.52827 3.52876C5.78862 3.26841 6.21063 3.26841 6.47098 3.52876L10.471 7.52876C10.7313 7.78911 10.7313 8.21112 10.471 8.47147L6.47098 12.4715C6.21063 12.7318 5.78862 12.7318 5.52827 12.4715C5.26792 12.2111 5.26792 11.7891 5.52827 11.5288L9.05692 8.00011L5.52827 4.47147C5.26792 4.21112 5.26792 3.78911 5.52827 3.52876Z"
181
+ fill="#080A0F"
182
+ />
183
+ </svg>
184
+ </a>
185
+ )}
186
+ </div>
187
+ {copy.promo.image?.url && (
188
+ <Picture
189
+ source={copy.promo.image.url}
190
+ alt={copy.promo.image.alt ?? ''}
191
+ className={cn('h-[100px] mt-[8px] w-full object-cover', rounded ? 'rounded-[8px]' : 'rounded-none')}
192
+ />
193
+ )}
194
+ </div>
195
+ )}
196
+ </div>
197
+ )
198
+ }
@@ -56,10 +56,14 @@ function ConsumeCredits({ copy, onClose }: Props) {
56
56
 
57
57
  let product
58
58
  let variant
59
- if (item.type === ConsumeCreditsItemType.RedeemAndBuy && item.product) {
59
+ if (
60
+ (item.type === ConsumeCreditsItemType.RedeemAndBuy ||
61
+ item.type === ConsumeCreditsItemType.Product) &&
62
+ item.product
63
+ ) {
60
64
  product = products?.find((p: any) => p.handle === item.product!.handle)
61
65
  variant = product?.variants?.find((v: any) => v.sku === item.product!.sku) ?? product?.variants?.[0]
62
- if (!product || !variant) return null
66
+ if (item.type === ConsumeCreditsItemType.RedeemAndBuy && (!product || !variant)) return null
63
67
  }
64
68
 
65
69
  return { ...item, alpcData, insufficient, soldOut, product, variant }
@@ -74,6 +78,12 @@ function ConsumeCredits({ copy, onClose }: Props) {
74
78
  }
75
79
 
76
80
  function isDisabled(item: (typeof list)[number]) {
81
+ if (
82
+ item.type === ConsumeCreditsItemType.GiftCard ||
83
+ item.type === ConsumeCreditsItemType.Product
84
+ ) {
85
+ return item.insufficient
86
+ }
77
87
  return item.soldOut || item.insufficient
78
88
  }
79
89
 
@@ -82,6 +92,19 @@ function ConsumeCredits({ copy, onClose }: Props) {
82
92
  openSignUpPopup()
83
93
  return
84
94
  }
95
+ if (!profile?.activated) {
96
+ pushView({ type: MemberPopupPanelType.Activate })
97
+ return
98
+ }
99
+ if (
100
+ item.type === ConsumeCreditsItemType.GiftCard ||
101
+ item.type === ConsumeCreditsItemType.Product
102
+ ) {
103
+ if (copy.creditsPage?.url) {
104
+ window.open(copy.creditsPage.url, '_blank', 'noopener,noreferrer')
105
+ }
106
+ return
107
+ }
85
108
  if (item.type === ConsumeCreditsItemType.Coupon) {
86
109
  pushView({
87
110
  type: MemberPopupPanelType.RedeemCoupon,
@@ -136,17 +159,18 @@ function ConsumeCredits({ copy, onClose }: Props) {
136
159
  </div>
137
160
  ) : (
138
161
  <div className="flex flex-col">
139
- {list.map((item, idx) => (
162
+ {list.map((item, idx) => {
163
+ const hasProduct = !!item.product
164
+ return (
140
165
  <div key={idx} className="relative py-[16px]">
141
166
  {idx > 0 && <div className="absolute inset-x-0 top-0 h-px bg-[#dadce0]" />}
142
167
  <div className="flex items-center gap-[12px]">
143
168
  {(() => {
144
- const isRedeemAndBuy = item.type === ConsumeCreditsItemType.RedeemAndBuy
145
169
  const mappedImgUrl = copy.imageMapping?.[item.type]?.url
146
- const imgUrl = isRedeemAndBuy
170
+ const imgUrl = hasProduct
147
171
  ? (item.variant?.image?.url ?? item.product?.images?.[0]?.url ?? item.image?.url)
148
172
  : (mappedImgUrl ?? item.image?.url)
149
- const imgAlt = isRedeemAndBuy
173
+ const imgAlt = hasProduct
150
174
  ? (item.variant?.image?.altText ?? item.product?.images?.[0]?.alt ?? item.image?.alt ?? '')
151
175
  : (item.image?.alt ?? '')
152
176
  if (!imgUrl) return null
@@ -156,9 +180,9 @@ function ConsumeCredits({ copy, onClose }: Props) {
156
180
  source={imgUrl}
157
181
  alt={imgAlt}
158
182
  className="flex size-full items-center justify-center"
159
- imgClassName={isRedeemAndBuy ? 'object-cover' : 'h-full w-auto object-contain'}
183
+ imgClassName={hasProduct ? 'object-cover' : 'h-full w-auto object-contain'}
160
184
  />
161
- {!isRedeemAndBuy && item.value && (
185
+ {!hasProduct && item.value && (
162
186
  <div className="absolute bottom-[20px] left-[4px] text-[14px] font-[800] leading-none text-white">
163
187
  {item.value} {copy.off}
164
188
  </div>
@@ -168,12 +192,12 @@ function ConsumeCredits({ copy, onClose }: Props) {
168
192
  })()}
169
193
  <div className="min-w-0 flex-1">
170
194
  <div className="text-[16px] font-[700] text-[#1e2024] line-clamp-2">
171
- {item.type === ConsumeCreditsItemType.RedeemAndBuy && item.product?.title
195
+ {hasProduct && item.product?.title
172
196
  ? item.product.title
173
197
  : item.title}
174
198
  </div>
175
199
  <div className="mt-[4px] text-[14px] text-[#666]">
176
- {item.type === ConsumeCreditsItemType.RedeemAndBuy && item.price != null
200
+ {hasProduct && item.price != null
177
201
  ? `${numberFormat(item.alpcData.consume_credits)} ${copy.pointUnit ?? ''} + $${Number(item.price).toFixed(2)}`
178
202
  : `${numberFormat(item.alpcData.consume_credits)} ${copy.pointUnit ?? ''}`}
179
203
  </div>
@@ -188,17 +212,18 @@ function ConsumeCredits({ copy, onClose }: Props) {
188
212
  {getButtonLabel(item)}
189
213
  </Button>
190
214
  {item.insufficient && (
191
- <div className="pointer-events-none absolute left-[48px] top-full mt-[10px] hidden -translate-x-1/2 group-hover:block">
192
- <div className="relative bg-[#6D6D6F] p-[16px] text-[14px] font-[700] text-white shadow md:px-[10px] md:py-[8px]">
215
+ <div className="pointer-events-none absolute right-0 top-full z-[100] mt-[10px] hidden w-[200px] group-hover:block">
216
+ <div className="relative bg-[#6D6D6F] p-[16px] text-[14px] font-[700] text-white shadow">
193
217
  <p className="text-pretty tracking-[-0.02em] text-[14px]">{copy.insufficientCredits}</p>
194
- <div className="absolute -top-[8px] left-[48px] size-[16px] origin-top-left rotate-45 rounded-[2px] bg-[#6D6D6F]" />
218
+ <div className="absolute -top-[8px] right-[20px] size-[16px] origin-top-left rotate-45 rounded-[2px] bg-[#6D6D6F]" />
195
219
  </div>
196
220
  </div>
197
221
  )}
198
222
  </div>
199
223
  </div>
200
224
  </div>
201
- ))}
225
+ )
226
+ })}
202
227
  </div>
203
228
  )}
204
229