@anker-in/campaign-ui 0.4.5-beta.11 → 0.4.5-beta.13
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.
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/CartCard.js +1 -1
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/CartCard.js.map +3 -3
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductCard.js +1 -1
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductCard.js.map +2 -2
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductComparison.js +1 -1
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductComparison.js.map +2 -2
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductList.js +1 -1
- package/dist/cjs/components/LiveChatWidget/components/MessageContent/ProductList.js.map +2 -2
- package/dist/cjs/components/LiveChatWidget/constants.d.ts +0 -1
- package/dist/cjs/components/LiveChatWidget/constants.js +1 -1
- package/dist/cjs/components/LiveChatWidget/constants.js.map +3 -3
- package/dist/cjs/components/credits/context/hooks/useActivities.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useActivities.js.map +2 -2
- package/dist/cjs/components/credits/context/hooks/useAlpcFetch.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useAlpcFetch.js.map +3 -3
- package/dist/cjs/components/credits/context/hooks/useCountries.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useCountries.js.map +2 -2
- package/dist/cjs/components/credits/context/hooks/useMyRewards.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useMyRewards.js.map +2 -2
- package/dist/cjs/components/credits/context/hooks/useRedeemAndBuy.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useRedeemAndBuy.js.map +3 -3
- package/dist/cjs/components/credits/context/hooks/useRedeemableList.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useRedeemableList.js.map +2 -2
- package/dist/cjs/components/credits/context/hooks/useSubscribed.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useSubscribed.js.map +3 -3
- package/dist/cjs/components/credits/context/hooks/useUploadReceipt.d.ts +0 -8
- package/dist/cjs/components/credits/context/hooks/useUploadReceipt.js +1 -1
- package/dist/cjs/components/credits/context/hooks/useUploadReceipt.js.map +3 -3
- package/dist/cjs/components/credits/context/provider.d.ts +2 -1
- package/dist/cjs/components/credits/context/provider.js +1 -1
- package/dist/cjs/components/credits/context/provider.js.map +3 -3
- package/dist/cjs/components/credits/context/utils.d.ts +1 -1
- package/dist/cjs/components/credits/context/utils.js +1 -1
- package/dist/cjs/components/credits/context/utils.js.map +3 -3
- package/dist/cjs/components/credits/creditsBenefits/index.js +2 -3
- package/dist/cjs/components/credits/creditsBenefits/index.js.map +2 -2
- package/dist/cjs/components/credits/creditsCash/CreditsCash.js +1 -1
- package/dist/cjs/components/credits/creditsCash/CreditsCash.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/index.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/index.js.map +2 -2
- package/dist/cjs/components/credits/creditsRedeemList/RedeemCouponModal.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemCouponModal.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/RedeemVirtualProductModal.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemVirtualProductModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/ActivitiesModal.js +1 -1
- package/dist/cjs/components/credits/modal/ActivitiesModal.js.map +2 -2
- package/dist/cjs/components/credits/modal/SubscribeModal.js +1 -1
- package/dist/cjs/components/credits/modal/SubscribeModal.js.map +3 -3
- package/dist/cjs/components/index.d.ts +2 -2
- package/dist/cjs/components/index.js +1 -1
- package/dist/cjs/components/index.js.map +2 -2
- package/dist/cjs/components/registration/authCodeActivate/index.js +1 -1
- package/dist/cjs/components/registration/authCodeActivate/index.js.map +3 -3
- package/dist/cjs/templates/Credits.js +1 -1
- package/dist/cjs/templates/Credits.js.map +2 -2
- package/dist/cjs/templates/Credits.types.d.ts +1 -0
- package/dist/cjs/templates/Credits.types.js.map +1 -1
- package/dist/esm/components/LiveChatWidget/components/MessageContent/CartCard.js +1 -1
- package/dist/esm/components/LiveChatWidget/components/MessageContent/CartCard.js.map +3 -3
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductCard.js +1 -1
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductCard.js.map +3 -3
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductComparison.js +1 -1
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductComparison.js.map +3 -3
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductList.js +1 -1
- package/dist/esm/components/LiveChatWidget/components/MessageContent/ProductList.js.map +3 -3
- package/dist/esm/components/LiveChatWidget/constants.d.ts +0 -1
- package/dist/esm/components/LiveChatWidget/constants.js +1 -1
- package/dist/esm/components/LiveChatWidget/constants.js.map +3 -3
- package/dist/esm/components/credits/context/hooks/useActivities.js +1 -1
- package/dist/esm/components/credits/context/hooks/useActivities.js.map +2 -2
- package/dist/esm/components/credits/context/hooks/useAlpcFetch.js +1 -1
- package/dist/esm/components/credits/context/hooks/useAlpcFetch.js.map +3 -3
- package/dist/esm/components/credits/context/hooks/useCountries.js +1 -1
- package/dist/esm/components/credits/context/hooks/useCountries.js.map +2 -2
- package/dist/esm/components/credits/context/hooks/useMyRewards.js +1 -1
- package/dist/esm/components/credits/context/hooks/useMyRewards.js.map +2 -2
- package/dist/esm/components/credits/context/hooks/useRedeemAndBuy.js +1 -1
- package/dist/esm/components/credits/context/hooks/useRedeemAndBuy.js.map +3 -3
- package/dist/esm/components/credits/context/hooks/useRedeemableList.js +1 -1
- package/dist/esm/components/credits/context/hooks/useRedeemableList.js.map +2 -2
- package/dist/esm/components/credits/context/hooks/useSubscribed.js +1 -1
- package/dist/esm/components/credits/context/hooks/useSubscribed.js.map +3 -3
- package/dist/esm/components/credits/context/hooks/useUploadReceipt.d.ts +0 -8
- package/dist/esm/components/credits/context/hooks/useUploadReceipt.js +1 -1
- package/dist/esm/components/credits/context/hooks/useUploadReceipt.js.map +3 -3
- package/dist/esm/components/credits/context/provider.d.ts +2 -1
- package/dist/esm/components/credits/context/provider.js +1 -1
- package/dist/esm/components/credits/context/provider.js.map +3 -3
- package/dist/esm/components/credits/context/utils.d.ts +1 -1
- package/dist/esm/components/credits/context/utils.js +1 -1
- package/dist/esm/components/credits/context/utils.js.map +3 -3
- package/dist/esm/components/credits/creditsBenefits/index.js +2 -3
- package/dist/esm/components/credits/creditsBenefits/index.js.map +2 -2
- package/dist/esm/components/credits/creditsCash/CreditsCash.js +1 -1
- package/dist/esm/components/credits/creditsCash/CreditsCash.js.map +3 -3
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/index.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/index.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/RedeemCouponModal.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemCouponModal.js.map +3 -3
- package/dist/esm/components/credits/creditsRedeemList/RedeemVirtualProductModal.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemVirtualProductModal.js.map +3 -3
- package/dist/esm/components/credits/modal/ActivitiesModal.js +1 -1
- package/dist/esm/components/credits/modal/ActivitiesModal.js.map +2 -2
- package/dist/esm/components/credits/modal/SubscribeModal.js +1 -1
- package/dist/esm/components/credits/modal/SubscribeModal.js.map +3 -3
- package/dist/esm/components/index.d.ts +2 -2
- package/dist/esm/components/index.js +1 -1
- package/dist/esm/components/index.js.map +2 -2
- package/dist/esm/components/registration/authCodeActivate/index.js +1 -1
- package/dist/esm/components/registration/authCodeActivate/index.js.map +3 -3
- package/dist/esm/templates/Credits.js +1 -1
- package/dist/esm/templates/Credits.js.map +2 -2
- package/dist/esm/templates/Credits.types.d.ts +1 -0
- package/dist/esm/templates/Credits.types.js.map +1 -1
- package/package.json +2 -3
- package/src/components/LiveChatWidget/components/MessageContent/CartCard.tsx +6 -2
- package/src/components/LiveChatWidget/components/MessageContent/ProductCard.tsx +6 -3
- package/src/components/LiveChatWidget/components/MessageContent/ProductComparison.tsx +5 -5
- package/src/components/LiveChatWidget/components/MessageContent/ProductList.tsx +6 -3
- package/src/components/LiveChatWidget/constants.ts +0 -9
- package/src/components/credits/context/hooks/useActivities.ts +2 -2
- package/src/components/credits/context/hooks/useAlpcFetch.ts +64 -20
- package/src/components/credits/context/hooks/useCountries.ts +7 -2
- package/src/components/credits/context/hooks/useMyRewards.ts +5 -2
- package/src/components/credits/context/hooks/useRedeemAndBuy.ts +3 -2
- package/src/components/credits/context/hooks/useRedeemableList.ts +22 -23
- package/src/components/credits/context/hooks/useSubscribed.ts +4 -3
- package/src/components/credits/context/hooks/useUploadReceipt.tsx +42 -21
- package/src/components/credits/context/provider.tsx +4 -0
- package/src/components/credits/context/utils.ts +6 -1
- package/src/components/credits/creditsBenefits/index.tsx +1 -2
- package/src/components/credits/creditsCash/CreditsCash.tsx +12 -5
- package/src/components/credits/creditsRedeemList/AddressForm/index.tsx +4 -6
- package/src/components/credits/creditsRedeemList/RedeemCouponModal.tsx +3 -2
- package/src/components/credits/creditsRedeemList/RedeemVirtualProductModal.tsx +5 -4
- package/src/components/credits/modal/ActivitiesModal.tsx +2 -2
- package/src/components/credits/modal/SubscribeModal.tsx +4 -6
- package/src/components/index.ts +2 -2
- package/src/components/registration/authCodeActivate/index.tsx +8 -6
- package/src/templates/Credits.tsx +1 -0
- package/src/templates/Credits.types.ts +1 -0
- package/dist/cjs/stories/CartCard.stories.d.ts +0 -33
- package/dist/cjs/stories/CartCard.stories.js +0 -21
- package/dist/cjs/stories/CartCard.stories.js.map +0 -7
- package/dist/esm/stories/CartCard.stories.d.ts +0 -33
- package/dist/esm/stories/CartCard.stories.js +0 -21
- package/dist/esm/stories/CartCard.stories.js.map +0 -7
- package/src/stories/CartCard.stories.tsx +0 -459
|
@@ -26,17 +26,36 @@ interface FetcherOptions {
|
|
|
26
26
|
fetchOptions: RequestInit
|
|
27
27
|
onReAuth: () => Promise<boolean>
|
|
28
28
|
onUnAuth: () => void
|
|
29
|
+
apiBaseUrl?: string
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
let reAuthPromise: Promise<boolean> | undefined
|
|
32
33
|
|
|
33
34
|
type Fetcher<TData, TBody> = (url: string, data: { arg: TBody }) => Promise<TData>
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* 统一处理 ALPC 接口返回的数据结构
|
|
38
|
+
* 兼容一层 data 和两层 data 的场景:
|
|
39
|
+
* - 两层 data: {data: {data: ..., code: 27004}}
|
|
40
|
+
* - 一层 data: {data: ..., code: 27004}
|
|
41
|
+
*/
|
|
42
|
+
const normalizeResponseData = (responseData: any) => {
|
|
43
|
+
if (!responseData) return responseData
|
|
44
|
+
|
|
45
|
+
// 如果 responseData.data 存在且是一个对象(不是数组),说明是两层 data 结构
|
|
46
|
+
if (responseData.data && typeof responseData.data === 'object' && !Array.isArray(responseData.data)) {
|
|
47
|
+
return responseData.data
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 一层 data 结构或其他情况,直接返回
|
|
51
|
+
return responseData
|
|
52
|
+
}
|
|
53
|
+
|
|
35
54
|
const fetcher = (options: FetcherOptions) => {
|
|
36
|
-
return fetch(getAlpcPath(options.locale) + options.url, options.fetchOptions).then(async response => {
|
|
55
|
+
return fetch(getAlpcPath(options.locale, options.apiBaseUrl) + options.url, options.fetchOptions).then(async response => {
|
|
37
56
|
if (response.status < 300) {
|
|
38
57
|
const responseData = await response.json()
|
|
39
|
-
return responseData
|
|
58
|
+
return normalizeResponseData(responseData)
|
|
40
59
|
}
|
|
41
60
|
|
|
42
61
|
// 错误处理
|
|
@@ -53,10 +72,10 @@ const fetcher = (options: FetcherOptions) => {
|
|
|
53
72
|
|
|
54
73
|
if (result) {
|
|
55
74
|
// 跨区重新登录后需要替换区域标志,所以不能用最开始请求的那个链接
|
|
56
|
-
return fetch(getAlpcPath(options.locale) + options.url, options.fetchOptions).then(async response => {
|
|
75
|
+
return fetch(getAlpcPath(options.locale, options.apiBaseUrl) + options.url, options.fetchOptions).then(async response => {
|
|
57
76
|
if (response.status < 300) {
|
|
58
77
|
const responseData = await response.json()
|
|
59
|
-
return responseData
|
|
78
|
+
return normalizeResponseData(responseData)
|
|
60
79
|
}
|
|
61
80
|
|
|
62
81
|
if (response.status === 401) {
|
|
@@ -77,14 +96,16 @@ const fetcher = (options: FetcherOptions) => {
|
|
|
77
96
|
})
|
|
78
97
|
}
|
|
79
98
|
|
|
80
|
-
const reAuth = async (locale: string, retry: boolean, brand: string) => {
|
|
81
|
-
let reloginResponse = await fetch(`${getAlpcPath(locale)}/cloud/login`, {
|
|
99
|
+
const reAuth = async (locale: string, retry: boolean, brand: string, apiBaseUrl?: string) => {
|
|
100
|
+
let reloginResponse = await fetch(`${getAlpcPath(locale, apiBaseUrl)}/cloud/login`, {
|
|
82
101
|
method: 'POST',
|
|
83
102
|
})
|
|
84
103
|
let reloginResponseData = await reloginResponse.json()
|
|
104
|
+
// 兼容两层 data 结构
|
|
105
|
+
let normalizedData = normalizeResponseData(reloginResponseData)
|
|
85
106
|
|
|
86
107
|
if (reloginResponse!.status < 300 && !retry) {
|
|
87
|
-
if (
|
|
108
|
+
if (normalizedData?.code === 27004) {
|
|
88
109
|
// 跨区登录错误
|
|
89
110
|
const alpcEUCookie = Cookies.get('alpcEU')
|
|
90
111
|
|
|
@@ -101,17 +122,18 @@ const reAuth = async (locale: string, retry: boolean, brand: string) => {
|
|
|
101
122
|
}
|
|
102
123
|
|
|
103
124
|
// 重新尝试换区登录
|
|
104
|
-
reloginResponse = await fetch(`${getAlpcPath(locale)}/cloud/login`, {
|
|
125
|
+
reloginResponse = await fetch(`${getAlpcPath(locale, apiBaseUrl)}/cloud/login`, {
|
|
105
126
|
method: 'POST',
|
|
106
127
|
})
|
|
107
128
|
reloginResponseData = await reloginResponse.json()
|
|
129
|
+
normalizedData = normalizeResponseData(reloginResponseData)
|
|
108
130
|
|
|
109
131
|
if (reloginResponse.status > 300) {
|
|
110
132
|
return false
|
|
111
133
|
}
|
|
112
134
|
}
|
|
113
135
|
}
|
|
114
|
-
if (!
|
|
136
|
+
if (!normalizedData?.code) {
|
|
115
137
|
// 重新登录成功
|
|
116
138
|
return true
|
|
117
139
|
}
|
|
@@ -127,7 +149,8 @@ export interface UseMutationConfig<TData> {
|
|
|
127
149
|
const useMutation = <TData, TBody>(
|
|
128
150
|
url: string,
|
|
129
151
|
fetcher: Fetcher<TData, TBody>,
|
|
130
|
-
mutationConfig: UseMutationConfig<TData> = {}
|
|
152
|
+
mutationConfig: UseMutationConfig<TData> = {},
|
|
153
|
+
brandRef: React.MutableRefObject<string | undefined>
|
|
131
154
|
) => {
|
|
132
155
|
const innerMutating = useRef<boolean>(false)
|
|
133
156
|
|
|
@@ -140,7 +163,15 @@ const useMutation = <TData, TBody>(
|
|
|
140
163
|
|
|
141
164
|
const trigger = useCallback(
|
|
142
165
|
async (fetchData: TBody, opts: UseMutationConfig<TData> = {}) => {
|
|
166
|
+
console.log('[useAlpcMutation] trigger called with:', { url: urlRef.current, fetchData, brand: brandRef.current })
|
|
167
|
+
|
|
143
168
|
if (innerMutating.current) {
|
|
169
|
+
console.log('[useAlpcMutation] already mutating, skipping')
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (!brandRef.current) {
|
|
174
|
+
console.log('[useAlpcMutation] brand not available, skipping request')
|
|
144
175
|
return
|
|
145
176
|
}
|
|
146
177
|
|
|
@@ -192,7 +223,7 @@ export const useAlpcFetch = <TData>(
|
|
|
192
223
|
swrOptions?: UseAlpcFetchOptionsSwrOptions<TData, Error>
|
|
193
224
|
) => {
|
|
194
225
|
const [retry, setRetry] = useState(false)
|
|
195
|
-
const { removeProfile, alpcBrand } = useCreditsContext()
|
|
226
|
+
const { removeProfile, alpcBrand, apiBaseUrl } = useCreditsContext()
|
|
196
227
|
|
|
197
228
|
const { enable, ...otherSwrOptions } = swrOptions || {}
|
|
198
229
|
|
|
@@ -207,12 +238,13 @@ export const useAlpcFetch = <TData>(
|
|
|
207
238
|
|
|
208
239
|
const context = useSWR<TData>(
|
|
209
240
|
[url, requestBody],
|
|
210
|
-
!fetchEnable
|
|
241
|
+
!fetchEnable || !brand
|
|
211
242
|
? null
|
|
212
243
|
: ([requestUrl, data]: [string, Record<string, any>]) =>
|
|
213
244
|
fetcher({
|
|
214
245
|
url: requestUrl,
|
|
215
246
|
locale,
|
|
247
|
+
apiBaseUrl,
|
|
216
248
|
fetchOptions: {
|
|
217
249
|
method: 'POST',
|
|
218
250
|
headers: {
|
|
@@ -226,7 +258,7 @@ export const useAlpcFetch = <TData>(
|
|
|
226
258
|
...fetchOptions,
|
|
227
259
|
},
|
|
228
260
|
onReAuth: async () => {
|
|
229
|
-
const result = await reAuth(locale, retry, brand)
|
|
261
|
+
const result = await reAuth(locale, retry, brand, apiBaseUrl)
|
|
230
262
|
|
|
231
263
|
if (result) {
|
|
232
264
|
setRetry(true)
|
|
@@ -251,20 +283,30 @@ export const useAlpcFetch = <TData>(
|
|
|
251
283
|
|
|
252
284
|
export const useAlpcMutation = <TData, TBody>(options: MutationOptions, mutationOptions?: UseMutationConfig<TData>) => {
|
|
253
285
|
const [retry, setRetry] = useState(false)
|
|
254
|
-
const { removeProfile, alpcBrand } = useCreditsContext()
|
|
286
|
+
const { removeProfile, alpcBrand, apiBaseUrl } = useCreditsContext()
|
|
255
287
|
|
|
256
288
|
const { locale = '', brand: headlessBrand } = useHeadlessContext()
|
|
257
289
|
// 优先使用 creditsContext 中的 alpcBrand,如果没有则使用 headlessConfig 中的 brand
|
|
258
290
|
const brand = alpcBrand || headlessBrand
|
|
291
|
+
const brandRef = useRef(brand)
|
|
292
|
+
brandRef.current = brand
|
|
259
293
|
|
|
260
294
|
const { url, initData, headers, ...fetchOptions } = options
|
|
295
|
+
const initDataRef = useRef(initData)
|
|
296
|
+
initDataRef.current = initData
|
|
261
297
|
|
|
262
298
|
const context = useMutation<TData, TBody>(
|
|
263
299
|
url,
|
|
264
|
-
(requestUrl, data: { arg: TBody }) =>
|
|
265
|
-
|
|
300
|
+
(requestUrl, data: { arg: TBody }) => {
|
|
301
|
+
// Prevent requests when brand is not available
|
|
302
|
+
if (!brandRef.current) {
|
|
303
|
+
return Promise.resolve(undefined as unknown as TData)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return fetcher({
|
|
266
307
|
url: requestUrl,
|
|
267
308
|
locale,
|
|
309
|
+
apiBaseUrl,
|
|
268
310
|
fetchOptions: {
|
|
269
311
|
method: 'POST',
|
|
270
312
|
headers: {
|
|
@@ -273,12 +315,12 @@ export const useAlpcMutation = <TData, TBody>(options: MutationOptions, mutation
|
|
|
273
315
|
},
|
|
274
316
|
...fetchOptions,
|
|
275
317
|
body: JSON.stringify({
|
|
276
|
-
...
|
|
318
|
+
...initDataRef.current,
|
|
277
319
|
...data.arg,
|
|
278
320
|
}),
|
|
279
321
|
},
|
|
280
322
|
onReAuth: async () => {
|
|
281
|
-
const result = await reAuth(locale, retry,
|
|
323
|
+
const result = await reAuth(locale, retry, brandRef.current!, apiBaseUrl)
|
|
282
324
|
|
|
283
325
|
if (result) {
|
|
284
326
|
setRetry(true)
|
|
@@ -291,8 +333,10 @@ export const useAlpcMutation = <TData, TBody>(options: MutationOptions, mutation
|
|
|
291
333
|
// 失败后退出登录
|
|
292
334
|
removeProfile()
|
|
293
335
|
},
|
|
294
|
-
})
|
|
295
|
-
|
|
336
|
+
})
|
|
337
|
+
},
|
|
338
|
+
mutationOptions,
|
|
339
|
+
brandRef
|
|
296
340
|
)
|
|
297
341
|
|
|
298
342
|
return context
|
|
@@ -13,13 +13,18 @@ function useCountries({ shopifyStoreDomain }: { shopifyStoreDomain: string }) {
|
|
|
13
13
|
const fetchCountries = async () => {
|
|
14
14
|
setLoading(true)
|
|
15
15
|
try {
|
|
16
|
-
const response = await fetch(`/api/multipass/rainbowbridge/uc/shop/shipping_zones?shop=${shopifyStoreDomain}
|
|
16
|
+
const response = await fetch(`/api/multipass/rainbowbridge/uc/shop/shipping_zones?shop=${shopifyStoreDomain}`, {
|
|
17
|
+
headers: {
|
|
18
|
+
'current-language': locale,
|
|
19
|
+
},
|
|
20
|
+
})
|
|
17
21
|
const res: any = await response.json()
|
|
18
22
|
|
|
19
23
|
// 国家过滤
|
|
20
24
|
let shipsToCountries: ShippingCountry[] = []
|
|
21
25
|
const countrySet = new Set()
|
|
22
|
-
res
|
|
26
|
+
const shippingZones = res?.data?.data || res?.data || []
|
|
27
|
+
shippingZones.forEach((shippingZoneItem: ShippingZone) => {
|
|
23
28
|
shippingZoneItem.countries.forEach(shippingZoneCountryItem => {
|
|
24
29
|
if (!countrySet.has(shippingZoneCountryItem.code)) {
|
|
25
30
|
countrySet.add(shippingZoneCountryItem.code)
|
|
@@ -15,7 +15,7 @@ function useMyRewards({
|
|
|
15
15
|
pageSize: number
|
|
16
16
|
consumeType?: AlpcConsumeType
|
|
17
17
|
}) {
|
|
18
|
-
const {
|
|
18
|
+
const { profile, alpcBrand } = useCreditsContext()
|
|
19
19
|
const { brand: headlessBrand, locale, appName } = useHeadlessContext()
|
|
20
20
|
const brand = alpcBrand || headlessBrand
|
|
21
21
|
|
|
@@ -60,8 +60,11 @@ function useMyRewards({
|
|
|
60
60
|
}, [consumeType, page, pageSize, profile?.user_id])
|
|
61
61
|
|
|
62
62
|
useEffect(() => {
|
|
63
|
+
if (!brand || !profile?.user_id) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
63
66
|
getMyRewards()
|
|
64
|
-
}, [getMyRewards])
|
|
67
|
+
}, [getMyRewards, brand])
|
|
65
68
|
|
|
66
69
|
return {
|
|
67
70
|
myRewards,
|
|
@@ -38,9 +38,10 @@ export const useRedeemAndBuy = (
|
|
|
38
38
|
user_id: profile?.user_id,
|
|
39
39
|
rule_id: arg.redeemId,
|
|
40
40
|
})
|
|
41
|
-
|
|
41
|
+
const data = (res?.data || res) as { success?: boolean; coupon_code?: string }
|
|
42
|
+
if (res && data?.coupon_code) {
|
|
42
43
|
buyNow({
|
|
43
|
-
discountCodes: [
|
|
44
|
+
discountCodes: [data.coupon_code],
|
|
44
45
|
lineItems: [
|
|
45
46
|
{
|
|
46
47
|
variant: arg.productVariant,
|
|
@@ -23,7 +23,7 @@ function useRedeemableList(props?: { consumeType: AlpcConsumeType }) {
|
|
|
23
23
|
{
|
|
24
24
|
data: { consume_credit_rules: ConsumeCreditRuleResponse[] }
|
|
25
25
|
},
|
|
26
|
-
{ consume_type?: AlpcConsumeType
|
|
26
|
+
{ consume_type?: AlpcConsumeType; user_id?: string }
|
|
27
27
|
>({
|
|
28
28
|
url: `/v1/credit/consume_credit_rules`,
|
|
29
29
|
initData: {
|
|
@@ -34,32 +34,31 @@ function useRedeemableList(props?: { consumeType: AlpcConsumeType }) {
|
|
|
34
34
|
},
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
const getRedeemableList = useCallback(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
onSuccess(responseData) {
|
|
45
|
-
console.log('responseData', responseData)
|
|
46
|
-
let list = responseData.data.consume_credit_rules || []
|
|
47
|
-
// let cList = list.filter(i => i.consume_type == 1) || []
|
|
48
|
-
// let pList = list.filter(i => i.consume_type == 2) || []
|
|
49
|
-
// cList = cList.sort((prev, next) => prev.consume_credits - next.consume_credits)
|
|
50
|
-
// pList = pList.sort((prev, next) => prev.consume_credits - next.consume_credits)
|
|
51
|
-
// const resultList = cList.concat(pList)
|
|
52
|
-
setRedeemableList(list)
|
|
37
|
+
const getRedeemableList = useCallback(
|
|
38
|
+
(props?: { consumeType?: AlpcConsumeType }) => {
|
|
39
|
+
trigger(
|
|
40
|
+
{
|
|
41
|
+
user_id: profile?.user_id,
|
|
42
|
+
...(props?.consumeType && { consume_type: props.consumeType }),
|
|
53
43
|
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
44
|
+
{
|
|
45
|
+
onSuccess(responseData) {
|
|
46
|
+
console.log('responseData', responseData)
|
|
47
|
+
let list = responseData?.data?.consume_credit_rules || []
|
|
48
|
+
setRedeemableList(list)
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
},
|
|
53
|
+
[profile, trigger, locale]
|
|
54
|
+
)
|
|
57
55
|
|
|
58
56
|
useEffect(() => {
|
|
59
|
-
if (!isLoadingProfile) {
|
|
60
|
-
|
|
57
|
+
if (!brand || isLoadingProfile) {
|
|
58
|
+
return
|
|
61
59
|
}
|
|
62
|
-
|
|
60
|
+
getRedeemableList({ consumeType: props?.consumeType })
|
|
61
|
+
}, [getRedeemableList, isLoadingProfile, brand])
|
|
63
62
|
|
|
64
63
|
return {
|
|
65
64
|
listLoading,
|
|
@@ -13,13 +13,14 @@ export const useSubscribed = () => {
|
|
|
13
13
|
|
|
14
14
|
const { activities } = useActivities(activitiesOptions)
|
|
15
15
|
const { data: subscription } = useSubscriptions({ email: profile?.email })
|
|
16
|
+
const subscriptionData = subscription?.data || subscription
|
|
16
17
|
|
|
17
18
|
const isSubscribed = useMemo(() => {
|
|
18
|
-
if (!
|
|
19
|
+
if (!subscriptionData?.preference) {
|
|
19
20
|
return false
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
const subscribeResult =
|
|
23
|
+
const subscribeResult = subscriptionData.preference.some((item: any) => {
|
|
23
24
|
return item.brand === brand && item.subscribe
|
|
24
25
|
})
|
|
25
26
|
|
|
@@ -30,7 +31,7 @@ export const useSubscribed = () => {
|
|
|
30
31
|
return activities?.some(item => {
|
|
31
32
|
return item.task_sub_type === TaskSubType.Subscription
|
|
32
33
|
})
|
|
33
|
-
}, [
|
|
34
|
+
}, [subscriptionData?.preference, activities])
|
|
34
35
|
|
|
35
36
|
return isSubscribed
|
|
36
37
|
}
|
|
@@ -1,29 +1,50 @@
|
|
|
1
1
|
import useSWRMutation from 'swr/mutation'
|
|
2
|
+
import { useHeadlessContext } from '@anker-in/lib'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
headers: {
|
|
14
|
-
'Content-Type': 'application/json',
|
|
15
|
-
},
|
|
16
|
-
body: JSON.stringify({
|
|
17
|
-
order_name: orderName,
|
|
18
|
-
}),
|
|
19
|
-
})
|
|
20
|
-
const { data } = await response.json()
|
|
21
|
-
return {
|
|
22
|
-
ok: data?.code === 0,
|
|
23
|
-
code: data?.code,
|
|
4
|
+
/**
|
|
5
|
+
* 统一处理 ALPC 接口返回的数据结构
|
|
6
|
+
* 兼容一层 data 和两层 data 的场景
|
|
7
|
+
*/
|
|
8
|
+
const normalizeResponseData = (responseData: any) => {
|
|
9
|
+
if (!responseData) return responseData
|
|
10
|
+
|
|
11
|
+
// 如果 responseData.data 存在且是一个对象(不是数组),说明是两层 data 结构
|
|
12
|
+
if (responseData.data && typeof responseData.data === 'object' && !Array.isArray(responseData.data)) {
|
|
13
|
+
return responseData.data
|
|
24
14
|
}
|
|
15
|
+
|
|
16
|
+
// 一层 data 结构或其他情况,直接返回
|
|
17
|
+
return responseData
|
|
25
18
|
}
|
|
26
19
|
|
|
27
20
|
export const useUploadReceipt = () => {
|
|
21
|
+
const { locale } = useHeadlessContext()
|
|
22
|
+
|
|
23
|
+
const uploadReceipt = async (
|
|
24
|
+
_: any,
|
|
25
|
+
{ arg: { orderName } }: { arg: { orderName: string } }
|
|
26
|
+
): Promise<{
|
|
27
|
+
ok: boolean
|
|
28
|
+
code: number
|
|
29
|
+
}> => {
|
|
30
|
+
const response = await fetch(`/api/multipass/mktsrv/v1/credit/upload_third_party_order`, {
|
|
31
|
+
credentials: 'include',
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/json',
|
|
35
|
+
'current-language': locale,
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
order_name: orderName,
|
|
39
|
+
}),
|
|
40
|
+
})
|
|
41
|
+
const result = await response.json()
|
|
42
|
+
const normalizedData = normalizeResponseData(result)
|
|
43
|
+
return {
|
|
44
|
+
ok: normalizedData?.data?.code === 0,
|
|
45
|
+
code: normalizedData?.data?.code ?? -1,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
28
49
|
return useSWRMutation('/api/multipass/mktsrv/v1/credit/upload_third_party_order', uploadReceipt)
|
|
29
50
|
}
|
|
@@ -37,6 +37,7 @@ type Context = {
|
|
|
37
37
|
setOpenMyRewardsModal: (open: boolean) => void
|
|
38
38
|
openActivitiesModal: boolean
|
|
39
39
|
setOpenActivitiesModal: (open: boolean) => void
|
|
40
|
+
apiBaseUrl?: string
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
export const CreditsContext = createContext<Context>({
|
|
@@ -61,6 +62,7 @@ export const CreditsContext = createContext<Context>({
|
|
|
61
62
|
setOpenMyRewardsModal: () => {},
|
|
62
63
|
openActivitiesModal: false,
|
|
63
64
|
setOpenActivitiesModal: () => {},
|
|
65
|
+
apiBaseUrl: undefined,
|
|
64
66
|
})
|
|
65
67
|
|
|
66
68
|
export function CreditsProvider({
|
|
@@ -80,6 +82,7 @@ export function CreditsProvider({
|
|
|
80
82
|
memberPriceDiscount,
|
|
81
83
|
alpcBrand,
|
|
82
84
|
cartConfig,
|
|
85
|
+
apiBaseUrl,
|
|
83
86
|
}: PropsWithChildren<Omit<Context, 'openMyRewardsModal' | 'setOpenMyRewardsModal' | 'openActivitiesModal' | 'setOpenActivitiesModal'>>) {
|
|
84
87
|
const [openMyRewardsModal, setOpenMyRewardsModal] = useState(false)
|
|
85
88
|
const [openActivitiesModal, setOpenActivitiesModal] = useState(false)
|
|
@@ -102,6 +105,7 @@ export function CreditsProvider({
|
|
|
102
105
|
memberPriceDiscount,
|
|
103
106
|
alpcBrand,
|
|
104
107
|
cartConfig,
|
|
108
|
+
apiBaseUrl,
|
|
105
109
|
openMyRewardsModal,
|
|
106
110
|
setOpenMyRewardsModal,
|
|
107
111
|
openActivitiesModal,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Cookies from 'js-cookie'
|
|
2
2
|
import { PRICE_SYMBOL } from './const'
|
|
3
3
|
|
|
4
|
-
export function getAlpcPath(locale = '') {
|
|
4
|
+
export function getAlpcPath(locale = '', apiBaseUrl?: string) {
|
|
5
5
|
let isEU = false
|
|
6
6
|
const alpcEUCookie = Cookies.get('alpcEU')
|
|
7
7
|
if (alpcEUCookie === undefined || alpcEUCookie === '') {
|
|
@@ -15,6 +15,11 @@ export function getAlpcPath(locale = '') {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// 如果提供了自定义的 apiBaseUrl,拼接对应的路径
|
|
19
|
+
if (apiBaseUrl) {
|
|
20
|
+
return isEU ? `${apiBaseUrl}/api/multipass/alpc-eu` : `${apiBaseUrl}/api/multipass/alpc`
|
|
21
|
+
}
|
|
22
|
+
|
|
18
23
|
if (isEU) {
|
|
19
24
|
return '/api/multipass/alpc-eu'
|
|
20
25
|
}
|
|
@@ -103,8 +103,7 @@ export const CreditsBenefits = ({ copy, id }: { copy: CreditsBenefitsCopy; id?:
|
|
|
103
103
|
</Swiper>
|
|
104
104
|
<div
|
|
105
105
|
id="benefits-pagination"
|
|
106
|
-
className="mx-auto mt-[12px] grid !w-fit grid-flow-col [&_.swiper-pagination-bullet-active
|
|
107
|
-
[&_.swiper-pagination-bullet]:cursor-pointer [&_.swiper-pagination-bullet]:rounded-full"
|
|
106
|
+
className="mx-auto mt-[12px] grid !w-fit grid-flow-col [&_.swiper-pagination-bullet-active]:!bg-[#151515]"
|
|
108
107
|
></div>
|
|
109
108
|
</div>
|
|
110
109
|
|
|
@@ -28,13 +28,20 @@ export const CreditsCash = ({ copy, id }: { copy: CreditsCashCopy; id?: string }
|
|
|
28
28
|
})
|
|
29
29
|
|
|
30
30
|
const list = useMemo(() => {
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
const
|
|
31
|
+
return (copy?.list || [])
|
|
32
|
+
.map(config => {
|
|
33
|
+
const handle = config?.products?.[0]?.handle
|
|
34
|
+
const sku = config?.products?.[0]?.sku
|
|
34
35
|
const alpcData = redeemableList.find(item => item.id?.toString() === config?.redeemId?.toString())
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
// 从 productByHandles 中找到对应 handle 的 product
|
|
38
|
+
const product = productByHandles?.find((p: Product) => p.handle === handle)
|
|
39
|
+
if (!product) return null
|
|
40
|
+
|
|
41
|
+
// 在 product 的 variants 中找到对应 sku 的 variant
|
|
42
|
+
const productVariant = product.variants?.find((variant: any) => variant.sku === sku) || product.variants?.[0]
|
|
37
43
|
if (!alpcData || !productVariant) return null
|
|
44
|
+
|
|
38
45
|
return {
|
|
39
46
|
product,
|
|
40
47
|
productVariant,
|
|
@@ -60,12 +60,10 @@ export const AddressForm = ({ countries, countriesLoading, form, validate, error
|
|
|
60
60
|
}, [customer, profile?.email, locale])
|
|
61
61
|
|
|
62
62
|
useEffect(() => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
}, [customer, getDefaultAddress])
|
|
63
|
+
const defaultAddress = getDefaultAddress()
|
|
64
|
+
setAddress(defaultAddress)
|
|
65
|
+
onChange(defaultAddress)
|
|
66
|
+
}, [getDefaultAddress])
|
|
69
67
|
|
|
70
68
|
if (!address) {
|
|
71
69
|
return null
|
|
@@ -32,8 +32,9 @@ function RedeemCouponModal({
|
|
|
32
32
|
return
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const data = responseData?.data || responseData
|
|
36
|
+
if (data?.success) {
|
|
37
|
+
setCouponCode(data.coupon_code)
|
|
37
38
|
fetchCreditInfo(profile?.user_id)
|
|
38
39
|
} else {
|
|
39
40
|
let errorMsg
|
|
@@ -40,8 +40,9 @@ function RedeemVirtualProductModal({
|
|
|
40
40
|
return
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
const data = responseData?.data || responseData
|
|
44
|
+
if (data?.id) {
|
|
45
|
+
setGiftCardId(data.id)
|
|
45
46
|
fetchCreditInfo(profile?.user_id)
|
|
46
47
|
} else {
|
|
47
48
|
handleRedeemError(responseData.code)
|
|
@@ -120,8 +121,8 @@ function RedeemVirtualProductModal({
|
|
|
120
121
|
// GiftCard 类型使用 Product 接口,传递默认地址
|
|
121
122
|
const defaultAddress = {
|
|
122
123
|
email: profile?.email || '',
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
first_name: profile?.firstName || 'Anker',
|
|
125
|
+
last_name: profile?.lastName || 'Direct',
|
|
125
126
|
address1: 'Default Address',
|
|
126
127
|
city: 'Default City',
|
|
127
128
|
province: 'Default Province',
|
|
@@ -108,7 +108,7 @@ function ActivitiesModal({ data, ...props }: ActivitiesModalProps) {
|
|
|
108
108
|
// 新增的部分任务都使用了 alpc 同一个任务类型,需要用任务 id 来区分
|
|
109
109
|
return item.task_name.replace('Refund', data.productUnApprovedTask)
|
|
110
110
|
} else if (taskIdToTypeMapping?.[String(item.task_rule_id)]) {
|
|
111
|
-
return dtcTaskTypeToNameMap[taskIdToTypeMapping?.[String(item.task_rule_id)]]
|
|
111
|
+
return dtcTaskTypeToNameMap[taskIdToTypeMapping?.[String(item.task_rule_id)]] || item.task_name
|
|
112
112
|
} else {
|
|
113
113
|
return taskNameMap[item.task_sub_type] || item.task_name
|
|
114
114
|
}
|
|
@@ -198,7 +198,7 @@ function ActivitiesModal({ data, ...props }: ActivitiesModalProps) {
|
|
|
198
198
|
</Tabs>
|
|
199
199
|
</div>
|
|
200
200
|
|
|
201
|
-
<div className="grid gap-[18px] overflow-auto
|
|
201
|
+
<div className="grid gap-[18px] overflow-auto md:gap-[12px]">
|
|
202
202
|
{isLoading && (
|
|
203
203
|
<div className="flex h-full flex-col items-center justify-center">
|
|
204
204
|
<LoadingDots />
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react'
|
|
2
|
-
import { useRouter } from 'next/router'
|
|
3
2
|
import { Button, Checkbox, Picture, Text } from '@anker-in/headless-ui'
|
|
4
3
|
import { classNames, fetcher, gaTrack, useHeadlessContext } from '@anker-in/lib'
|
|
5
4
|
import Cookies from 'js-cookie'
|
|
@@ -43,9 +42,8 @@ const getAdCookie = () => {
|
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
export function CreditsSubscribeModal({ copy, onSuccess, ...props }: CreditsSubscribeModalProps) {
|
|
46
|
-
const { brand } = useHeadlessContext()
|
|
45
|
+
const { brand, locale } = useHeadlessContext()
|
|
47
46
|
const rounded = ROUNDED_BRANDS.includes(brand)
|
|
48
|
-
const { locale } = useRouter()
|
|
49
47
|
const [policy, setPolicy] = useState(false)
|
|
50
48
|
const [email, setEmail] = useState('')
|
|
51
49
|
const [errorMessage, setErrorMessage] = useState('')
|
|
@@ -137,7 +135,7 @@ export function CreditsSubscribeModal({ copy, onSuccess, ...props }: CreditsSubs
|
|
|
137
135
|
animationClassName="md:translate-y-[100vh]"
|
|
138
136
|
{...props}
|
|
139
137
|
>
|
|
140
|
-
<div className="flex flex-col gap-[16px] text-center
|
|
138
|
+
<div className="min-l:px-[16px] flex flex-col gap-[16px] text-center">
|
|
141
139
|
<div>
|
|
142
140
|
<Text className={classNames('mb-[24px] text-[22px] font-bold')} html={copy.title}></Text>
|
|
143
141
|
</div>
|
|
@@ -173,7 +171,7 @@ export function CreditsSubscribeModal({ copy, onSuccess, ...props }: CreditsSubs
|
|
|
173
171
|
>
|
|
174
172
|
<Picture
|
|
175
173
|
source="https://cdn.shopify.com/s/files/1/0512/8568/8505/files/icon_email.png?v=1697527383"
|
|
176
|
-
className="
|
|
174
|
+
className="size-[24px]"
|
|
177
175
|
alt="email"
|
|
178
176
|
/>
|
|
179
177
|
</Button>
|
|
@@ -181,7 +179,7 @@ export function CreditsSubscribeModal({ copy, onSuccess, ...props }: CreditsSubs
|
|
|
181
179
|
<div className="flex w-full">
|
|
182
180
|
<Checkbox checked={policy} onCheckedChange={() => setPolicy(!policy)} required className="border-[#1d1d1f]" />
|
|
183
181
|
<label
|
|
184
|
-
className="
|
|
182
|
+
className="ml-2 text-left text-[14px] font-semibold text-[#777] [&_a]:underline"
|
|
185
183
|
dangerouslySetInnerHTML={{
|
|
186
184
|
__html: copy?.policy || '',
|
|
187
185
|
}}
|
package/src/components/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as Chat } from './chat/index
|
|
1
|
+
export { default as Chat } from './chat/index'
|
|
2
2
|
|
|
3
3
|
export {
|
|
4
4
|
Role,
|
|
@@ -7,7 +7,7 @@ export {
|
|
|
7
7
|
useCopilotChat,
|
|
8
8
|
useCopilotAction,
|
|
9
9
|
useCopilotReadable,
|
|
10
|
-
} from './chat/utils
|
|
10
|
+
} from './chat/utils'
|
|
11
11
|
|
|
12
12
|
export * from './credits/index.js'
|
|
13
13
|
|