@anker-in/campaign-ui 0.2.11-beta.2 → 0.2.11-beta.3
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/credits/context/hooks/useSendEmailValidation.d.ts +1 -0
- package/dist/cjs/components/credits/context/hooks/useSendEmailValidation.js +2 -0
- package/dist/cjs/components/credits/context/hooks/useSendEmailValidation.js.map +7 -0
- package/dist/cjs/components/credits/context/hooks/useSubscriptions.d.ts +9 -0
- package/dist/cjs/components/credits/context/hooks/useSubscriptions.js +2 -0
- package/dist/cjs/components/credits/context/hooks/useSubscriptions.js.map +7 -0
- package/dist/cjs/components/credits/context/utils.d.ts +4 -0
- 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/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
- package/dist/cjs/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +3 -3
- package/dist/cjs/components/credits/creditsBenefits/benefitItem.js +2 -0
- package/dist/cjs/components/credits/creditsBenefits/benefitItem.js.map +7 -0
- package/dist/cjs/components/credits/creditsBenefits/index.js +3 -3
- package/dist/cjs/components/credits/creditsBenefits/index.js.map +2 -2
- package/dist/cjs/components/credits/creditsCash/RedeemableItem.js +1 -1
- package/dist/cjs/components/credits/creditsCash/RedeemableItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsFaq/index.js +1 -1
- package/dist/cjs/components/credits/creditsFaq/index.js.map +3 -3
- package/dist/cjs/components/credits/creditsInfoCard/index.js +1 -1
- package/dist/cjs/components/credits/creditsInfoCard/index.js.map +3 -3
- package/dist/cjs/components/credits/creditsMemberPrice/CreditsMemberPrice.js +1 -1
- package/dist/cjs/components/credits/creditsMemberPrice/CreditsMemberPrice.js.map +3 -3
- package/dist/cjs/components/credits/creditsMemberPrice/MemberPriceItem.js +1 -1
- package/dist/cjs/components/credits/creditsMemberPrice/MemberPriceItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsMemberPrice/Pagination.d.ts +7 -0
- package/dist/cjs/components/credits/creditsMemberPrice/Pagination.js +2 -0
- package/dist/cjs/components/credits/creditsMemberPrice/Pagination.js.map +7 -0
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/CountrySelect.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/CountrySelect.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/StateSelect.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/AddressForm/StateSelect.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 +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/CreditsRedeemList.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/CreditsRedeemList.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Address.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Address.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Success.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemProductModal/Success.js.map +3 -3
- package/dist/cjs/components/credits/creditsRedeemList/RedeemableItem.js +1 -1
- package/dist/cjs/components/credits/creditsRedeemList/RedeemableItem.js.map +3 -3
- package/dist/cjs/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js +1 -1
- package/dist/cjs/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js.map +3 -3
- package/dist/cjs/components/credits/modal/MyRewardsModal.js +1 -1
- package/dist/cjs/components/credits/modal/MyRewardsModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/activitiesModal.js +1 -1
- package/dist/cjs/components/credits/modal/activitiesModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/creditsUploadReceiptModal.js +1 -1
- package/dist/cjs/components/credits/modal/creditsUploadReceiptModal.js.map +3 -3
- package/dist/cjs/components/credits/modal/modalContainer.js +1 -1
- package/dist/cjs/components/credits/modal/modalContainer.js.map +3 -3
- 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/credits/modal/tip.js +1 -1
- package/dist/cjs/components/credits/modal/tip.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/components/registration/modalContainer.js +1 -1
- package/dist/cjs/components/registration/modalContainer.js.map +3 -3
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/constants.js +2 -0
- package/dist/cjs/constants.js.map +7 -0
- package/dist/cjs/helpers/fetchResponse.d.ts +14 -0
- package/dist/cjs/helpers/fetchResponse.js +2 -0
- package/dist/cjs/helpers/fetchResponse.js.map +7 -0
- package/dist/cjs/helpers/fetcher.d.ts +2 -0
- package/dist/cjs/helpers/fetcher.js +2 -0
- package/dist/cjs/helpers/fetcher.js.map +7 -0
- package/dist/cjs/helpers/index.d.ts +2 -0
- package/dist/cjs/helpers/index.js +2 -0
- package/dist/cjs/helpers/index.js.map +7 -0
- package/dist/cjs/helpers/track.d.ts +19 -0
- package/dist/cjs/helpers/track.js +2 -0
- package/dist/cjs/helpers/track.js.map +7 -0
- package/dist/cjs/helpers/utils.d.ts +3 -0
- package/dist/cjs/helpers/utils.js +2 -0
- package/dist/cjs/helpers/utils.js.map +7 -0
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +2 -2
- package/dist/esm/components/credits/context/hooks/useSendEmailValidation.d.ts +1 -0
- package/dist/esm/components/credits/context/hooks/useSendEmailValidation.js +2 -0
- package/dist/esm/components/credits/context/hooks/useSendEmailValidation.js.map +7 -0
- package/dist/esm/components/credits/context/hooks/useSubscriptions.d.ts +9 -0
- package/dist/esm/components/credits/context/hooks/useSubscriptions.js +2 -0
- package/dist/esm/components/credits/context/hooks/useSubscriptions.js.map +7 -0
- package/dist/esm/components/credits/context/utils.d.ts +4 -0
- 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/creditsAnkersolixTask/CreditsAnkersolixTask.js +1 -1
- package/dist/esm/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.js.map +3 -3
- package/dist/esm/components/credits/creditsBenefits/benefitItem.js +2 -0
- package/dist/esm/components/credits/creditsBenefits/benefitItem.js.map +7 -0
- package/dist/esm/components/credits/creditsBenefits/index.js +3 -3
- package/dist/esm/components/credits/creditsBenefits/index.js.map +2 -2
- package/dist/esm/components/credits/creditsCash/RedeemableItem.js +1 -1
- package/dist/esm/components/credits/creditsCash/RedeemableItem.js.map +3 -3
- package/dist/esm/components/credits/creditsFaq/index.js +1 -1
- package/dist/esm/components/credits/creditsFaq/index.js.map +3 -3
- package/dist/esm/components/credits/creditsInfoCard/index.js +1 -1
- package/dist/esm/components/credits/creditsInfoCard/index.js.map +2 -2
- package/dist/esm/components/credits/creditsMemberPrice/CreditsMemberPrice.js +1 -1
- package/dist/esm/components/credits/creditsMemberPrice/CreditsMemberPrice.js.map +3 -3
- package/dist/esm/components/credits/creditsMemberPrice/MemberPriceItem.js +1 -1
- package/dist/esm/components/credits/creditsMemberPrice/MemberPriceItem.js.map +3 -3
- package/dist/esm/components/credits/creditsMemberPrice/Pagination.d.ts +7 -0
- package/dist/esm/components/credits/creditsMemberPrice/Pagination.js +2 -0
- package/dist/esm/components/credits/creditsMemberPrice/Pagination.js.map +7 -0
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/CountrySelect.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/CountrySelect.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/StateSelect.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/AddressForm/StateSelect.js.map +2 -2
- 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/CreditsRedeemList.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/CreditsRedeemList.js.map +3 -3
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Address.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Address.js.map +3 -3
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Success.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemProductModal/Success.js.map +2 -2
- package/dist/esm/components/credits/creditsRedeemList/RedeemableItem.js +1 -1
- package/dist/esm/components/credits/creditsRedeemList/RedeemableItem.js.map +3 -3
- package/dist/esm/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js +1 -1
- package/dist/esm/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.js.map +3 -3
- package/dist/esm/components/credits/modal/MyRewardsModal.js +1 -1
- package/dist/esm/components/credits/modal/MyRewardsModal.js.map +2 -2
- package/dist/esm/components/credits/modal/activitiesModal.js +1 -1
- package/dist/esm/components/credits/modal/activitiesModal.js.map +3 -3
- package/dist/esm/components/credits/modal/creditsUploadReceiptModal.js +1 -1
- package/dist/esm/components/credits/modal/creditsUploadReceiptModal.js.map +3 -3
- package/dist/esm/components/credits/modal/modalContainer.js +1 -1
- package/dist/esm/components/credits/modal/modalContainer.js.map +3 -3
- 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/credits/modal/tip.js +1 -1
- package/dist/esm/components/credits/modal/tip.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/components/registration/modalContainer.js +1 -1
- package/dist/esm/components/registration/modalContainer.js.map +3 -3
- package/dist/esm/constants.d.ts +1 -0
- package/dist/esm/constants.js +2 -0
- package/dist/esm/constants.js.map +7 -0
- package/dist/esm/helpers/fetchResponse.d.ts +14 -0
- package/dist/esm/helpers/fetchResponse.js +2 -0
- package/dist/esm/helpers/fetchResponse.js.map +7 -0
- package/dist/esm/helpers/fetcher.d.ts +2 -0
- package/dist/esm/helpers/fetcher.js +2 -0
- package/dist/esm/helpers/fetcher.js.map +7 -0
- package/dist/esm/helpers/index.d.ts +2 -0
- package/dist/esm/helpers/index.js +2 -0
- package/dist/esm/helpers/index.js.map +7 -0
- package/dist/esm/helpers/track.d.ts +19 -0
- package/dist/esm/helpers/track.js +2 -0
- package/dist/esm/helpers/track.js.map +7 -0
- package/dist/esm/helpers/utils.d.ts +3 -0
- package/dist/esm/helpers/utils.js +2 -0
- package/dist/esm/helpers/utils.js.map +7 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +2 -2
- package/package.json +3 -3
- package/src/components/credits/context/utils.ts +9 -0
- package/src/components/credits/creditsAnkersolixTask/CreditsAnkersolixTask.tsx +21 -18
- package/src/components/credits/creditsBenefits/BenefitItem.tsx +3 -2
- package/src/components/credits/creditsBenefits/index.tsx +1 -1
- package/src/components/credits/creditsCash/RedeemableItem.tsx +9 -4
- package/src/components/credits/creditsFaq/index.tsx +2 -1
- package/src/components/credits/creditsInfoCard/index.tsx +2 -1
- package/src/components/credits/creditsMemberPrice/CreditsMemberPrice.tsx +37 -112
- package/src/components/credits/creditsMemberPrice/MemberPriceItem.tsx +32 -9
- package/src/components/credits/creditsMemberPrice/Pagination.tsx +113 -0
- package/src/components/credits/creditsRedeemList/AddressForm/CountrySelect.tsx +2 -1
- package/src/components/credits/creditsRedeemList/AddressForm/StateSelect.tsx +2 -1
- package/src/components/credits/creditsRedeemList/AddressForm/index.tsx +2 -1
- package/src/components/credits/creditsRedeemList/CreditsRedeemList.tsx +2 -1
- package/src/components/credits/creditsRedeemList/RedeemProductModal/Address.tsx +2 -1
- package/src/components/credits/creditsRedeemList/RedeemProductModal/Success.tsx +2 -1
- package/src/components/credits/creditsRedeemList/RedeemableItem.tsx +2 -1
- package/src/components/credits/creditsWaysToGetCredits/CreditsWaysToGetCredits.tsx +14 -3
- package/src/components/credits/modal/MyRewardsModal.tsx +2 -1
- package/src/components/credits/modal/activitiesModal.tsx +2 -1
- package/src/components/credits/modal/creditsUploadReceiptModal.tsx +2 -1
- package/src/components/credits/modal/modalContainer.tsx +2 -1
- package/src/components/credits/modal/subscribeModal.tsx +2 -1
- package/src/components/credits/modal/tip.tsx +2 -1
- package/src/components/index.ts +2 -2
- package/src/components/registration/authCodeActivate/index.tsx +1 -1
- package/src/components/registration/modalContainer.tsx +2 -1
- package/src/constants.ts +1 -0
- package/src/index.ts +3 -2
- package/dist/cjs/components/credits/creditsBenefits/BenefitItem.js +0 -2
- package/dist/cjs/components/credits/creditsBenefits/BenefitItem.js.map +0 -7
- package/dist/esm/components/credits/creditsBenefits/BenefitItem.js +0 -2
- package/dist/esm/components/credits/creditsBenefits/BenefitItem.js.map +0 -7
- /package/dist/cjs/components/credits/creditsBenefits/{BenefitItem.d.ts → benefitItem.d.ts} +0 -0
- /package/dist/cjs/components/credits/creditsBenefits/{IconInfo.d.ts → iconInfo.d.ts} +0 -0
- /package/dist/cjs/components/credits/creditsBenefits/{IconInfo.js → iconInfo.js} +0 -0
- /package/dist/cjs/components/credits/creditsBenefits/{IconInfo.js.map → iconInfo.js.map} +0 -0
- /package/dist/cjs/templates/{Credits.d.ts → credits.d.ts} +0 -0
- /package/dist/cjs/templates/{Credits.js → credits.js} +0 -0
- /package/dist/cjs/templates/{Credits.js.map → credits.js.map} +0 -0
- /package/dist/esm/components/credits/creditsBenefits/{BenefitItem.d.ts → benefitItem.d.ts} +0 -0
- /package/dist/esm/components/credits/creditsBenefits/{IconInfo.d.ts → iconInfo.d.ts} +0 -0
- /package/dist/esm/components/credits/creditsBenefits/{IconInfo.js → iconInfo.js} +0 -0
- /package/dist/esm/components/credits/creditsBenefits/{IconInfo.js.map → iconInfo.js.map} +0 -0
- /package/dist/esm/templates/{Credits.d.ts → credits.d.ts} +0 -0
- /package/dist/esm/templates/{Credits.js → credits.js} +0 -0
- /package/dist/esm/templates/{Credits.js.map → credits.js.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/helpers/utils.ts"],
|
|
4
|
+
"sourcesContent": ["import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\nexport function noop(): any {}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAS,QAAAA,MAA6B,OACtC,OAAS,WAAAC,MAAe,iBAEjB,SAASC,KAAMC,EAAsB,CAC1C,OAAOF,EAAQD,EAAKG,CAAM,CAAC,CAC7B,CAEO,SAASC,GAAY,CAAC",
|
|
6
|
+
"names": ["clsx", "twMerge", "cn", "inputs", "noop"]
|
|
7
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export * from './components';
|
|
2
|
-
export * from './templates';
|
|
1
|
+
export * from './components/index.js';
|
|
2
|
+
export * from './templates/index.js';
|
|
3
|
+
export * from './constants.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export*from"./components";export*from"./templates";
|
|
1
|
+
export*from"./components/index.js";export*from"./templates/index.js";export*from"./constants.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * from './components'\nexport * from './templates'\n"],
|
|
5
|
-
"mappings": "AAAA,WAAc,
|
|
4
|
+
"sourcesContent": ["export * from './components/index.js'\nexport * from './templates/index.js'\nexport * from './constants.js'\n"],
|
|
5
|
+
"mappings": "AAAA,WAAc,wBACd,WAAc,uBACd,WAAc",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anker-in/campaign-ui",
|
|
3
|
-
"version": "0.2.11-beta.
|
|
3
|
+
"version": "0.2.11-beta.3",
|
|
4
4
|
"description": "Campaign UI components and utilities for Anker projects",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
"swiper": "^11.1.3",
|
|
89
89
|
"tailwind-merge": "^2.3.0",
|
|
90
90
|
"tailwindcss": "^3.4.3",
|
|
91
|
-
"@anker-in/
|
|
92
|
-
"@anker-in/
|
|
91
|
+
"@anker-in/lib": "1.1.2-beta.2",
|
|
92
|
+
"@anker-in/headless-ui": "1.1.25-alpha.1767516866003"
|
|
93
93
|
},
|
|
94
94
|
"publishConfig": {
|
|
95
95
|
"access": "public",
|
|
@@ -147,3 +147,12 @@ export function formatVariantPrice({
|
|
|
147
147
|
|
|
148
148
|
return { price, basePrice, discount }
|
|
149
149
|
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 提取 variant id,去掉 gid://shopify/ProductVariant/ 前缀
|
|
153
|
+
*/
|
|
154
|
+
export function extractVariantId(id: string | number | undefined): string | null {
|
|
155
|
+
if (!id) return null
|
|
156
|
+
const idStr = typeof id === 'number' ? id.toString() : id
|
|
157
|
+
return idStr.replace('gid://shopify/ProductVariant/', '')
|
|
158
|
+
}
|
|
@@ -6,10 +6,11 @@ import { useMemo, useState } from 'react'
|
|
|
6
6
|
import { TaskType, type CreditsAnkersolixTaskProps } from './type'
|
|
7
7
|
import { useActions } from '../creditsWaysToGetCredits/useActions'
|
|
8
8
|
import { useCreditsContext } from '../context/provider'
|
|
9
|
-
import { classNames as cn, useHeadlessContext
|
|
9
|
+
import { classNames as cn, useHeadlessContext } from '@anker-in/lib'
|
|
10
10
|
import { useRegistration } from '../../registration'
|
|
11
11
|
import { CreditsUploadReceiptModal } from '../modal/creditsUploadReceiptModal'
|
|
12
12
|
import { CreditsSubscribeModal } from '../modal/subscribeModal'
|
|
13
|
+
import { ROUNDED_BRANDS } from '../../../constants'
|
|
13
14
|
|
|
14
15
|
export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersolixTaskProps & { id?: string }) => {
|
|
15
16
|
const [showMore, setShowMore] = useState(false)
|
|
@@ -94,8 +95,8 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
|
|
|
94
95
|
const shouldShowMask = list.length > 3
|
|
95
96
|
|
|
96
97
|
return (
|
|
97
|
-
<Container id={id} className="
|
|
98
|
-
<Heading as="h2" size="4" html={copy.title}
|
|
98
|
+
<Container id={id} className="bg-[#F5F5F7]">
|
|
99
|
+
<Heading as="h2" size="4" html={copy.title} />
|
|
99
100
|
<div
|
|
100
101
|
className={cn(
|
|
101
102
|
'mt-[24px] p-[32px] md-l:p-[32px] md:p-[16px] relative overflow-hidden',
|
|
@@ -114,8 +115,8 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
|
|
|
114
115
|
}}
|
|
115
116
|
/>
|
|
116
117
|
{/* 副标题和装饰图部分 */}
|
|
117
|
-
<div className="flex items-center justify-between h-[560px]
|
|
118
|
-
<div className="flex flex-col gap-[8px]">
|
|
118
|
+
<div className="flex items-center justify-between xl-xxl:h-[448px] l-xl:h-[336px] h-[560px] l:h-auto md:flex-col md:items-start l:h-auto l:mb-[16px] l:flex-col-reverse l:items-start">
|
|
119
|
+
<div className="flex flex-col gap-[8px] l:mt-[8px]">
|
|
119
120
|
<Heading
|
|
120
121
|
as="h3"
|
|
121
122
|
size={4}
|
|
@@ -130,16 +131,18 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
|
|
|
130
131
|
</div>
|
|
131
132
|
</div>
|
|
132
133
|
{copy.mainImage?.url && (
|
|
133
|
-
<Picture
|
|
134
|
+
<Picture
|
|
135
|
+
className="h-full object-contain l:mx-auto md:h-auto md:w-full md-l:h-[302px]"
|
|
136
|
+
imgClassName="!h-full !object-contain"
|
|
137
|
+
source={copy.mainImage.url}
|
|
138
|
+
/>
|
|
134
139
|
)}
|
|
135
140
|
</div>
|
|
136
141
|
|
|
137
142
|
{/* 卡片列表 */}
|
|
138
|
-
<div className="relative">
|
|
143
|
+
<div className="relative mt-[24px]">
|
|
139
144
|
<motion.div
|
|
140
|
-
className={cn(
|
|
141
|
-
'grid grid-cols-3 gap-[16px] overflow-hidden md:grid-cols-1 md-l:grid-cols-2 min-md:!h-auto'
|
|
142
|
-
)}
|
|
145
|
+
className={cn('grid grid-cols-3 gap-[16px] overflow-hidden md:grid-cols-1 md-l:grid-cols-2 min-md:!h-auto')}
|
|
143
146
|
initial={{ height: shouldShowMask ? 512 : 'auto' }}
|
|
144
147
|
animate={{ height: showMore || !shouldShowMask ? 'auto' : 512 }}
|
|
145
148
|
transition={{ duration: 0.3 }}
|
|
@@ -156,27 +159,27 @@ export const CreditsAnkersolixTask = ({ copy, classNames, id }: CreditsAnkersoli
|
|
|
156
159
|
<div
|
|
157
160
|
key={item.id}
|
|
158
161
|
className={cn(
|
|
159
|
-
'flex min-h-[241px] xl-xxl:min-h-[192px] l:min-h-[160px] l-xl:min-h-[170px] flex-col justify-between bg-white p-[32px]
|
|
160
|
-
rounded ? '' : ''
|
|
162
|
+
'flex min-h-[241px] xl-xxl:min-h-[192px] l:min-h-[160px] l-xl:min-h-[170px] flex-col justify-between bg-white p-[32px] xl:p-[16px]',
|
|
163
|
+
rounded ? 'rounded-[16px]' : ''
|
|
161
164
|
)}
|
|
162
165
|
>
|
|
163
166
|
<div>
|
|
164
|
-
<
|
|
165
|
-
as="
|
|
167
|
+
<Text
|
|
168
|
+
as="p"
|
|
166
169
|
html={item.title}
|
|
167
170
|
size={2}
|
|
168
|
-
className="text-[24px] font-bold
|
|
171
|
+
className="text-pretty text-[24px] font-bold xxl:text-[20px]"
|
|
169
172
|
/>
|
|
170
|
-
<div className="mt-[8px] flex items-center
|
|
173
|
+
<div className="mt-[8px] l:mt-[4px] flex items-center">
|
|
171
174
|
<Picture
|
|
172
|
-
className="size-[24px] [&_path]:size-full"
|
|
175
|
+
className="size-[24px] xxl:size-[18px] [&_path]:size-full"
|
|
173
176
|
source="https://cdn.shopify.com/s/files/1/0511/6346/3874/files/20250902-153351.png?v=1756798450"
|
|
174
177
|
/>
|
|
175
178
|
<Text
|
|
176
179
|
as="p"
|
|
177
180
|
html={item.credits}
|
|
178
181
|
size={2}
|
|
179
|
-
className="
|
|
182
|
+
className="ml-[4px] mt-[6px] text-[18px] xxl:text-[14px]"
|
|
180
183
|
/>
|
|
181
184
|
</div>
|
|
182
185
|
</div>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Heading, Picture, Text } from '@anker-in/headless-ui'
|
|
2
|
-
import { classNames as cn, useHeadlessContext
|
|
2
|
+
import { classNames as cn, useHeadlessContext } from '@anker-in/lib'
|
|
3
3
|
import IconInfo from './IconInfo'
|
|
4
|
+
import { ROUNDED_BRANDS } from '../../../constants'
|
|
4
5
|
|
|
5
6
|
export interface BenefitItemCopy {
|
|
6
7
|
icon: {
|
|
@@ -60,7 +61,7 @@ const BenefitItem = ({
|
|
|
60
61
|
<div className="flex flex-col">
|
|
61
62
|
<Picture className={iconSizeClass} alt={item.icon?.alt} source={item.icon?.url} />
|
|
62
63
|
<div className="flex items-center">
|
|
63
|
-
<Heading html={item.text} size="2" className="break-all" />
|
|
64
|
+
<Heading html={item.text} size="2" className="break-all md-l:line-clamp-3" />
|
|
64
65
|
{item.note && (
|
|
65
66
|
<div
|
|
66
67
|
role="button"
|
|
@@ -47,7 +47,7 @@ export const CreditsBenefits = ({ copy, id }: { copy: CreditsBenefitsCopy; id?:
|
|
|
47
47
|
return (
|
|
48
48
|
<Container id={id} className="!z-[30] bg-[#F5F5F7]">
|
|
49
49
|
<Heading as="h2" size="4" html={copy?.title} />
|
|
50
|
-
<div className="mt-[24px] grid grid-cols-4
|
|
50
|
+
<div className="mt-[24px] grid grid-cols-4 gap-[16px] l:hidden items-stretch">
|
|
51
51
|
{copy.benefits.map((item, index) => (
|
|
52
52
|
<BenefitItem
|
|
53
53
|
key={index}
|
|
@@ -4,9 +4,10 @@ import { useMemo, useState } from 'react'
|
|
|
4
4
|
import { CreditsCashCopy, RedeemItem } from './type'
|
|
5
5
|
import { useCreditsContext } from '../context/provider'
|
|
6
6
|
import { useRedeemAndBuy } from '../context/hooks/useRedeemAndBuy'
|
|
7
|
-
import { formatPrice, numberFormat } from '../context/utils'
|
|
8
|
-
import { gaTrack, classNames as cn,
|
|
7
|
+
import { formatPrice, numberFormat, extractVariantId } from '../context/utils'
|
|
8
|
+
import { gaTrack, classNames as cn, useHeadlessContext } from '@anker-in/lib'
|
|
9
9
|
import { useRegistration } from '../../../components/registration'
|
|
10
|
+
import { ROUNDED_BRANDS } from '../../../constants'
|
|
10
11
|
|
|
11
12
|
function RedeemableItem({
|
|
12
13
|
copy,
|
|
@@ -112,13 +113,17 @@ function RedeemableItem({
|
|
|
112
113
|
return (
|
|
113
114
|
<div
|
|
114
115
|
className={cn(
|
|
115
|
-
'flex flex-col items-center rounded-[16px] bg-[#EAEAEC]
|
|
116
|
+
'flex flex-col items-center rounded-[16px] bg-[#EAEAEC] md:rounded-[12px] p-[24px] l:p-[8px] md-xl:p-[16px]',
|
|
116
117
|
!rounded && 'rounded-none md:rounded-none',
|
|
117
118
|
className
|
|
118
119
|
)}
|
|
119
120
|
>
|
|
120
121
|
<a
|
|
121
|
-
href={
|
|
122
|
+
href={
|
|
123
|
+
extractVariantId(itemData.productVariant?.id)
|
|
124
|
+
? `/products/${itemData.product.handle}?variant=${extractVariantId(itemData.productVariant?.id)}`
|
|
125
|
+
: `/products/${itemData.product.handle}`
|
|
126
|
+
}
|
|
122
127
|
className={cn('relative mx-auto h-[224px] w-fit l:h-[120px] l-xxl:h-[138px]')}
|
|
123
128
|
>
|
|
124
129
|
<Picture
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Container, Heading, Tabs, TabsList, TabsTrigger, Text } from '@anker-in/headless-ui'
|
|
2
|
-
import { classNames as cn, useHeadlessContext
|
|
2
|
+
import { classNames as cn, useHeadlessContext } from '@anker-in/lib'
|
|
3
3
|
import { useMemo, useState } from 'react'
|
|
4
4
|
|
|
5
5
|
import { FaqItem } from './faqItem/FaqItem'
|
|
6
|
+
import { ROUNDED_BRANDS } from '../../../constants'
|
|
6
7
|
|
|
7
8
|
export type CreditsFaqCopy = {
|
|
8
9
|
title: string
|
|
@@ -5,7 +5,8 @@ import { useCreditsContext } from '../context/provider'
|
|
|
5
5
|
import { numberFormat } from '../context/utils'
|
|
6
6
|
import ActivitiesModal from '../modal/activitiesModal'
|
|
7
7
|
import MyRewardsModal from '../modal/MyRewardsModal'
|
|
8
|
-
import { gaNormalClick, classNames as cn, useHeadlessContext
|
|
8
|
+
import { gaNormalClick, classNames as cn, useHeadlessContext } from '@anker-in/lib'
|
|
9
|
+
import { ROUNDED_BRANDS } from '../../../constants'
|
|
9
10
|
|
|
10
11
|
type ButtonConfig = {
|
|
11
12
|
text: string
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Container, Heading, Tabs, TabsList, TabsTrigger } from '@anker-in/headless-ui'
|
|
2
|
-
import { useMemo, useState, useEffect, useCallback } from 'react'
|
|
2
|
+
import { useMemo, useState, useEffect, useCallback, useRef } from 'react'
|
|
3
3
|
import Decimal from 'decimal.js'
|
|
4
4
|
|
|
5
5
|
import MemberPriceItem from './MemberPriceItem'
|
|
6
6
|
import RedeemableItem from '../creditsCash/RedeemableItem'
|
|
7
7
|
import useRedeemableList from '../context/hooks/useRedeemableList'
|
|
8
8
|
import RulesModal from '../modal/rulesModal'
|
|
9
|
+
import { Pagination } from './Pagination'
|
|
9
10
|
import { useProductsByHandles } from '@anker-in/lib'
|
|
10
11
|
import { CreditsMemberPriceCopy, MemberPriceProduct } from './type'
|
|
11
12
|
import { Product, classNames as cn } from '@anker-in/lib'
|
|
@@ -20,6 +21,7 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
|
|
|
20
21
|
const [itemsPerPage, setItemsPerPage] = useState(9) // 默认 1024px 以上:3列 × 3行 = 9
|
|
21
22
|
const { redeemableList } = useRedeemableList()
|
|
22
23
|
const { pageCommon, memberPriceDiscount } = useCreditsContext()
|
|
24
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
23
25
|
|
|
24
26
|
console.log('copy in CreditsMemberPrice', copy)
|
|
25
27
|
|
|
@@ -35,11 +37,17 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
|
|
|
35
37
|
useEffect(() => {
|
|
36
38
|
const updateItemsPerPage = () => {
|
|
37
39
|
const width = window.innerWidth
|
|
38
|
-
if (width >=
|
|
39
|
-
//
|
|
40
|
+
if (width >= 1440) {
|
|
41
|
+
// 1920px 以上:4列 × 3行 = 12个
|
|
42
|
+
setItemsPerPage(12)
|
|
43
|
+
} else if (width >= 1024) {
|
|
44
|
+
// 1024px - 1919px:3列 × 3行 = 9个
|
|
40
45
|
setItemsPerPage(9)
|
|
46
|
+
} else if (width >= 768) {
|
|
47
|
+
// 1024px 以下:3列 × 4行 = 12个
|
|
48
|
+
setItemsPerPage(12)
|
|
41
49
|
} else {
|
|
42
|
-
//
|
|
50
|
+
// 768px 以下:2列 × 4行 = 8个
|
|
43
51
|
setItemsPerPage(8)
|
|
44
52
|
}
|
|
45
53
|
}
|
|
@@ -208,115 +216,24 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
|
|
|
208
216
|
}
|
|
209
217
|
}, [redeemList, currentPage, itemsPerPage])
|
|
210
218
|
|
|
211
|
-
//
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (i === 1 || i === totalPages || (i >= currentPage - delta && i <= currentPage + delta)) {
|
|
223
|
-
range.push(i)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
let prev = 0
|
|
228
|
-
for (const i of range) {
|
|
229
|
-
if (prev && i - prev > 1) {
|
|
230
|
-
rangeWithDots.push('...')
|
|
231
|
-
}
|
|
232
|
-
rangeWithDots.push(i)
|
|
233
|
-
prev = i
|
|
219
|
+
// 处理页面切换,滚动到模块顶部
|
|
220
|
+
const handlePageChange = useCallback(
|
|
221
|
+
(page: number) => {
|
|
222
|
+
setCurrentPage(page)
|
|
223
|
+
// 滚动到模块顶部
|
|
224
|
+
if (containerRef.current) {
|
|
225
|
+
const top = containerRef.current.offsetTop
|
|
226
|
+
window.scrollTo({
|
|
227
|
+
top: top - 80, // 减去 80px 的偏移量,避免被固定头部遮挡
|
|
228
|
+
behavior: 'smooth',
|
|
229
|
+
})
|
|
234
230
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const pages = getPageNumbers()
|
|
240
|
-
|
|
241
|
-
return (
|
|
242
|
-
<div className="mt-[32px] flex items-center justify-center gap-[8px]">
|
|
243
|
-
{/* 上一页按钮 */}
|
|
244
|
-
<button
|
|
245
|
-
onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
|
|
246
|
-
disabled={currentPage === 1}
|
|
247
|
-
className={cn(
|
|
248
|
-
'flex size-[32px] xl:size-[24px] items-center justify-center overflow-hidden bg-white',
|
|
249
|
-
currentPage === 1 && 'cursor-not-allowed opacity-50'
|
|
250
|
-
)}
|
|
251
|
-
>
|
|
252
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
253
|
-
<path
|
|
254
|
-
d="M10 12L6 8L10 4"
|
|
255
|
-
stroke={currentPage === 1 ? '#767880' : '#080A0F'}
|
|
256
|
-
strokeWidth="1.5"
|
|
257
|
-
strokeLinecap="round"
|
|
258
|
-
strokeLinejoin="round"
|
|
259
|
-
/>
|
|
260
|
-
</svg>
|
|
261
|
-
</button>
|
|
262
|
-
|
|
263
|
-
{/* 页码按钮 */}
|
|
264
|
-
{pages.map((page, index) => {
|
|
265
|
-
if (page === '...') {
|
|
266
|
-
return (
|
|
267
|
-
<div
|
|
268
|
-
key={`ellipsis-${index}`}
|
|
269
|
-
className="flex size-[32px] xl:size-[24px] items-center justify-center overflow-hidden bg-white"
|
|
270
|
-
>
|
|
271
|
-
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
272
|
-
<circle cx="4.5" cy="10" r="1.25" fill="#2A2C32" />
|
|
273
|
-
<circle cx="10" cy="10" r="1.25" fill="#2A2C32" />
|
|
274
|
-
<circle cx="15.5" cy="10" r="1.25" fill="#2A2C32" />
|
|
275
|
-
</svg>
|
|
276
|
-
</div>
|
|
277
|
-
)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const isActive = currentPage === page
|
|
281
|
-
return (
|
|
282
|
-
<button
|
|
283
|
-
key={page}
|
|
284
|
-
onClick={() => setCurrentPage(page as number)}
|
|
285
|
-
className={cn(
|
|
286
|
-
'flex size-[32px] xl:size-[24px] pt-[4px] items-center justify-center overflow-hidden text-[16px] xl:text-[14px] font-bold leading-[1.4] tracking-[-0.28px]',
|
|
287
|
-
isActive ? 'bg-[#080a0f] text-white' : 'bg-white text-[#080a0f]'
|
|
288
|
-
)}
|
|
289
|
-
>
|
|
290
|
-
{page}
|
|
291
|
-
</button>
|
|
292
|
-
)
|
|
293
|
-
})}
|
|
294
|
-
|
|
295
|
-
{/* 下一页按钮 */}
|
|
296
|
-
<button
|
|
297
|
-
onClick={() => setCurrentPage(prev => Math.min(totalPages, prev + 1))}
|
|
298
|
-
disabled={currentPage === totalPages}
|
|
299
|
-
className={cn(
|
|
300
|
-
'flex size-[32px] xl:size-[24px] items-center justify-center overflow-hidden bg-white',
|
|
301
|
-
currentPage === totalPages && 'cursor-not-allowed opacity-50'
|
|
302
|
-
)}
|
|
303
|
-
>
|
|
304
|
-
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
305
|
-
<path
|
|
306
|
-
d="M6 4L10 8L6 12"
|
|
307
|
-
stroke={currentPage === totalPages ? '#767880' : '#080A0F'}
|
|
308
|
-
strokeWidth="1.5"
|
|
309
|
-
strokeLinecap="round"
|
|
310
|
-
strokeLinejoin="round"
|
|
311
|
-
/>
|
|
312
|
-
</svg>
|
|
313
|
-
</button>
|
|
314
|
-
</div>
|
|
315
|
-
)
|
|
316
|
-
}
|
|
231
|
+
},
|
|
232
|
+
[setCurrentPage]
|
|
233
|
+
)
|
|
317
234
|
|
|
318
235
|
return (
|
|
319
|
-
<Container id={id} className={cn('bg-[#F5F5F5]')}>
|
|
236
|
+
<Container id={id} className={cn('bg-[#F5F5F5]')} ref={containerRef}>
|
|
320
237
|
<Heading as="h2" size="4" html={copy.title} className="mx:px-[16px]" />
|
|
321
238
|
|
|
322
239
|
<Tabs
|
|
@@ -344,7 +261,11 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
|
|
|
344
261
|
<MemberPriceItem key={index} itemData={item} copy={copy.memberPriceTab} />
|
|
345
262
|
))}
|
|
346
263
|
</div>
|
|
347
|
-
|
|
264
|
+
<Pagination
|
|
265
|
+
currentPage={currentPage}
|
|
266
|
+
totalPages={memberPricePagination.totalPages}
|
|
267
|
+
onPageChange={handlePageChange}
|
|
268
|
+
/>
|
|
348
269
|
</>
|
|
349
270
|
)}
|
|
350
271
|
|
|
@@ -365,7 +286,11 @@ export const CreditsMemberPrice = ({ copy, id }: { copy: CreditsMemberPriceCopy;
|
|
|
365
286
|
/>
|
|
366
287
|
))}
|
|
367
288
|
</div>
|
|
368
|
-
|
|
289
|
+
<Pagination
|
|
290
|
+
currentPage={currentPage}
|
|
291
|
+
totalPages={redeemPagination.totalPages}
|
|
292
|
+
onPageChange={handlePageChange}
|
|
293
|
+
/>
|
|
369
294
|
</>
|
|
370
295
|
)}
|
|
371
296
|
</div>
|
|
@@ -2,9 +2,10 @@ import { Button, Text, Picture } from '@anker-in/headless-ui'
|
|
|
2
2
|
import { useMemo } from 'react'
|
|
3
3
|
|
|
4
4
|
import { CreditsMemberPriceCopy, MemberPriceProduct } from './type'
|
|
5
|
-
import { formatPrice } from '../context/utils'
|
|
6
|
-
import { classNames as cn,
|
|
5
|
+
import { formatPrice, extractVariantId } from '../context/utils'
|
|
6
|
+
import { classNames as cn, useHeadlessContext, useBuyNow } from '@anker-in/lib'
|
|
7
7
|
import { useCreditsContext } from '../context/provider'
|
|
8
|
+
import { ROUNDED_BRANDS } from '../../../constants'
|
|
8
9
|
|
|
9
10
|
function MemberPriceItem({
|
|
10
11
|
itemData,
|
|
@@ -16,7 +17,7 @@ function MemberPriceItem({
|
|
|
16
17
|
className?: string
|
|
17
18
|
}) {
|
|
18
19
|
const { brand, locale } = useHeadlessContext()
|
|
19
|
-
const { profile } = useCreditsContext()
|
|
20
|
+
const { profile, openSignUpPopup } = useCreditsContext()
|
|
20
21
|
const rounded = ROUNDED_BRANDS.includes(brand)
|
|
21
22
|
|
|
22
23
|
// 使用 buyNow hook 来处理结算
|
|
@@ -26,13 +27,28 @@ function MemberPriceItem({
|
|
|
26
27
|
return itemData.productVariant?.availableForSale
|
|
27
28
|
}, [itemData.productVariant?.availableForSale])
|
|
28
29
|
|
|
30
|
+
const isLogin = useMemo(() => {
|
|
31
|
+
return !!profile
|
|
32
|
+
}, [profile])
|
|
33
|
+
|
|
29
34
|
// Learn More 按钮点击 - 跳转到产品详情页
|
|
30
35
|
const handleLearnMore = () => {
|
|
31
|
-
|
|
36
|
+
const variantId = extractVariantId(itemData.productVariant?.id)
|
|
37
|
+
const url = variantId
|
|
38
|
+
? `/products/${itemData.product.handle}?variant=${variantId}`
|
|
39
|
+
: `/products/${itemData.product.handle}`
|
|
40
|
+
window.location.href = url
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
// Shop Now 按钮点击 -
|
|
43
|
+
// Shop Now 按钮点击 - 检查登录状态后使用 buyNow 进行结算
|
|
35
44
|
const handleShopNow = () => {
|
|
45
|
+
// 如果未登录,弹出登录弹窗
|
|
46
|
+
if (!isLogin) {
|
|
47
|
+
openSignUpPopup()
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 已登录,执行购买
|
|
36
52
|
buyNow({
|
|
37
53
|
customAttributes: [
|
|
38
54
|
{
|
|
@@ -52,7 +68,7 @@ function MemberPriceItem({
|
|
|
52
68
|
return (
|
|
53
69
|
<div
|
|
54
70
|
className={cn(
|
|
55
|
-
'relative flex flex-col items-center bg-[#EAEAEC] p-[16px] md:rounded-[12px]',
|
|
71
|
+
'relative flex flex-col items-center bg-[#EAEAEC] p-[24px] l:p-[8px] rounded-[16px] md-xl:p-[16px] md:rounded-[12px]',
|
|
56
72
|
!rounded && 'rounded-none md:rounded-none',
|
|
57
73
|
className
|
|
58
74
|
)}
|
|
@@ -68,7 +84,14 @@ function MemberPriceItem({
|
|
|
68
84
|
)}
|
|
69
85
|
|
|
70
86
|
{/* 产品图片 - 优先使用产品的 metafields 透明图 */}
|
|
71
|
-
<a
|
|
87
|
+
<a
|
|
88
|
+
href={
|
|
89
|
+
extractVariantId(itemData.productVariant?.id)
|
|
90
|
+
? `/products/${itemData.product.handle}?variant=${extractVariantId(itemData.productVariant?.id)}`
|
|
91
|
+
: `/products/${itemData.product.handle}`
|
|
92
|
+
}
|
|
93
|
+
className={cn('relative mx-auto size-[138px]')}
|
|
94
|
+
>
|
|
72
95
|
<Picture
|
|
73
96
|
className="mx-auto size-full"
|
|
74
97
|
imgClassName="object-contain"
|
|
@@ -81,7 +104,7 @@ function MemberPriceItem({
|
|
|
81
104
|
</a>
|
|
82
105
|
|
|
83
106
|
{/* 产品信息 */}
|
|
84
|
-
<div className={cn('mt-[
|
|
107
|
+
<div className={cn('mt-[10px] xl:mt-[8px] w-full')}>
|
|
85
108
|
{/* 产品标题 - 使用产品的真实标题 */}
|
|
86
109
|
<Text
|
|
87
110
|
html={itemData?.product?.title}
|
|
@@ -125,7 +148,7 @@ function MemberPriceItem({
|
|
|
125
148
|
</div>
|
|
126
149
|
|
|
127
150
|
{/* 按钮组 */}
|
|
128
|
-
<div className="flex w-full gap-[8px]
|
|
151
|
+
<div className="flex w-full gap-[8px] l:flex-col">
|
|
129
152
|
{/* Learn More 按钮 */}
|
|
130
153
|
<Button
|
|
131
154
|
variant="secondary"
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { classNames as cn } from '@anker-in/lib'
|
|
2
|
+
|
|
3
|
+
interface PaginationProps {
|
|
4
|
+
currentPage: number
|
|
5
|
+
totalPages: number
|
|
6
|
+
onPageChange: (page: number) => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function Pagination({ currentPage, totalPages, onPageChange }: PaginationProps) {
|
|
10
|
+
if (totalPages <= 1) return null
|
|
11
|
+
|
|
12
|
+
// 计算要显示的页码
|
|
13
|
+
const getPageNumbers = () => {
|
|
14
|
+
const delta = 2 // 当前页前后显示的页码数量
|
|
15
|
+
const range = []
|
|
16
|
+
const rangeWithDots = []
|
|
17
|
+
|
|
18
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
19
|
+
if (i === 1 || i === totalPages || (i >= currentPage - delta && i <= currentPage + delta)) {
|
|
20
|
+
range.push(i)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let prev = 0
|
|
25
|
+
for (const i of range) {
|
|
26
|
+
if (prev && i - prev > 1) {
|
|
27
|
+
rangeWithDots.push('...')
|
|
28
|
+
}
|
|
29
|
+
rangeWithDots.push(i)
|
|
30
|
+
prev = i
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return rangeWithDots
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const pages = getPageNumbers()
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className="mt-[32px] flex items-center justify-center gap-[8px]">
|
|
40
|
+
{/* 上一页按钮 */}
|
|
41
|
+
<button
|
|
42
|
+
onClick={() => onPageChange(Math.max(1, currentPage - 1))}
|
|
43
|
+
disabled={currentPage === 1}
|
|
44
|
+
className={cn(
|
|
45
|
+
'flex size-[32px] xl:size-[24px] items-center justify-center overflow-hidden bg-white',
|
|
46
|
+
currentPage === 1 && 'cursor-not-allowed opacity-50'
|
|
47
|
+
)}
|
|
48
|
+
>
|
|
49
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
50
|
+
<path
|
|
51
|
+
d="M10 12L6 8L10 4"
|
|
52
|
+
stroke={currentPage === 1 ? '#767880' : '#080A0F'}
|
|
53
|
+
strokeWidth="1.5"
|
|
54
|
+
strokeLinecap="round"
|
|
55
|
+
strokeLinejoin="round"
|
|
56
|
+
/>
|
|
57
|
+
</svg>
|
|
58
|
+
</button>
|
|
59
|
+
|
|
60
|
+
{/* 页码按钮 */}
|
|
61
|
+
{pages.map((page, index) => {
|
|
62
|
+
if (page === '...') {
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
key={`ellipsis-${index}`}
|
|
66
|
+
className="flex size-[32px] xl:size-[24px] items-center justify-center overflow-hidden bg-white"
|
|
67
|
+
>
|
|
68
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
69
|
+
<circle cx="4.5" cy="10" r="1.25" fill="#2A2C32" />
|
|
70
|
+
<circle cx="10" cy="10" r="1.25" fill="#2A2C32" />
|
|
71
|
+
<circle cx="15.5" cy="10" r="1.25" fill="#2A2C32" />
|
|
72
|
+
</svg>
|
|
73
|
+
</div>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const isActive = currentPage === page
|
|
78
|
+
return (
|
|
79
|
+
<button
|
|
80
|
+
key={page}
|
|
81
|
+
onClick={() => onPageChange(page as number)}
|
|
82
|
+
className={cn(
|
|
83
|
+
'flex size-[32px] xl:size-[24px] pt-[4px] items-center justify-center overflow-hidden text-[16px] xl:text-[14px] font-bold leading-[1.4] tracking-[-0.28px]',
|
|
84
|
+
isActive ? 'bg-[#080a0f] text-white' : 'bg-white text-[#080a0f]'
|
|
85
|
+
)}
|
|
86
|
+
>
|
|
87
|
+
{page}
|
|
88
|
+
</button>
|
|
89
|
+
)
|
|
90
|
+
})}
|
|
91
|
+
|
|
92
|
+
{/* 下一页按钮 */}
|
|
93
|
+
<button
|
|
94
|
+
onClick={() => onPageChange(Math.min(totalPages, currentPage + 1))}
|
|
95
|
+
disabled={currentPage === totalPages}
|
|
96
|
+
className={cn(
|
|
97
|
+
'flex size-[32px] xl:size-[24px] items-center justify-center overflow-hidden bg-white',
|
|
98
|
+
currentPage === totalPages && 'cursor-not-allowed opacity-50'
|
|
99
|
+
)}
|
|
100
|
+
>
|
|
101
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
102
|
+
<path
|
|
103
|
+
d="M6 4L10 8L6 12"
|
|
104
|
+
stroke={currentPage === totalPages ? '#767880' : '#080A0F'}
|
|
105
|
+
strokeWidth="1.5"
|
|
106
|
+
strokeLinecap="round"
|
|
107
|
+
strokeLinejoin="round"
|
|
108
|
+
/>
|
|
109
|
+
</svg>
|
|
110
|
+
</button>
|
|
111
|
+
</div>
|
|
112
|
+
)
|
|
113
|
+
}
|