@anker-in/campaign-ui 0.2.11-beta.3 → 0.2.11-beta.4

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 (193) hide show
  1. package/dist/cjs/components/credits/context/hooks/useFunctionMemberPrice.d.ts +2 -2
  2. package/dist/cjs/components/credits/context/hooks/useFunctionMemberPrice.js +1 -1
  3. package/dist/cjs/components/credits/context/hooks/useFunctionMemberPrice.js.map +2 -2
  4. package/dist/cjs/components/credits/context/memberPriceConst.d.ts +0 -5
  5. package/dist/cjs/components/credits/context/memberPriceConst.js +1 -1
  6. package/dist/cjs/components/credits/context/memberPriceConst.js.map +3 -3
  7. package/dist/cjs/components/credits/context/memberPriceTypes.d.ts +1 -22
  8. package/dist/cjs/components/credits/context/memberPriceTypes.js +1 -1
  9. package/dist/cjs/components/credits/context/memberPriceTypes.js.map +1 -1
  10. package/dist/cjs/components/credits/context/provider.d.ts +15 -1
  11. package/dist/cjs/components/credits/context/provider.js +1 -1
  12. package/dist/cjs/components/credits/context/provider.js.map +3 -3
  13. package/dist/cjs/components/credits/context/utils/getFunctionMemberPrice.d.ts +2 -2
  14. package/dist/cjs/components/credits/context/utils/getFunctionMemberPrice.js +1 -1
  15. package/dist/cjs/components/credits/context/utils/getFunctionMemberPrice.js.map +1 -1
  16. package/dist/cjs/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.d.ts +2 -2
  17. package/dist/cjs/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js +1 -1
  18. package/dist/cjs/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js.map +1 -1
  19. package/dist/cjs/components/credits/context/utils/variantGetCoupon.d.ts +2 -2
  20. package/dist/cjs/components/credits/context/utils/variantGetCoupon.js +1 -1
  21. package/dist/cjs/components/credits/context/utils/variantGetCoupon.js.map +1 -1
  22. package/dist/cjs/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
  23. package/dist/cjs/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +3 -3
  24. package/dist/cjs/components/credits/creditsBanner/index.d.ts +2 -0
  25. package/dist/cjs/components/credits/creditsBanner/index.js +12 -1
  26. package/dist/cjs/components/credits/creditsBanner/index.js.map +3 -3
  27. package/dist/cjs/components/credits/creditsBenefits/BenefitItem.js +2 -0
  28. package/dist/cjs/components/credits/creditsBenefits/BenefitItem.js.map +7 -0
  29. package/dist/cjs/components/credits/creditsBenefits/{iconInfo.js → IconInfo.js} +1 -1
  30. package/dist/cjs/components/credits/creditsBenefits/{iconInfo.js.map → IconInfo.js.map} +1 -1
  31. package/dist/cjs/components/credits/creditsCash/CreditsCash.js +1 -1
  32. package/dist/cjs/components/credits/creditsCash/CreditsCash.js.map +2 -2
  33. package/dist/cjs/components/credits/creditsCash/RedeemableItem.js +1 -1
  34. package/dist/cjs/components/credits/creditsCash/RedeemableItem.js.map +2 -2
  35. package/dist/cjs/components/credits/creditsCash/type.d.ts +1 -0
  36. package/dist/cjs/components/credits/creditsCash/type.js +1 -1
  37. package/dist/cjs/components/credits/creditsCash/type.js.map +1 -1
  38. package/dist/cjs/components/credits/creditsFaq/faqItem/FaqItem.js +1 -1
  39. package/dist/cjs/components/credits/creditsFaq/faqItem/FaqItem.js.map +3 -3
  40. package/dist/cjs/components/credits/creditsInfoCard/index.js +1 -1
  41. package/dist/cjs/components/credits/creditsInfoCard/index.js.map +2 -2
  42. package/dist/cjs/components/credits/creditsMemberPrice/CreditsMemberPrice.js +1 -1
  43. package/dist/cjs/components/credits/creditsMemberPrice/CreditsMemberPrice.js.map +3 -3
  44. package/dist/cjs/components/credits/creditsMemberPrice/MemberPriceItem.js +1 -1
  45. package/dist/cjs/components/credits/creditsMemberPrice/MemberPriceItem.js.map +3 -3
  46. package/dist/cjs/components/credits/creditsMemberPrice/type.d.ts +3 -5
  47. package/dist/cjs/components/credits/creditsMemberPrice/type.js +1 -1
  48. package/dist/cjs/components/credits/creditsMemberPrice/type.js.map +1 -1
  49. package/dist/cjs/components/credits/creditsNavigation/CreditsNavigation.js +1 -1
  50. package/dist/cjs/components/credits/creditsNavigation/CreditsNavigation.js.map +2 -2
  51. package/dist/cjs/components/credits/creditsRedeemList/CreditsRedeemList.js +1 -1
  52. package/dist/cjs/components/credits/creditsRedeemList/CreditsRedeemList.js.map +3 -3
  53. package/dist/cjs/components/credits/creditsRedeemList/RedeemableItem.js +1 -1
  54. package/dist/cjs/components/credits/creditsRedeemList/RedeemableItem.js.map +2 -2
  55. package/dist/cjs/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js +1 -1
  56. package/dist/cjs/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js.map +3 -3
  57. package/dist/cjs/templates/{credits.d.ts → Credits.d.ts} +15 -1
  58. package/dist/cjs/templates/Credits.js +2 -0
  59. package/dist/cjs/templates/Credits.js.map +7 -0
  60. package/dist/esm/components/credits/context/hooks/useFunctionMemberPrice.d.ts +2 -2
  61. package/dist/esm/components/credits/context/hooks/useFunctionMemberPrice.js +1 -1
  62. package/dist/esm/components/credits/context/hooks/useFunctionMemberPrice.js.map +2 -2
  63. package/dist/esm/components/credits/context/memberPriceConst.d.ts +0 -5
  64. package/dist/esm/components/credits/context/memberPriceConst.js +1 -1
  65. package/dist/esm/components/credits/context/memberPriceConst.js.map +3 -3
  66. package/dist/esm/components/credits/context/memberPriceTypes.d.ts +1 -22
  67. package/dist/esm/components/credits/context/provider.d.ts +15 -1
  68. package/dist/esm/components/credits/context/provider.js +1 -1
  69. package/dist/esm/components/credits/context/provider.js.map +3 -3
  70. package/dist/esm/components/credits/context/utils/getFunctionMemberPrice.d.ts +2 -2
  71. package/dist/esm/components/credits/context/utils/getFunctionMemberPrice.js +1 -1
  72. package/dist/esm/components/credits/context/utils/getFunctionMemberPrice.js.map +1 -1
  73. package/dist/esm/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.d.ts +2 -2
  74. package/dist/esm/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js +1 -1
  75. package/dist/esm/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.js.map +1 -1
  76. package/dist/esm/components/credits/context/utils/variantGetCoupon.d.ts +2 -2
  77. package/dist/esm/components/credits/context/utils/variantGetCoupon.js +1 -1
  78. package/dist/esm/components/credits/context/utils/variantGetCoupon.js.map +1 -1
  79. package/dist/esm/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
  80. package/dist/esm/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +3 -3
  81. package/dist/esm/components/credits/creditsBanner/index.d.ts +2 -0
  82. package/dist/esm/components/credits/creditsBanner/index.js +12 -1
  83. package/dist/esm/components/credits/creditsBanner/index.js.map +3 -3
  84. package/dist/esm/components/credits/creditsBenefits/BenefitItem.js +2 -0
  85. package/dist/esm/components/credits/creditsBenefits/BenefitItem.js.map +7 -0
  86. package/dist/esm/components/credits/creditsBenefits/{iconInfo.js → IconInfo.js} +1 -1
  87. package/dist/esm/components/credits/creditsBenefits/{iconInfo.js.map → IconInfo.js.map} +1 -1
  88. package/dist/esm/components/credits/creditsCash/CreditsCash.js +1 -1
  89. package/dist/esm/components/credits/creditsCash/CreditsCash.js.map +2 -2
  90. package/dist/esm/components/credits/creditsCash/RedeemableItem.js +1 -1
  91. package/dist/esm/components/credits/creditsCash/RedeemableItem.js.map +3 -3
  92. package/dist/esm/components/credits/creditsCash/type.d.ts +1 -0
  93. package/dist/esm/components/credits/creditsFaq/faqItem/FaqItem.js +1 -1
  94. package/dist/esm/components/credits/creditsFaq/faqItem/FaqItem.js.map +3 -3
  95. package/dist/esm/components/credits/creditsInfoCard/index.js +1 -1
  96. package/dist/esm/components/credits/creditsInfoCard/index.js.map +2 -2
  97. package/dist/esm/components/credits/creditsMemberPrice/CreditsMemberPrice.js +1 -1
  98. package/dist/esm/components/credits/creditsMemberPrice/CreditsMemberPrice.js.map +3 -3
  99. package/dist/esm/components/credits/creditsMemberPrice/MemberPriceItem.js +1 -1
  100. package/dist/esm/components/credits/creditsMemberPrice/MemberPriceItem.js.map +3 -3
  101. package/dist/esm/components/credits/creditsMemberPrice/type.d.ts +3 -5
  102. package/dist/esm/components/credits/creditsNavigation/CreditsNavigation.js +1 -1
  103. package/dist/esm/components/credits/creditsNavigation/CreditsNavigation.js.map +2 -2
  104. package/dist/esm/components/credits/creditsRedeemList/CreditsRedeemList.js +1 -1
  105. package/dist/esm/components/credits/creditsRedeemList/CreditsRedeemList.js.map +3 -3
  106. package/dist/esm/components/credits/creditsRedeemList/RedeemableItem.js +1 -1
  107. package/dist/esm/components/credits/creditsRedeemList/RedeemableItem.js.map +2 -2
  108. package/dist/esm/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js +1 -1
  109. package/dist/esm/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js.map +3 -3
  110. package/dist/esm/templates/{credits.d.ts → Credits.d.ts} +15 -1
  111. package/dist/esm/templates/Credits.js +2 -0
  112. package/dist/esm/templates/Credits.js.map +7 -0
  113. package/package.json +1 -1
  114. package/src/components/credits/context/memberPriceConst.ts +0 -7
  115. package/src/components/credits/context/memberPriceTypes.ts +1 -26
  116. package/src/components/credits/context/provider.tsx +14 -0
  117. package/src/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.tsx +25 -25
  118. package/src/components/credits/creditsBanner/index.tsx +31 -2
  119. package/src/components/credits/creditsBenefits/BenefitItem.tsx +11 -4
  120. package/src/components/credits/creditsBenefits/IconInfo.tsx +1 -1
  121. package/src/components/credits/creditsCash/CreditsCash.tsx +1 -1
  122. package/src/components/credits/creditsCash/RedeemableItem.tsx +17 -4
  123. package/src/components/credits/creditsCash/type.ts +1 -0
  124. package/src/components/credits/creditsFaq/faqItem/FaqItem.tsx +25 -23
  125. package/src/components/credits/creditsInfoCard/index.tsx +1 -1
  126. package/src/components/credits/creditsMemberPrice/CreditsMemberPrice.tsx +57 -5
  127. package/src/components/credits/creditsMemberPrice/MemberPriceItem.tsx +102 -25
  128. package/src/components/credits/creditsMemberPrice/type.ts +3 -5
  129. package/src/components/credits/creditsNavigation/CreditsNavigation.tsx +3 -3
  130. package/src/components/credits/creditsRedeemList/CreditsRedeemList.tsx +26 -13
  131. package/src/components/credits/creditsRedeemList/RedeemableItem.tsx +1 -1
  132. package/src/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.tsx +20 -17
  133. package/src/templates/Credits.tsx +26 -9
  134. package/dist/cjs/components/credits/context/hooks/useSendEmailValidation.d.ts +0 -1
  135. package/dist/cjs/components/credits/context/hooks/useSendEmailValidation.js +0 -2
  136. package/dist/cjs/components/credits/context/hooks/useSendEmailValidation.js.map +0 -7
  137. package/dist/cjs/components/credits/context/hooks/useSubscriptions.d.ts +0 -9
  138. package/dist/cjs/components/credits/context/hooks/useSubscriptions.js +0 -2
  139. package/dist/cjs/components/credits/context/hooks/useSubscriptions.js.map +0 -7
  140. package/dist/cjs/components/credits/creditsBenefits/benefitItem.js +0 -2
  141. package/dist/cjs/components/credits/creditsBenefits/benefitItem.js.map +0 -7
  142. package/dist/cjs/helpers/fetchResponse.d.ts +0 -14
  143. package/dist/cjs/helpers/fetchResponse.js +0 -2
  144. package/dist/cjs/helpers/fetchResponse.js.map +0 -7
  145. package/dist/cjs/helpers/fetcher.d.ts +0 -2
  146. package/dist/cjs/helpers/fetcher.js +0 -2
  147. package/dist/cjs/helpers/fetcher.js.map +0 -7
  148. package/dist/cjs/helpers/index.d.ts +0 -2
  149. package/dist/cjs/helpers/index.js +0 -2
  150. package/dist/cjs/helpers/index.js.map +0 -7
  151. package/dist/cjs/helpers/track.d.ts +0 -19
  152. package/dist/cjs/helpers/track.js +0 -2
  153. package/dist/cjs/helpers/track.js.map +0 -7
  154. package/dist/cjs/helpers/utils.d.ts +0 -3
  155. package/dist/cjs/helpers/utils.js +0 -2
  156. package/dist/cjs/helpers/utils.js.map +0 -7
  157. package/dist/cjs/templates/credits.js +0 -2
  158. package/dist/cjs/templates/credits.js.map +0 -7
  159. package/dist/esm/components/credits/context/hooks/useSendEmailValidation.d.ts +0 -1
  160. package/dist/esm/components/credits/context/hooks/useSendEmailValidation.js +0 -2
  161. package/dist/esm/components/credits/context/hooks/useSendEmailValidation.js.map +0 -7
  162. package/dist/esm/components/credits/context/hooks/useSubscriptions.d.ts +0 -9
  163. package/dist/esm/components/credits/context/hooks/useSubscriptions.js +0 -2
  164. package/dist/esm/components/credits/context/hooks/useSubscriptions.js.map +0 -7
  165. package/dist/esm/components/credits/creditsBenefits/benefitItem.js +0 -2
  166. package/dist/esm/components/credits/creditsBenefits/benefitItem.js.map +0 -7
  167. package/dist/esm/helpers/fetchResponse.d.ts +0 -14
  168. package/dist/esm/helpers/fetchResponse.js +0 -2
  169. package/dist/esm/helpers/fetchResponse.js.map +0 -7
  170. package/dist/esm/helpers/fetcher.d.ts +0 -2
  171. package/dist/esm/helpers/fetcher.js +0 -2
  172. package/dist/esm/helpers/fetcher.js.map +0 -7
  173. package/dist/esm/helpers/index.d.ts +0 -2
  174. package/dist/esm/helpers/index.js +0 -2
  175. package/dist/esm/helpers/index.js.map +0 -7
  176. package/dist/esm/helpers/track.d.ts +0 -19
  177. package/dist/esm/helpers/track.js +0 -2
  178. package/dist/esm/helpers/track.js.map +0 -7
  179. package/dist/esm/helpers/utils.d.ts +0 -3
  180. package/dist/esm/helpers/utils.js +0 -2
  181. package/dist/esm/helpers/utils.js.map +0 -7
  182. package/dist/esm/templates/credits.js +0 -2
  183. package/dist/esm/templates/credits.js.map +0 -7
  184. package/src/components/credits/context/hooks/useFunctionMemberPrice.ts +0 -33
  185. package/src/components/credits/context/utils/atobID.ts +0 -8
  186. package/src/components/credits/context/utils/functionDiscountCalculate.ts +0 -57
  187. package/src/components/credits/context/utils/getFunctionMemberPrice.ts +0 -135
  188. package/src/components/credits/context/utils/getFunctionMemberPriceDiscountConfig.ts +0 -51
  189. package/src/components/credits/context/utils/variantGetCoupon.ts +0 -34
  190. /package/dist/cjs/components/credits/creditsBenefits/{benefitItem.d.ts → BenefitItem.d.ts} +0 -0
  191. /package/dist/cjs/components/credits/creditsBenefits/{iconInfo.d.ts → IconInfo.d.ts} +0 -0
  192. /package/dist/esm/components/credits/creditsBenefits/{benefitItem.d.ts → BenefitItem.d.ts} +0 -0
  193. /package/dist/esm/components/credits/creditsBenefits/{iconInfo.d.ts → IconInfo.d.ts} +0 -0
