@anker-in/campaign-ui 0.5.0-beta.8 → 0.5.0

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 (158) hide show
  1. package/dist/cjs/components/LiveChatWidget/components/MessageContent/TextBlock.js +1 -1
  2. package/dist/cjs/components/LiveChatWidget/components/MessageContent/TextBlock.js.map +3 -3
  3. package/dist/cjs/components/credits/context/hooks/useShippingCountries.d.ts +8 -0
  4. package/dist/cjs/components/credits/context/hooks/useShippingCountries.js +2 -0
  5. package/dist/cjs/components/credits/context/hooks/useShippingCountries.js.map +7 -0
  6. package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Address.js +1 -1
  7. package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Address.js.map +3 -3
  8. package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/index.js +1 -1
  9. package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/index.js.map +3 -3
  10. package/dist/cjs/components/memberPopup/MemberPopup.d.ts +1 -1
  11. package/dist/cjs/components/memberPopup/MemberPopup.js +1 -1
  12. package/dist/cjs/components/memberPopup/MemberPopup.js.map +3 -3
  13. package/dist/cjs/components/memberPopup/context/provider.d.ts +3 -3
  14. package/dist/cjs/components/memberPopup/context/provider.js +1 -1
  15. package/dist/cjs/components/memberPopup/context/provider.js.map +3 -3
  16. package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.d.ts +1 -4
  17. package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.js +1 -1
  18. package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.js.map +3 -3
  19. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.d.ts +8 -7
  20. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js +1 -1
  21. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js.map +3 -3
  22. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/index.d.ts +1 -2
  23. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/index.js +1 -1
  24. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/index.js.map +3 -3
  25. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivatePanel.d.ts +1 -2
  26. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivatePanel.js +1 -1
  27. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivatePanel.js.map +3 -3
  28. package/dist/cjs/components/memberPopup/panels/EarnCredits/CompleteProfilePanel.d.ts +1 -3
  29. package/dist/cjs/components/memberPopup/panels/EarnCredits/CompleteProfilePanel.js +1 -1
  30. package/dist/cjs/components/memberPopup/panels/EarnCredits/CompleteProfilePanel.js.map +3 -3
  31. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeEmailPanel.d.ts +1 -2
  32. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeEmailPanel.js +1 -1
  33. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeEmailPanel.js.map +3 -3
  34. package/dist/cjs/components/memberPopup/panels/EarnCredits/index.d.ts +1 -8
  35. package/dist/cjs/components/memberPopup/panels/EarnCredits/index.js +1 -1
  36. package/dist/cjs/components/memberPopup/panels/EarnCredits/index.js.map +3 -3
  37. package/dist/cjs/components/memberPopup/panels/Referral/index.js +1 -1
  38. package/dist/cjs/components/memberPopup/panels/Referral/index.js.map +3 -3
  39. package/dist/cjs/components/memberPopup/type.d.ts +19 -2
  40. package/dist/cjs/components/memberPopup/type.js +1 -1
  41. package/dist/cjs/components/memberPopup/type.js.map +1 -1
  42. package/dist/cjs/templates/Credits.js +1 -1
  43. package/dist/cjs/templates/Credits.js.map +3 -3
  44. package/dist/esm/components/LiveChatWidget/components/MessageContent/TextBlock.js +1 -1
  45. package/dist/esm/components/LiveChatWidget/components/MessageContent/TextBlock.js.map +3 -3
  46. package/dist/esm/components/credits/context/hooks/useShippingCountries.d.ts +8 -0
  47. package/dist/esm/components/credits/context/hooks/useShippingCountries.js +2 -0
  48. package/dist/esm/components/credits/context/hooks/useShippingCountries.js.map +7 -0
  49. package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Address.js +1 -1
  50. package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Address.js.map +3 -3
  51. package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/index.js +1 -1
  52. package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/index.js.map +3 -3
  53. package/dist/esm/components/memberPopup/MemberPopup.d.ts +1 -1
  54. package/dist/esm/components/memberPopup/MemberPopup.js +1 -1
  55. package/dist/esm/components/memberPopup/MemberPopup.js.map +3 -3
  56. package/dist/esm/components/memberPopup/context/provider.d.ts +3 -3
  57. package/dist/esm/components/memberPopup/context/provider.js +1 -1
  58. package/dist/esm/components/memberPopup/context/provider.js.map +3 -3
  59. package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.d.ts +1 -4
  60. package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.js +1 -1
  61. package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.js.map +3 -3
  62. package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.d.ts +8 -7
  63. package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js +1 -1
  64. package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js.map +3 -3
  65. package/dist/esm/components/memberPopup/panels/ConsumeCredits/index.d.ts +1 -2
  66. package/dist/esm/components/memberPopup/panels/ConsumeCredits/index.js +1 -1
  67. package/dist/esm/components/memberPopup/panels/ConsumeCredits/index.js.map +3 -3
  68. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivatePanel.d.ts +1 -2
  69. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivatePanel.js +1 -1
  70. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivatePanel.js.map +3 -3
  71. package/dist/esm/components/memberPopup/panels/EarnCredits/CompleteProfilePanel.d.ts +1 -3
  72. package/dist/esm/components/memberPopup/panels/EarnCredits/CompleteProfilePanel.js +1 -1
  73. package/dist/esm/components/memberPopup/panels/EarnCredits/CompleteProfilePanel.js.map +3 -3
  74. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeEmailPanel.d.ts +1 -2
  75. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeEmailPanel.js +1 -1
  76. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeEmailPanel.js.map +3 -3
  77. package/dist/esm/components/memberPopup/panels/EarnCredits/index.d.ts +1 -8
  78. package/dist/esm/components/memberPopup/panels/EarnCredits/index.js +1 -1
  79. package/dist/esm/components/memberPopup/panels/EarnCredits/index.js.map +3 -3
  80. package/dist/esm/components/memberPopup/panels/Referral/index.js +1 -1
  81. package/dist/esm/components/memberPopup/panels/Referral/index.js.map +3 -3
  82. package/dist/esm/components/memberPopup/type.d.ts +19 -2
  83. package/dist/esm/components/memberPopup/type.js +1 -1
  84. package/dist/esm/components/memberPopup/type.js.map +1 -1
  85. package/dist/esm/templates/Credits.js +1 -1
  86. package/dist/esm/templates/Credits.js.map +3 -3
  87. package/package.json +2 -1
  88. package/src/components/LiveChatWidget/components/MessageContent/TextBlock.tsx +7 -5
  89. package/src/components/credits/context/hooks/useShippingCountries.ts +60 -0
  90. package/src/components/credits/creditsRedeemList/RedeemProductModal/Address.tsx +2 -2
  91. package/src/components/credits/creditsRedeemList/RedeemProductModal/index.tsx +2 -2
  92. package/src/components/memberPopup/MemberPopup.tsx +166 -178
  93. package/src/components/memberPopup/context/provider.tsx +24 -4
  94. package/src/components/memberPopup/panels/ActivitiesSubscribePanel.tsx +66 -73
  95. package/src/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.tsx +38 -55
  96. package/src/components/memberPopup/panels/ConsumeCredits/index.tsx +210 -105
  97. package/src/components/memberPopup/panels/EarnCredits/ActivatePanel.tsx +32 -16
  98. package/src/components/memberPopup/panels/EarnCredits/CompleteProfilePanel.tsx +60 -35
  99. package/src/components/memberPopup/panels/EarnCredits/SubscribeEmailPanel.tsx +32 -22
  100. package/src/components/memberPopup/panels/EarnCredits/index.tsx +56 -49
  101. package/src/components/memberPopup/panels/Referral/index.tsx +40 -22
  102. package/src/components/memberPopup/type.ts +20 -3
  103. package/src/templates/Credits.tsx +25 -0
  104. package/dist/cjs/components/memberPopup/panels/Activity/SubscribeModal.d.ts +0 -10
  105. package/dist/cjs/components/memberPopup/panels/Activity/SubscribeModal.js +0 -2
  106. package/dist/cjs/components/memberPopup/panels/Activity/SubscribeModal.js.map +0 -7
  107. package/dist/cjs/components/memberPopup/panels/Activity/hooks/useActivitySubscribe.d.ts +0 -7
  108. package/dist/cjs/components/memberPopup/panels/Activity/hooks/useActivitySubscribe.js +0 -2
  109. package/dist/cjs/components/memberPopup/panels/Activity/hooks/useActivitySubscribe.js.map +0 -7
  110. package/dist/cjs/components/memberPopup/panels/Activity/index.d.ts +0 -7
  111. package/dist/cjs/components/memberPopup/panels/Activity/index.js +0 -2
  112. package/dist/cjs/components/memberPopup/panels/Activity/index.js.map +0 -7
  113. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponModal.d.ts +0 -19
  114. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponModal.js +0 -2
  115. package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponModal.js.map +0 -7
  116. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.d.ts +0 -11
  117. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js +0 -2
  118. package/dist/cjs/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js.map +0 -7
  119. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeModal.d.ts +0 -10
  120. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeModal.js +0 -2
  121. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribeModal.js.map +0 -7
  122. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribePanel.d.ts +0 -9
  123. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribePanel.js +0 -2
  124. package/dist/cjs/components/memberPopup/panels/EarnCredits/SubscribePanel.js.map +0 -7
  125. package/dist/cjs/components/memberPopup/panels/Referral/hooks/useReferralDashboard.d.ts +0 -13
  126. package/dist/cjs/components/memberPopup/panels/Referral/hooks/useReferralDashboard.js +0 -2
  127. package/dist/cjs/components/memberPopup/panels/Referral/hooks/useReferralDashboard.js.map +0 -7
  128. package/dist/esm/components/memberPopup/panels/Activity/SubscribeModal.d.ts +0 -10
  129. package/dist/esm/components/memberPopup/panels/Activity/SubscribeModal.js +0 -2
  130. package/dist/esm/components/memberPopup/panels/Activity/SubscribeModal.js.map +0 -7
  131. package/dist/esm/components/memberPopup/panels/Activity/hooks/useActivitySubscribe.d.ts +0 -7
  132. package/dist/esm/components/memberPopup/panels/Activity/hooks/useActivitySubscribe.js +0 -2
  133. package/dist/esm/components/memberPopup/panels/Activity/hooks/useActivitySubscribe.js.map +0 -7
  134. package/dist/esm/components/memberPopup/panels/Activity/index.d.ts +0 -7
  135. package/dist/esm/components/memberPopup/panels/Activity/index.js +0 -2
  136. package/dist/esm/components/memberPopup/panels/Activity/index.js.map +0 -7
  137. package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponModal.d.ts +0 -19
  138. package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponModal.js +0 -2
  139. package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponModal.js.map +0 -7
  140. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.d.ts +0 -11
  141. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js +0 -2
  142. package/dist/esm/components/memberPopup/panels/EarnCredits/ActivitiesSubscribePanel.js.map +0 -7
  143. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeModal.d.ts +0 -10
  144. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeModal.js +0 -2
  145. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribeModal.js.map +0 -7
  146. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribePanel.d.ts +0 -9
  147. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribePanel.js +0 -2
  148. package/dist/esm/components/memberPopup/panels/EarnCredits/SubscribePanel.js.map +0 -7
  149. package/dist/esm/components/memberPopup/panels/Referral/hooks/useReferralDashboard.d.ts +0 -13
  150. package/dist/esm/components/memberPopup/panels/Referral/hooks/useReferralDashboard.js +0 -2
  151. package/dist/esm/components/memberPopup/panels/Referral/hooks/useReferralDashboard.js.map +0 -7
  152. package/dist/index.d.mts +0 -1775
  153. package/dist/index.d.ts +0 -1775
  154. package/dist/index.js +0 -18542
  155. package/dist/index.js.map +0 -1
  156. package/dist/index.mjs +0 -18514
  157. package/dist/index.mjs.map +0 -1
  158. package/src/components/memberPopup/panels/EarnCredits/CompleteProfileModal.tsx +0 -191