@@ -1,18 +1,9 @@
1
- import { FunctionDiscountType, RoundSelected } from './memberPriceConst'
2
-
3
- // 价格结尾配置
4
- export type PriceEndingConf = {
5
- apply_price_ending: boolean
6
- one_decimal_place: string
7
- two_decimal_place: string
8
- round_selected: RoundSelected
9
- }
1
+ import { FunctionDiscountType } from './memberPriceConst'
10
2
 
11
3
  // 折扣配置
12
4
  export type DiscountConfig = {
13
5
  discount_type: FunctionDiscountType
14
6
  discount_value: number
15
- price_ending_conf?: PriceEndingConf
16
7
  }
17
8
 
18
9
  // 会员价配置类型
@@ -36,19 +27,3 @@ export type FunctionMemberPriceConfig = {
36
27
  other_product_discounts: boolean
37
28
  }
38
29
  }
39
-
40
- // 会员价计算结果
41
- export type FunctionMemberPriceResult = {
42
- hasMemberPrice: boolean
43
- useCoupon: boolean
44
- originalPrice: number
45
- originalPriceWithCurrency: string
46
- salePrice: number
47
- salePriceWithCurrency: string
48
- salePriceWithoutCoupon: number
49
- salePriceWithoutCouponWithCurrency: string
50
- savePrice: number
51
- savePriceWithCurrency: string
52
- savePriceWithoutCoupon: number
53
- savePriceWithoutCouponWithCurrency: string
54
- }
@@ -21,6 +21,17 @@ type Context = {
21
21
  pageCommon: CreditsPageCommon
22
22
  memberPriceDiscount?: FunctionMemberPriceConfig[]
23
23
  alpcBrand?: string
24
+ cartConfig?: {
25
+ addToCart: (params: {
26
+ variantList: Array<{
27
+ variant: any
28
+ quantity: number
29
+ attributes?: Array<{ key: string; value: string }>
30
+ }>
31
+ cartAttributes?: Record<string, string>
32
+ discountCodes?: string[]
33
+ }) => void | Promise<any>
34
+ }
24
35
  }