@@ -1,6 +1,6 @@
1
- import { useMemo, useState } from 'react'
1
+ import { useEffect, useMemo, useState } from 'react'
2
2
  import { Picture, Button } from '@anker-in/headless-ui'
3
- import { classNames as cn, useProductsByHandles, useHeadlessContext } from '@anker-in/lib'
3
+ import { gaTrack, classNames as cn, useProductsByHandles, useHeadlessContext } from '@anker-in/lib'
4
4
  import { useMemberPopupContext } from '../../context/provider'
5
5
  import { useViewStack } from '../../context/viewStack'
6
6
  import { useRedeemableList } from './hooks/useRedeemableList'
@@ -19,17 +19,18 @@ type EnrichedItem = ConsumeCreditsItem & {
19
19
  alpcData: ConsumeCreditRuleResponse
20
20
  insufficient: boolean
21
21
  soldOut: boolean
22
+ disabled: boolean
22
23
  product?: any
23
24
  variant?: any
24
25
  }
25
26
 
26
27
  type Props = {
27
28
  copy: ConsumeCreditsopy
28
- onClose: () => void
29
29
  }
30
30
 
31
- function ConsumeCredits({ copy, onClose }: Props) {
32
- const { profile, creditInfo, openSignUpPopup, alpcConfig } = useMemberPopupContext()
31
+ function ConsumeCredits({ copy }: Props) {
32
+ const { profile, creditInfo, openSignUpPopup, alpcConfig, isActivateSuccess, fetchCreditInfo, pageHandle } =
33
+ useMemberPopupContext()
33
34
  const { pushView } = useViewStack()
34
35
  const { brand } = useHeadlessContext()
35
36
  const rounded = ROUNDED_BRANDS.includes(brand)
@@ -37,6 +38,10 @@ function ConsumeCredits({ copy, onClose }: Props) {
37
38
  const [redeemAndBuyError, setRedeemAndBuyError] = useState('')
38
39
  const [loadingId, setLoadingId] = useState<string | number | null>(null)
39
40
 
41
+ useEffect(() => {
42
+ if (profile?.user_id) fetchCreditInfo(profile.user_id)
43
+ }, [])
44
+
40
45
  const isLogin = !!profile
41
46
  const { redeemableList, listLoading } = useRedeemableList(alpcConfig)
42
47
  const { trigger: redeemAndBuy } = useRedeemAndBuy(alpcConfig)
@@ -51,40 +56,53 @@ function ConsumeCredits({ copy, onClose }: Props) {
51
56
  if (!alpcData) return null
52
57
 
53
58
  const availableCredit = Number(creditInfo?.available_credit ?? 0)
54
- const insufficient = isLogin && !!profile?.activated && alpcData.consume_credits > availableCredit
55
- const soldOut = alpcData.is_limited && (!alpcData.remaining_inventory || alpcData.remaining_inventory <= 0)
56
-
57
- let product
58
- let variant
59
- if (
60
- (item.type === ConsumeCreditsItemType.RedeemAndBuy ||
61
- item.type === ConsumeCreditsItemType.Product) &&
62
- item.product
63
- ) {
64
- product = products?.find((p: any) => p.handle === item.product!.handle)
65
- variant = product?.variants?.find((v: any) => v.sku === item.product!.sku) ?? product?.variants?.[0]
66
- if (item.type === ConsumeCreditsItemType.RedeemAndBuy && (!product || !variant)) return null
67
- }
59
+ const insufficient = alpcData.consume_credits > availableCredit
60
+ const alpcSoldOut = alpcData.is_limited && (!alpcData.remaining_inventory || alpcData.remaining_inventory <= 0)
68
61
 
69
- return { ...item, alpcData, insufficient, soldOut, product, variant }
62
+ const isPhysicalProduct =
63
+ item.type === ConsumeCreditsItemType.RedeemAndBuy || item.type === ConsumeCreditsItemType.Product
64
+ const product = products?.find((p: any) => p.handle === item.product?.handle)
65
+ const variant = product?.variants?.find((v: any) => v.sku === item.product?.sku) ?? product?.variants?.[0]
66
+ if (isPhysicalProduct && (!product || !variant || !variant?.availableForSale || alpcSoldOut)) {
67
+ return null
68
+ }
69
+ if (item.type === ConsumeCreditsItemType.RedeemAndBuy && item.price == null) {
70
+ return null
71
+ }
72
+ return { ...item, alpcData, insufficient, product, variant }
70
73
  })
71
74
  .filter(Boolean) as EnrichedItem[]
72
75
  }, [copy.list, redeemableList, creditInfo, profile, isLogin, products])
73
76
 
77
+ const isActivate = profile?.activated || isActivateSuccess
78
+
74
79
  function getButtonLabel(item: (typeof list)[number]) {
75
- if (!isLogin) return copy.unlockRewards
76
- if (item.soldOut) return copy.soldOut
80
+ if (!isLogin || !isActivate) {
81
+ return copy.unlockRewards
82
+ }
83
+ if (item.soldOut) {
84
+ return copy.soldOut
85
+ }
77
86
  return copy.btnRedeem
78
87
  }
79
88
 
80
89
  function isDisabled(item: (typeof list)[number]) {
81
- if (
82
- item.type === ConsumeCreditsItemType.GiftCard ||
83
- item.type === ConsumeCreditsItemType.Product
84
- ) {
85
- return item.insufficient
90
+ if (!isLogin || !isActivate) {
91
+ return false
86
92
  }
87
- return item.soldOut || item.insufficient
93
+ return item.insufficient
94
+ }
95
+
96
+ function trackRedeemButton(itemTitle: string) {
97
+ gaTrack({
98
+ event: 'ga4Event',
99
+ event_name: 'lp_button',
100
+ event_parameters: {
101
+ position: 'consume_credits',
102
+ button_name: 'redeem',
103
+ info: 'Member Floating Window',
104
+ },
105
+ })
88
106
  }
89
107
 
90
108
  async function handleRedeem(item: (typeof list)[number]) {
@@ -92,20 +110,28 @@ function ConsumeCredits({ copy, onClose }: Props) {
92
110
  openSignUpPopup()
93
111
  return
94
112
  }
95
- if (!profile?.activated) {
96
- pushView({ type: MemberPopupPanelType.Activate })
113
+ if (!isActivate) {
114
+ pushView({
115
+ type: MemberPopupPanelType.Activate,
116
+ })
97
117
  return
98
118
  }
99
- if (
100
- item.type === ConsumeCreditsItemType.GiftCard ||
101
- item.type === ConsumeCreditsItemType.Product
102
- ) {
119
+ if (item.type === ConsumeCreditsItemType.GiftCard || item.type === ConsumeCreditsItemType.Product) {
103
120
  if (copy.creditsPage?.url) {
104
- window.open(copy.creditsPage.url, '_blank', 'noopener,noreferrer')
121
+ const sectionId = copy.creditsPage.redeemListSectionId ?? 'creditsRedeemList'
122
+ const targetUrl = new URL(copy.creditsPage.url, window.location.href)
123
+ targetUrl.searchParams.set('section', sectionId)
124
+ targetUrl.hash = sectionId
125
+ if (pageHandle) {
126
+ targetUrl.searchParams.set('ref', `${pageHandle}_consume_credits`)
127
+ }
128
+ trackRedeemButton(item.title)
129
+ window.open(targetUrl.toString(), '_blank', 'noopener,noreferrer')
105
130
  }
106
131
  return
107
132
  }
108
133
  if (item.type === ConsumeCreditsItemType.Coupon) {
134
+ trackRedeemButton(item.title)
109
135
  pushView({
110
136
  type: MemberPopupPanelType.RedeemCoupon,
111
137
  props: {
@@ -115,7 +141,6 @@ function ConsumeCredits({ copy, onClose }: Props) {
115
141
  ? { url: copy.imageMapping[item.type]!.url, alt: item.image?.alt }
116
142
  : item.image,
117
143
  itemValue: item.value,
118
- itemOff: copy.off,
119
144
  itemRules: item.rules,
120
145
  redeemId: Number(item.redeemId),
121
146
  userId: profile?.user_id,
@@ -125,12 +150,22 @@ function ConsumeCredits({ copy, onClose }: Props) {
125
150
  } else {
126
151
  setRedeemAndBuyError('')
127
152
  setLoadingId(item.redeemId)
153
+ trackRedeemButton(item.title)
128
154
  try {
129
155
  await redeemAndBuy({
130
156
  productVariant: item.variant,
131
157
  redeemId: Number(item.redeemId),
132
158
  userId: profile?.user_id,
133
159
  })
160
+ gaTrack({
161
+ event: 'ga4Event',
162
+ event_name: 'lp_button',
163
+ event_parameters: {
164
+ position: 'consume_credits',
165
+ button_name: 'redeem_success',
166
+ info: 'Member Floating Window',
167
+ },
168
+ })
134
169
  } catch (e: any) {
135
170
  setRedeemAndBuyError(e?.message ?? copy.redeemModal.commonError)
136
171
  } finally {
@@ -141,99 +176,169 @@ function ConsumeCredits({ copy, onClose }: Props) {
141
176
 
142
177
  return (
143
178
  <>
144
- <div className="flex flex-1 flex-col gap-[12px]">
179
+ <div className="flex flex-1 flex-col">
145
180
  <div className="flex flex-col gap-[8px]">
146
181
  {copy.title && <h2 className="text-[24px] font-[700] leading-[1.2] text-[#080a0f]">{copy.title}</h2>}
147
- {copy.subtitle && <p className="text-[16px] font-[700] leading-snug text-[#4a4c56]">{copy.subtitle}</p>}
182
+ {copy.subtitle && (
183
+ <p className="text-[16px] mt-[8px] font-[700] leading-snug text-[#4a4c56]">{copy.subtitle}</p>
184
+ )}
148
185
  </div>
149
186
 
150
- {copy.insufficientCredits && creditInfo && (
151
- <div className="text-[14px] font-[700] text-[#1d1d1f]">
152
- {copy.insufficientCredits}: {numberFormat(creditInfo.available_credit)} {copy.pointUnit}
187
+ {isLogin && (
188
+ <div
189
+ className={cn(
190
+ 'flex items-center mt-[16px] gap-[12px] bg-[#f5f6f7] p-[16px]',
191
+ rounded ? 'rounded-[8px]' : 'rounded-none'
192
+ )}
193
+ >
194
+ <div className="flex flex-1 flex-col gap-[4px]">
195
+ <div className="text-[14px] font-[700] text-[#1e2024]">{copy.balanceLabel ?? 'AnkerCredits Balance'}</div>
196
+ <div className="flex items-end gap-[4px]">
197
+ <span className="text-[24px] font-[700] leading-[1.2] text-[#1e2024]">
198
+ {numberFormat(creditInfo?.available_credit || 0)}
199
+ </span>
200
+ <span className="text-[14px] font-[700] leading-[1.4] text-[#1e2024]">
201
+ {copy.creditUnit ?? 'ankercredits'}
202
+ </span>
203
+ </div>
204
+ </div>
205
+ <div className="h-full w-px bg-[#dadce0]" />
206
+ <div className="flex flex-1 flex-col gap-[4px]">
207
+ <div className="text-[14px] font-[700] text-[#1e2024]">{copy.comingSoonLabel ?? 'Coming Soon'}</div>
208
+ <div className="flex items-end gap-[4px]">
209
+ <span className="text-[24px] font-[700] leading-[1.2] text-[#1e2024]">
210
+ {numberFormat(creditInfo?.pending_credit || 0)}
211
+ </span>
212
+ <span className="text-[14px] font-[700] leading-[1.4] text-[#1e2024]">
213
+ {copy.creditUnit ?? 'ankercredits'}
214
+ </span>
215
+ </div>
216
+ </div>
153
217
  </div>
154
218
  )}
155
- {redeemAndBuyError && <div className="text-[14px] font-[700] text-[#f84d4f]">{redeemAndBuyError}</div>}
219
+ {redeemAndBuyError && <div className="text-[14px] mt-[8px] font-[700] text-[#f84d4f]">{redeemAndBuyError}</div>}
156
220
 
157
221
  {listLoading ? (
158
222
  <div className="flex flex-1 items-center justify-center py-[32px]">
159
223
  <div className="size-[32px] animate-spin rounded-full border-[3px] border-[#080a0f] border-t-transparent" />
160
224
  </div>
161
225
  ) : (
162
- <div className="flex flex-col">
163
- {list.map((item, idx) => {
164
- const hasProduct = !!item.product
165
- return (
166
- <div key={idx} className="relative py-[16px]">
167
- {idx > 0 && <div className="absolute inset-x-0 top-0 h-px bg-[#dadce0]" />}
168
- <div className="flex items-center gap-[12px]">
169
- {(() => {
170
- const mappedImgUrl = copy.imageMapping?.[item.type]?.url
171
- const imgUrl = hasProduct
172
- ? (item.variant?.image?.url ?? item.product?.images?.[0]?.url ?? item.image?.url)
173
- : (mappedImgUrl ?? item.image?.url)
174
- const imgAlt = hasProduct
175
- ? (item.variant?.image?.altText ?? item.product?.images?.[0]?.alt ?? item.image?.alt ?? '')
176
- : (item.image?.alt ?? '')
177
- if (!imgUrl) return null
178
- return (
179
- <div className={cn('relative size-[64px] shrink-0 overflow-hidden', rounded ? 'rounded-[4px]' : 'rounded-none')}>
180
- <Picture
181
- source={imgUrl}
182
- alt={imgAlt}
183
- className="flex size-full items-center justify-center"
184
- imgClassName={hasProduct ? 'object-cover' : 'h-full w-auto object-contain'}
185
- />
186
- {!hasProduct && item.value && (
187
- <div className="absolute bottom-[16px] left-[4px] text-[12px] font-[800] leading-none text-white">
188
- {item.value} {copy.off}
226
+ <div className="flex mt-[16px] flex-col">
227
+ {list.map((item, idx) => {
228
+ return (
229
+ <div key={idx} className="relative py-[16px]">
230
+ {idx > 0 && <div className="absolute inset-x-0 top-0 h-px bg-[#dadce0]" />}
231
+ <div className="flex items-center gap-[12px]">
232
+ {(() => {
233
+ const phsicalProduct =
234
+ item.type === ConsumeCreditsItemType.Product ||
235
+ item.type === ConsumeCreditsItemType.RedeemAndBuy
236
+ const imgUrl = phsicalProduct
237
+ ? (item.variant?.image?.url ?? item.product?.images?.[0]?.url ?? item.image?.url)
238
+ : item.image?.url || copy.imageMapping?.[item.type]?.url
239
+ const imgAlt = phsicalProduct
240
+ ? (item.variant?.image?.altText ?? item.product?.images?.[0]?.alt ?? item.image?.alt ?? '')
241
+ : (item.image?.alt ?? '')
242
+ if (!imgUrl) return null
243
+ return (
244
+ <div
245
+ className={cn(
246
+ 'relative size-[64px] shrink-0 overflow-hidden',
247
+ rounded ? 'rounded-[4px]' : 'rounded-none'
248
+ )}
249
+ >
250
+ <Picture
251
+ source={imgUrl}
252
+ alt={imgAlt}
253
+ className="flex size-full items-center justify-center"
254
+ imgClassName={phsicalProduct ? 'object-cover' : 'h-full w-auto object-contain'}
255
+ />
256
+ {item.type === ConsumeCreditsItemType.Coupon && item.value && (
257
+ <div className="absolute bottom-[16px] left-[4px] text-[12px] font-[800] leading-none text-white">
258
+ {item.value && `${item.value} ${copy.off}`}
259
+ </div>
260
+ )}
261
+ {item.type === ConsumeCreditsItemType.GiftCard && item.value && (
262
+ <div className="absolute bottom-[16px] left-[4px] text-[12px] font-[800] leading-none text-white">
263
+ {item.value && `${item.value} ${copy.giftCard || 'Gift Card'}`}
264
+ </div>
265
+ )}
266
+ </div>
267
+ )
268
+ })()}
269
+ <div className="min-w-0 flex-1">
270
+ <div className="text-[16px] font-[700] text-[#1e2024] line-clamp-2">
271
+ {item.product?.title ?? item.title ?? item.alpcData?.name}
272
+ </div>
273
+ <div className="mt-[4px] text-[14px] text-[#666]">
274
+ {item.type === ConsumeCreditsItemType.RedeemAndBuy ? (
275
+ <div>
276
+ <span>
277
+ {numberFormat(item.alpcData.consume_credits)} {copy.creditUnit ?? ''} + $
278
+ {Number(item.price).toFixed(2)}
279
+ </span>
280
+ {item.variant?.price?.amount && (
281
+ <span className="text-[12px] ml-1 text-[#999] line-through">
282
+ ${Number(item.variant.price.amount).toFixed(2)}
283
+ </span>
284
+ )}
285
+ </div>
286
+ ) : (
287
+ `${numberFormat(item.alpcData.consume_credits)} ${copy.creditUnit ?? ''}`
288
+ )}
289
+ </div>
290
+ </div>
291
+ <div className="relative group">
292
+ <Button
293
+ size="base"
294
+ disabled={isDisabled(item)}
295
+ loading={loadingId === item.redeemId}
296
+ onClick={() => handleRedeem(item)}
297
+ >
298
+ {getButtonLabel(item)}
299
+ </Button>
300
+ {item.insufficient && isLogin && isActivate && (
301
+ <div className="pointer-events-none absolute right-0 top-full z-[100] mt-[10px] hidden w-[200px] group-hover:block">
302
+ <div className="relative bg-[#6D6D6F] p-[16px] text-[14px] font-[700] text-white shadow">
303
+ <p className="text-pretty tracking-[-0.02em] text-[14px]">{copy.insufficientCredits}</p>
304
+ <div className="absolute -top-[8px] right-[20px] size-[16px] origin-top-left rotate-45 rounded-[2px] bg-[#6D6D6F]" />
305
+ </div>
189
306
  </div>
190
307
  )}
191
308
  </div>
192
- )
193
- })()}
194
- <div className="min-w-0 flex-1">
195
- <div className="text-[16px] font-[700] text-[#1e2024] line-clamp-2">
196
- {hasProduct && item.product?.title
197
- ? item.product.title
198
- : item.title}
199
- </div>
200
- <div className="mt-[4px] text-[14px] text-[#666]">
201
- {hasProduct && item.price != null
202
- ? `${numberFormat(item.alpcData.consume_credits)} ${copy.pointUnit ?? ''} + $${Number(item.price).toFixed(2)}`
203
- : `${numberFormat(item.alpcData.consume_credits)} ${copy.pointUnit ?? ''}`}
204
309
  </div>
205
310
  </div>
206
- <div className="relative group">
207
- <Button
208
- className={cn('bg-[#080a0f] px-[20px] pb-[10px] pt-[11px] text-[14px] font-[700] leading-[1.2] text-white', rounded ? 'rounded-[4px]' : 'rounded-none')}
209
- disabled={isDisabled(item)}
210
- loading={loadingId === item.redeemId}
211
- onClick={() => handleRedeem(item)}
212
- >
213
- {getButtonLabel(item)}
214
- </Button>
215
- {item.insufficient && (
216
- <div className="pointer-events-none absolute right-0 top-full z-[100] mt-[10px] hidden w-[200px] group-hover:block">
217
- <div className="relative bg-[#6D6D6F] p-[16px] text-[14px] font-[700] text-white shadow">
218
- <p className="text-pretty tracking-[-0.02em] text-[14px]">{copy.insufficientCredits}</p>
219
- <div className="absolute -top-[8px] right-[20px] size-[16px] origin-top-left rotate-45 rounded-[2px] bg-[#6D6D6F]" />
220
- </div>
221
- </div>
222
- )}
223
- </div>
224
- </div>
225
- </div>
226
- )
227
- })}
228
- </div>
311
+ )
312
+ })}
313
+ </div>
229
314
  )}
230
315
 
231
316
  {copy.creditsPage?.url && (
232
317
  <a
233
- href={copy.creditsPage.url}
318
+ href={(() => {
319
+ if (!pageHandle) return copy.creditsPage!.url
320
+ try {
321
+ const url = new URL(copy.creditsPage!.url, window.location.href)
322
+ url.searchParams.set('ref', `${pageHandle}_consume_credits`)
323
+ return url.toString()
324
+ } catch {
325
+ return copy.creditsPage!.url
326
+ }
327
+ })()}
234
328
  target="_blank"
235
329
  rel="noopener noreferrer"
236
330
  className="mt-auto self-start text-[14px] font-[700] text-[#080a0f] underline"
331
+ onClick={() =>
332
+ gaTrack({
333
+ event: 'ga4Event',
334
+ event_name: 'lp_button',
335
+ event_parameters: {
336
+ position: 'consume_credits',
337
+ button_name: 'credits_page_link',
338
+ info: 'Member Floating Window',
339
+ },
340
+ })
341
+ }
237
342
  >
238
343
  {copy.creditsPage.label ?? 'Go to Credits Page'}
239
344
  </a>
@@ -11,15 +11,16 @@ import {
11
11
  import { Message } from '../../../registration/authCodeActivate/Message'
12
12
  import type { AuthCodeActivateCopy } from '../../type'
13
13
  import { useRegistration } from '../../../registration'
14
+ import { useMemberPopupContext } from '../../context/provider'
14
15
  import { ROUNDED_BRANDS } from '../../../../constants'
15
16
 
16
17
  type Props = {
17
18
  copy: AuthCodeActivateCopy
18
19
  onClose: () => void
19
- onSuccess?: () => void
20
20
  }
21
21
 
22
- export default function ActivatePanel({ copy, onClose, onSuccess }: Props) {
22
+ export default function ActivatePanel({ copy, onClose }: Props) {
23
+ const { setIsActivateSuccess, fetchCreditInfo, profile } = useMemberPopupContext()
23
24
  const { locale, brand } = useHeadlessContext()
24
25
  const { email } = useRegistration()
25
26
  const rounded = ROUNDED_BRANDS.includes(brand)
@@ -165,14 +166,36 @@ export default function ActivatePanel({ copy, onClose, onSuccess }: Props) {
165
166
  if (data.status >= 200 && data.status < 300) {
166
167
  setMessageStatus('success')
167
168
  setMessageText(copy?.authSuccessMessage || '')
168
- onSuccess?.()
169
+ setIsActivateSuccess(true)
170
+ if (profile?.user_id) setTimeout(() => fetchCreditInfo(profile.user_id), 3000)
171
+ gaTrack({
172
+ event: 'ga4Event',
173
+ event_name: 'lp_button',
174
+ event_parameters: {
175
+ page_group: 'reg_sub_pop',
176
+ position: 'auth_code',
177
+ button_name: 'check_and_active',
178
+ info: 'Member Floating Window',
179
+ },
180
+ })
169
181
  setTimeout(() => {
170
182
  onClose()
171
183
  }, 3000)
172
184
  } else {
173
185
  const errorCode = data?.data?.error_code ?? data?.error_code
174
186
  if (errorCode === '104') {
175
- onSuccess?.()
187
+ setIsActivateSuccess(true)
188
+ if (profile?.user_id) setTimeout(() => fetchCreditInfo(profile.user_id), 3000)
189
+ gaTrack({
190
+ event: 'ga4Event',
191
+ event_name: 'lp_button',
192
+ event_parameters: {
193
+ page_group: 'reg_sub_pop',
194
+ position: 'auth_code',
195
+ button_name: 'check_and_active',
196
+ info: 'Member Floating Window',
197
+ },
198
+ })
176
199
  setTimeout(() => {
177
200
  onClose()
178
201
  }, 3000)
@@ -194,16 +217,6 @@ export default function ActivatePanel({ copy, onClose, onSuccess }: Props) {
194
217
  setMessageText('')
195
218
  clearTimeout(timer)
196
219
  }, 5000)
197
-
198
- gaTrack({
199
- event: 'ga4Event',
200
- event_name: 'lp_button',
201
- event_parameters: {
202
- page_group: 'reg_sub_pop',
203
- position: 'auth_code',
204
- button_name: 'check_and_active',
205
- },
206
- })
207
220
  }, [
208
221
  code,
209
222
  copy?.codeEmptyError,
@@ -215,7 +228,9 @@ export default function ActivatePanel({ copy, onClose, onSuccess }: Props) {
215
228
  sendEmailData,
216
229
  triggerEmailValidation,
217
230
  onClose,
218
- onSuccess,
231
+ setIsActivateSuccess,
232
+ fetchCreditInfo,
233
+ profile,
219
234
  ])
220
235
 
221
236
  return (
@@ -311,7 +326,8 @@ export default function ActivatePanel({ copy, onClose, onSuccess }: Props) {
311
326
  <Button
312
327
  type="submit"
313
328
  loading={emailValidationLoading}
314
- className="mt-6 flex h-[54px] w-full cursor-pointer items-center justify-center px-8 py-[15px] text-center text-base font-bold leading-[100%] text-white min-l:mt-8"
329
+ className="mt-6 w-full min-l:mt-8"
330
+ size="base"
315
331
  onClick={handleAuthCodeSubmit}
316
332
  >
317
333
  {copy.buttonText}