25
36
 
26
37
  export const CreditsContext = createContext<Context>({
@@ -39,6 +50,7 @@ export const CreditsContext = createContext<Context>({
39
50
  pageCommon: {},
40
51
  memberPriceDiscount: undefined,
41
52
  alpcBrand: undefined,
53
+ cartConfig: undefined,
42
54
  })
43
55
 
44
56
  export function CreditsProvider({
@@ -57,6 +69,7 @@ export function CreditsProvider({
57
69
  pageCommon,
58
70
  memberPriceDiscount,
59
71
  alpcBrand,
72
+ cartConfig,
60
73
  }: PropsWithChildren<Context>) {
61
74
  return (
62
75
  <CreditsContext.Provider
@@ -75,6 +88,7 @@ export function CreditsProvider({
75
88
  pageCommon,
76
89
  memberPriceDiscount,
77
90
  alpcBrand,
91
+ cartConfig,
78
92
  }}
79
93
  >
80
94
  {children}
@@ -1,7 +1,6 @@
1
1
  import { Button, Container, Heading, Picture, Text } from '@anker-in/headless-ui'
2
2
  import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline'
3
- import { motion } from 'framer-motion'
4
- import { useMemo, useState } from 'react'
3
+ import { useMemo, useState, useRef, useEffect } from 'react'
5
4
 
6
5
  import { TaskType, type CreditsAnkersolixTaskProps } from './type'
7
6
  import { useActions } from '../creditsWaysToGetCredits/useActions'
@@ -36,6 +35,21 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
36
35
  isSuccess: isUploadReceiptSuccess,
37
36
  },
38
37
  })
38
+
39
+ const shouldShowMask = (copy?.list || []).length > 3
40
+
41
+ // Handle scroll after collapse animation
42
+ useEffect(() => {
43
+ if (!showMore && shouldShowMask && window.screen.width < 768) {
44
+ const timer = setTimeout(() => {
45
+ const section = document.getElementById(id || 'ankersolix-task')
46
+ if (section) {
47
+ section.scrollIntoView({ behavior: 'smooth', block: 'end' })
48
+ }
49
+ }, 300) // Match transition duration
50
+ return () => clearTimeout(timer)
51
+ }
52
+ }, [showMore, shouldShowMask, id])
39
53
  const list = useMemo(() => {
40
54
  const list = copy.list
41
55
  .map(item => {
@@ -91,9 +105,6 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
91
105
  }
92
106
  }, [actions, copy.list, isLogin])
93
107
 
94
- // 只有大于3个任务时才显示蒙层
95
- const shouldShowMask = list.length > 3
96
-
97
108
  return (
98
109
  <Container id={id} className="bg-[#F5F5F7]">
99
110
  <Heading as="h2" size="4" html={copy.title} />
@@ -141,18 +152,12 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
141
152
 
142
153
  {/* 卡片列表 */}
143
154
  <div className="relative mt-[24px]">
144
- <motion.div
145
- className={cn('grid grid-cols-3 gap-[16px] overflow-hidden md:grid-cols-1 md-l:grid-cols-2 min-md:!h-auto')}
146
- initial={{ height: shouldShowMask ? 512 : 'auto' }}
147
- animate={{ height: showMore || !shouldShowMask ? 'auto' : 512 }}
148
- transition={{ duration: 0.3 }}
149
- onAnimationComplete={() => {
150
- if (!showMore && shouldShowMask && window.screen.width < 768) {
151
- const section = document.getElementById(id || 'ankersolix-task')
152
- if (section) {
153
- section.scrollIntoView({ behavior: 'smooth', block: 'end' })
154
- }
155
- }
155
+ <div
156
+ className={cn(
157
+ 'grid grid-cols-3 gap-[16px] overflow-hidden md:grid-cols-1 md-l:grid-cols-2 min-md:!h-auto transition-all duration-300 ease-in-out'
158
+ )}
159
+ style={{
160
+ height: showMore || !shouldShowMask ? 'auto' : '512px',
156
161
  }}
157
162
  >
158
163
  {list.map(item => (
@@ -194,17 +199,12 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
194
199
  {...(item.handleClick && { onClick: item.handleClick })}
195
200
  variant="primary"
196
201
  size="lg"
197
- className="mt-[24px] w-fit bg-[#080a0f] text-white text-[16px] font-bold tracking-[-0.64px] leading-[1.2]"
202
+ className="mt-[24px] w-fit"
198
203
  >
199
204
  {item.buttonLabel}
200
205
  </Button>
201
206
  ) : (
202
- <Button
203
- variant="primary"
204
- size="lg"
205
- className="mt-[24px] w-fit bg-[#080a0f] text-white text-[16px] font-bold tracking-[-0.64px] leading-[1.2]"
206
- disabled
207
- >
207
+ <Button variant="primary" size="lg" className="mt-[24px] w-fit" disabled>
208
208
  {item.buttonLabel}
209
209
  </Button>
210
210
  )}
@@ -216,7 +216,7 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
216
216
  style={{ background: 'linear-gradient(180deg, rgba(244, 202, 129, 0) 66.37%, #f4ca81 100%)' }}
217
217
  ></div>
218
218
  )}
219
- </motion.div>
219
+ </div>
220
220
  {shouldShowMask && (
221
221
  <>
222
222
  {showMore ? (
@@ -5,6 +5,8 @@ import { useCreditsContext } from '../context/provider'
5
5
  type Img = {
6
6
  url: string
7
7
  alt: string
8
+ width?: number
9
+ height?: number
8
10
  }
9
11
  export type CreditsBannerCopy = {
10
12
  pcImg: Img
@@ -34,15 +36,41 @@ export function CreditsBanner({ copy, id }: { copy: CreditsBannerCopy; id?: stri
34
36
  buttonType === 'primary' ? openSignUpPopup() : openSignInPopup()
35
37
  }
36
38
 
39
+ // 计算图片比例,如果没有配置则使用默认值
40
+ const pcAspectRatio =
41
+ copy.pcImg?.width && copy.pcImg?.height ? `${copy.pcImg.width} / ${copy.pcImg.height}` : '1920 / 804'
42
+ const laptopAspectRatio =
43
+ copy.laptopImg?.width && copy.laptopImg?.height ? `${copy.laptopImg.width} / ${copy.laptopImg.height}` : '768 / 660'
44
+ const mobileAspectRatio =
45
+ copy.mobileImg?.width && copy.mobileImg?.height ? `${copy.mobileImg.width} / ${copy.mobileImg.height}` : '390 / 660'
46
+
37
47
  return (
38
48
  <>
39
49
  <div id={id} className=" relative w-full">
40
50
  <Picture
41
- className="aspect-h-[804] aspect-w-[1920] md:aspect-h-[660] md:aspect-w-[390] md-l:aspect-h-[660] md-l:aspect-w-[768]"
51
+ className="credits-banner-image w-full"
52
+ style={{
53
+ aspectRatio: pcAspectRatio,
54
+ }}
55
+ imgClassName="object-cover w-full h-full"
42
56
  source={`${copy.pcImg?.url}, ${copy.laptopImg?.url} 1024, ${copy.mobileImg?.url} 768`}
43
57
  alt={copy.pcImg?.alt}
44
58
  loading="eager"
45
59
  ></Picture>
60
+ <style>
61
+ {`
62
+ @media (max-width: 1024px) and (min-width: 768px) {
63
+ .credits-banner-image {
64
+ aspect-ratio: ${laptopAspectRatio} !important;
65
+ }
66
+ }
67
+ @media (max-width: 767px) {
68
+ .credits-banner-image {
69
+ aspect-ratio: ${mobileAspectRatio} !important;
70
+ }
71
+ }
72
+ `}
73
+ </style>
46
74
  {isLogin && (
47
75
  <div
48
76
  className="absolute inset-0 "
@@ -54,10 +82,11 @@ export function CreditsBanner({ copy, id }: { copy: CreditsBannerCopy; id?: stri
54
82
 
55
83
  <Container className="l:h-auto !absolute inset-0 mx-auto grid h-full" asChild>
56
84
  <div className="grid grid-cols-12">
57
- <div className="l:col-span-12 l:justify-start l:truncate l:pt-[64px] col-span-5 flex h-full flex-col justify-center text-[#1F2021]">
85
+ <div className="l:col-span-12 l:justify-start l:truncate l:pt-[32px] col-span-5 flex h-full flex-col justify-center text-[#1F2021]">
58
86
  <Heading
59
87
  as="h1"
60
88
  size="5"
89
+ className="text-[48px] xl-xxl:text-[40px] l:text-[32px]"
61
90
  html={isLogin ? copy.login.title?.replace('$name', displayName || '') : copy.unLogin.title}
62
91
  ></Heading>
63
92
 
@@ -29,13 +29,16 @@ const BenefitItem = ({
29
29
  cardBgColor?: string
30
30
  cardBorderColor?: string
31
31
  }) => {
32
- const { brand } = useHeadlessContext()
32
+ const { brand, locale } = useHeadlessContext()
33
33
  const rounded = ROUNDED_BRANDS.includes(brand)
34
34
 
35
+ // 德语和法语需要折行
36
+ const shouldBreakWords = ['de', 'eu-de', 'fr', 'eu-fr'].includes(locale)
37
+
35
38
  // 根据 bigIcon 设置不同屏幕下的图标大小
36
- // 尺寸:≥1921px=64px, 1441-1920px=54px, 1440px=48px
39
+ // 尺寸:≥1921px=64px, 1441-1920px=56px, 1025-1440px=20px, ≤1024px=48px
37
40
  const iconSizeClass = bigIcon
38
- ? 'mb-[16px] size-[64px] xl-xxl:size-[54px] xl:size-[48px] md:absolute md:bottom-[16px] md:right-[16px] md:mb-0'
41
+ ? 'mb-[16px] size-[64px] xl-xxl:size-[56px] xl:size-[48px] md:absolute md:bottom-[16px] md:right-[16px] md:mb-0'
39
42
  : 'mb-[16px] size-[31px] md:absolute md:bottom-[16px] md:right-[16px] md:mb-0'
40
43
 
41
44
  console.log('cardBgColor in BenefitItem', cardBgColor)
@@ -61,7 +64,11 @@ const BenefitItem = ({
61
64
  <div className="flex flex-col">
62
65
  <Picture className={iconSizeClass} alt={item.icon?.alt} source={item.icon?.url} />
63
66
  <div className="flex items-center">
64
- <Heading html={item.text} size="2" className="break-all md-l:line-clamp-3" />
67
+ <Heading
68
+ html={item.text}
69
+ size="2"
70
+ className={cn('md-l:line-clamp-3', shouldBreakWords && 'break-words')}
71
+ />
65
72
  {item.note && (
66
73
  <div
67
74
  role="button"
@@ -2,7 +2,7 @@ export const IconInfo = () => {
2
2
  return (
3
3
  <svg
4
4
  xmlns='http://www.w3.org/2000/svg'
5
- className='size-[18px] cursor-pointer [&_svg]:size-full'
5
+ className='size-[20px] cursor-pointer [&_svg]:size-full'
6
6
  width='18'
7
7
  height='18'
8
8
  viewBox='0 0 18 18'
@@ -27,7 +27,7 @@ export const CreditsCash = ({ copy, id }: { copy: CreditsCashCopy; id?: string }
27
27
  const list = useMemo(() => {
28
28
  return productByHandles
29
29
  ?.map((product: Product) => {
30
- const config = copy.list.find(item => item.products?.[0]?.handle === product.handle)
30
+ const config = (copy.list || []).find(item => item.products?.[0]?.handle === product.handle)
31
31
  const alpcData = redeemableList.find(item => item.id?.toString() === config?.redeemId?.toString())
32
32
  const productVariant =
33
33
  product.variants?.find((variant: any) => variant.sku === config?.products?.[0]?.sku) || product.variants?.[0]
@@ -1,4 +1,4 @@
1
- import { Button, Text, Picture } from '@anker-in/headless-ui'
1
+ import { Button, Text, Picture, Badge } from '@anker-in/headless-ui'
2
2
  import { useMemo, useState } from 'react'
3
3
 
4
4
  import { CreditsCashCopy, RedeemItem } from './type'
@@ -113,11 +113,24 @@ function RedeemableItem({
113
113
  return (
114
114
  <div
115
115
  className={cn(
116
- 'flex flex-col items-center rounded-[16px] bg-[#EAEAEC] md:rounded-[12px] p-[24px] l:p-[8px] md-xl:p-[16px]',
116
+ 'relative flex flex-col items-center rounded-[16px] bg-[#EAEAEC] md:rounded-[12px] p-[24px] l:p-[8px] md-xl:p-[16px]',
117
117
  !rounded && 'rounded-none md:rounded-none',
118
+ copy.badgeLabel && 'pt-[48px] l:pt-[44px]',
118
119
  className
119
120
  )}
120
121
  >
122
+ {/* Redeem 标签 Badge */}
123
+ {copy.badgeLabel && (
124
+ <Badge
125
+ className="absolute left-[24px] l:left-[16px] !bg-gradient-brand top-[16px] z-10"
126
+ size="lg"
127
+ variant="promotional"
128
+ promotionalType="regular-member"
129
+ >
130
+ {copy.badgeLabel}
131
+ </Badge>
132
+ )}
133
+
121
134
  <a
122
135
  href={
123
136
  extractVariantId(itemData.productVariant?.id)
@@ -141,7 +154,7 @@ function RedeemableItem({
141
154
  html={itemData?.product?.title}
142
155
  title={itemData.config?.title || itemData.alpcData?.title || itemData.product?.title}
143
156
  size={2}
144
- className="line-clamp-2 h-[58px] text-[24px] l-xxl:text-[20px] l:text-[16px] leading-[1.2] l:h-[40px] l-xxl:h-[48px]"
157
+ className="line-clamp-2 h-[58px] text-[24px] l-xxl:text-[20px] l:text-[16px] leading-[1.2] l:h-[38px] l-xxl:h-[48px]"
145
158
  />
146
159
  {itemData?.config?.rules?.split('<br>')?.length > 0 && (
147
160
  <button
@@ -198,7 +211,7 @@ function RedeemableItem({
198
211
  />
199
212
  </div>
200
213
 
201
- <div className="group relative w-full">
214
+ <div className="group relative w-full mt-[8px]">
202
215
  <Button
203
216
  disabled={isDisabled}
204
217
  variant="primary"
@@ -25,6 +25,7 @@ export type CreditsCashCopy = {
25
25
  unlockRewards: string
26
26
  btnRedeem: string
27
27
  off: string
28
+ badgeLabel?: string
28
29
  }
29
30
 
30
31
  export type RedeemItem = {
@@ -1,7 +1,6 @@
1
1
  import { Heading, Text } from '@anker-in/headless-ui'
2
2
  import { ChevronDownIcon } from '@heroicons/react/24/outline'
3
3
  import { classNames as cn } from '@anker-in/lib'
4
- import { motion } from 'framer-motion'
5
4
  import { type ReactNode, useEffect, useState } from 'react'
6
5
 
7
6
  type FaqItemProps = {
@@ -67,29 +66,32 @@ export const FaqItem = ({
67
66
  />
68
67
  )}
69
68
  </div>
70
- <motion.div
71
- initial={false}
72
- animate={{ height: !expanded ? 0 : 'auto' }}
73
- className="overflow-hidden [&_td]:border [&_td]:border-[#333] [&_td]:px-[8px] [&_td]:py-[4px]"
74
- >
75
- {answer?.toString()?.includes('https://www.youtube.com') ? (
76
- <Text
77
- as="div"
78
- className={cn('mt-[8px]')}
79
- data-ratio="16:9"
80
- data-content={answer}
81
- html={answer?.toString()}
82
- ></Text>
83
- ) : (
84
- <Text
85
- as="div"
86
- html={answer?.toString()}
87
- className={cn(
88
- 'mt-[8px] text-[16px] font-bold leading-[1.5] text-[#3D3D3F] l:text-[14px] [&_a]:text-brand [&_a]:underline'
89
- )}
90
- ></Text>
69
+ <div
70
+ className={cn(
71
+ 'grid transition-all duration-300 ease-in-out [&_td]:border [&_td]:border-[#333] [&_td]:px-[8px] [&_td]:py-[4px]',
72
+ expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'
91
73
  )}
92
- </motion.div>
74
+ >
75
+ <div className="overflow-hidden">
76
+ {answer?.toString()?.includes('https://www.youtube.com') ? (
77
+ <Text
78
+ as="div"
79
+ className={cn('mt-[8px]')}
80
+ data-ratio="16:9"
81
+ data-content={answer}
82
+ html={answer?.toString()}
83
+ ></Text>
84
+ ) : (
85
+ <Text
86
+ as="div"
87
+ html={answer?.toString()}
88
+ className={cn(
89
+ 'mt-[8px] text-[16px] font-bold leading-[1.5] text-[#3D3D3F] l:text-[14px] [&_a]:text-brand [&_a]:underline'
90
+ )}
91
+ ></Text>
92
+ )}
93
+ </div>
94
+ </div>
93
95
  </div>
94
96
  )
95
97
  }
@@ -72,7 +72,7 @@ export function CreditsInfoCard({ copy, id }: { copy: CreditsInfoCardCopy; id?:
72
72
  {copy.balanceLabel}
73
73
  </div>
74
74
  <div className="flex items-baseline">
75
- <div className={cn('mr-[8px] text-[36px] font-extrabold', 'min-md:text-[44px]', 'min-xl:text-[56px]')}>
75
+ <div className={cn('mr-[8px] text-[36px] font-extrabold text-brand-color-1', 'min-md:text-[44px]', 'min-xl:text-[56px]')}>
76
76
  {creditInfo ? numberFormat(creditInfo.available_credit) : 0}
77
77
  </div>
78
78
  <div className="text-[16px]">{pageCommon?.pointUnit}</div>
@@ -25,12 +25,16 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
25
25
 
26
26
  console.log('copy in CreditsMemberPrice', copy)
27
27
 
28
- // 定义需要获取的 metafield,包括透明图
28
+ // 定义需要获取的 metafield,包括透明图和优惠券信息
29
29
  const variantMetafieldIdentifiers: any[] = [
30
30
  {
31
31
  namespace: 'global',
32
32
  key: 'transparentImg',
33
33
  },
34
+ {
35
+ namespace: '__discountCodeApp',
36
+ key: 'data',
37
+ },
34
38
  ]
35
39
 
36
40
  // 根据屏幕尺寸动态调整每页显示的商品数量
@@ -94,9 +98,44 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
94
98
  },
95
99
  })
96
100
 
97
- // 计算会员价的辅助函数(仅使用普通会员 user_identity = 1 的折扣)
101
+ // variant metafields 中获取有效的 coupon 折扣金额
102
+ const getCouponDiscount = useCallback((variant: any) => {
103
+ try {
104
+ const discountData = variant?.metafields?.__discountCodeApp?.data
105
+ if (!discountData) return 0
106
+
107
+ // discountData 已经是对象,不需要 JSON.parse
108
+ const discounts = discountData
109
+ if (!Array.isArray(discounts) || discounts.length === 0) return 0
110
+
111
+ // 获取第一个有效的 coupon(检查时间范围)
112
+ const now = new Date()
113
+ const validDiscount = discounts.find((discount: any) => {
114
+ const startsAt = discount.starts_at ? new Date(discount.starts_at) : null
115
+ const endsAt = discount.ends_at ? new Date(discount.ends_at) : null
116
+
117
+ // 检查 coupon 是否在有效期内
118
+ if (startsAt && startsAt > now) return false
119
+ if (endsAt && endsAt < now) return false
120
+
121
+ return true
122
+ })
123
+
124
+ // 返回折扣金额(fixed_amount 类型)
125
+ if (validDiscount?.value_type === 'fixed_amount' && validDiscount?.fixed_value) {
126
+ return parseFloat(validDiscount.fixed_value)
127
+ }
128
+
129
+ return 0
130
+ } catch (error) {
131
+ console.error('Failed to get coupon discount:', error)
132
+ return 0
133
+ }
134
+ }, [])
135
+
136
+ // 计算会员价的辅助函数(仅使用普通会员 user_identity = 1 的折扣,并叠加 coupon 折扣)
98
137
  const calculateMemberPrice = useCallback(
99
- (price: number) => {
138
+ (price: number, variant?: any) => {
100
139
  if (!targetRule) return null
101
140
 
102
141
  const discountConfig = targetRule?.discount_conf
@@ -116,12 +155,25 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
116
155
  break
117
156
  }
118
157
 
158
+ // 叠加 coupon 折扣
159
+ if (variant) {
160
+ const couponDiscount = getCouponDiscount(variant)
161
+ if (couponDiscount > 0) {
162
+ salePrice = salePrice.sub(couponDiscount)
163
+ }
164
+ }
165
+
166
+ // 确保价格不为负数
167
+ if (salePrice.lessThan(0)) {
168
+ salePrice = new Decimal(0)
169
+ }
170
+
119
171
  return {
120
172
  memberPrice: salePrice.toNumber(),
121
173
  originalPrice: price,
122
174
  }
123
175
  },
124
- [targetRule]
176
+ [targetRule, getCouponDiscount]
125
177
  )
126
178
 
127
179
  // 处理会员价产品列表(仅普通会员 user_identity = 1 的折扣)
@@ -137,7 +189,7 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
137
189
  const productVariant = product.variants?.find(v => v.sku === variant.sku) || product.variants?.[0]
138
190
  if (!productVariant || !productVariant.availableForSale) return null
139
191
 
140
- const priceResult = calculateMemberPrice(productVariant.price.amount)
192
+ const priceResult = calculateMemberPrice(productVariant.price.amount, productVariant)
141
193
  if (!priceResult) return null
142
194
 
143
195
  return {