@anker-in/campaign-ui 0.5.0-beta.5 → 0.5.0-beta.7
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/memberPopup/MemberPopup.js +1 -1
- package/dist/cjs/components/memberPopup/MemberPopup.js.map +2 -2
- package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.js +1 -1
- package/dist/cjs/components/memberPopup/panels/ActivitiesSubscribePanel.js.map +2 -2
- package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.d.ts +2 -1
- package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js +1 -1
- package/dist/cjs/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js.map +3 -3
- package/dist/cjs/components/memberPopup/panels/ConsumeCredits/index.js +1 -1
- package/dist/cjs/components/memberPopup/panels/ConsumeCredits/index.js.map +2 -2
- package/dist/esm/components/memberPopup/MemberPopup.js +1 -1
- package/dist/esm/components/memberPopup/MemberPopup.js.map +2 -2
- package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.js +1 -1
- package/dist/esm/components/memberPopup/panels/ActivitiesSubscribePanel.js.map +3 -3
- package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.d.ts +2 -1
- package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js +1 -1
- package/dist/esm/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.js.map +3 -3
- package/dist/esm/components/memberPopup/panels/ConsumeCredits/index.js +1 -1
- package/dist/esm/components/memberPopup/panels/ConsumeCredits/index.js.map +2 -2
- package/package.json +1 -1
- package/src/components/memberPopup/MemberPopup.tsx +1 -0
- package/src/components/memberPopup/panels/ActivitiesSubscribePanel.tsx +25 -29
- package/src/components/memberPopup/panels/ConsumeCredits/RedeemCouponPanel.tsx +61 -28
- package/src/components/memberPopup/panels/ConsumeCredits/index.tsx +2 -1
- package/src/components/memberPopup/panels/ConsumeCredits/RedeemCouponModal.tsx +0 -150
|
@@ -14,6 +14,7 @@ type Props = {
|
|
|
14
14
|
itemImage?: { url: string; alt?: string }
|
|
15
15
|
itemValue?: string
|
|
16
16
|
itemOff?: string
|
|
17
|
+
itemRules?: string[]
|
|
17
18
|
redeemId: number
|
|
18
19
|
userId?: string
|
|
19
20
|
copy: RedeemCouponModalCopy
|
|
@@ -29,6 +30,7 @@ export default function RedeemCouponPanel({
|
|
|
29
30
|
itemImage,
|
|
30
31
|
itemValue,
|
|
31
32
|
itemOff,
|
|
33
|
+
itemRules,
|
|
32
34
|
redeemId,
|
|
33
35
|
userId,
|
|
34
36
|
copy,
|
|
@@ -80,38 +82,45 @@ export default function RedeemCouponPanel({
|
|
|
80
82
|
setDisabled(false)
|
|
81
83
|
}, [redeemId])
|
|
82
84
|
|
|
85
|
+
const rulesSection = itemRules && itemRules.length > 0 && (
|
|
86
|
+
<div className="w-full text-[16px] font-bold leading-[1.4] text-[#6D6D6F] md:mt-[12px] md:text-[14px]">
|
|
87
|
+
<ul className="ml-4 grid grid-flow-row gap-[4px]">
|
|
88
|
+
{itemRules?.map((text, index) => (
|
|
89
|
+
<li className="list-disc" key={index}>
|
|
90
|
+
<Text html={text} className="font-bold" />
|
|
91
|
+
</li>
|
|
92
|
+
))}
|
|
93
|
+
</ul>
|
|
94
|
+
</div>
|
|
95
|
+
)
|
|
96
|
+
|
|
83
97
|
return (
|
|
84
|
-
<div className="flex flex-col
|
|
98
|
+
<div className="flex flex-col">
|
|
85
99
|
{itemImage?.url && (
|
|
86
|
-
<div className=
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
<div className="relative w-full px-[24px]">
|
|
101
|
+
<div className={cn('relative mx-auto overflow-hidden', rounded ? 'rounded-[8px]' : 'rounded-none')}>
|
|
102
|
+
<img src={itemImage.url} alt={itemImage.alt ?? ''} className="mx-auto h-[140px] w-full object-cover" />
|
|
103
|
+
{itemValue && (
|
|
104
|
+
<div className="absolute bottom-[20px] left-[20px] text-[32px] font-[800] leading-none text-white">
|
|
105
|
+
{itemValue}
|
|
106
|
+
{itemOff ? ` ${itemOff}` : ''}
|
|
107
|
+
</div>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
94
110
|
</div>
|
|
95
111
|
)}
|
|
96
112
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<Text className="block text-[20px] font-[700]" html={copy.confirmTitle} />
|
|
104
|
-
<Button
|
|
105
|
-
className={cn('w-full py-[12px] text-[14px] font-[700] text-white disabled:opacity-60 bg-[#080a0f]', rounded ? 'rounded-[4px]' : 'rounded-none')}
|
|
106
|
-
disabled={disabled}
|
|
107
|
-
loading={loading}
|
|
108
|
-
onClick={handleConfirm}
|
|
109
|
-
>
|
|
110
|
-
{copy.confirmButton}
|
|
111
|
-
</Button>
|
|
113
|
+
{!couponCode && (
|
|
114
|
+
<div className="flex flex-col gap-[16px] px-[24px] py-[20px]">
|
|
115
|
+
<p className="text-center text-[24px] font-[700] text-[#1d1d1f]">
|
|
116
|
+
{itemCredits} {pointUnit}
|
|
117
|
+
</p>
|
|
118
|
+
{rulesSection}
|
|
112
119
|
</div>
|
|
113
|
-
)
|
|
114
|
-
|
|
120
|
+
)}
|
|
121
|
+
|
|
122
|
+
{couponCode && (
|
|
123
|
+
<div className="flex mt-[16px] flex-col gap-[8px] text-center">
|
|
115
124
|
<div className="flex items-center justify-center gap-[10px]">
|
|
116
125
|
<span className="text-[24px] font-[700]">{couponCode}</span>
|
|
117
126
|
<button
|
|
@@ -125,7 +134,10 @@ export default function RedeemCouponPanel({
|
|
|
125
134
|
<Text className="text-[20px] font-[700]" html={copy.successTitle} />
|
|
126
135
|
<Text className="text-[14px] font-[700] text-[#6d6d6f]" html={copy.successDesc} />
|
|
127
136
|
<Button
|
|
128
|
-
className={cn(
|
|
137
|
+
className={cn(
|
|
138
|
+
'w-full py-[12px] text-[14px] font-[700] text-white bg-[#080a0f]',
|
|
139
|
+
rounded ? 'rounded-[4px]' : 'rounded-none'
|
|
140
|
+
)}
|
|
129
141
|
onClick={() => {
|
|
130
142
|
if (copy.successButtonUrl) window.location.href = copy.successButtonUrl
|
|
131
143
|
onClose()
|
|
@@ -136,7 +148,28 @@ export default function RedeemCouponPanel({
|
|
|
136
148
|
</div>
|
|
137
149
|
)}
|
|
138
150
|
|
|
139
|
-
{
|
|
151
|
+
{!couponCode && (
|
|
152
|
+
<div className="sticky bottom-0 bg-white border-t border-[#e5e5e5] pt-[10px]">
|
|
153
|
+
<div className="flex flex-col gap-[8px] text-center">
|
|
154
|
+
<Text className="block text-[16px] font-[700] leading-[1.3]" html={copy.confirmTitle} />
|
|
155
|
+
<Button
|
|
156
|
+
className={cn(
|
|
157
|
+
'w-full py-[12px] text-[14px] font-[700] text-white disabled:opacity-60 bg-[#080a0f]',
|
|
158
|
+
rounded ? 'rounded-[4px]' : 'rounded-none'
|
|
159
|
+
)}
|
|
160
|
+
disabled={disabled}
|
|
161
|
+
loading={loading}
|
|
162
|
+
onClick={handleConfirm}
|
|
163
|
+
>
|
|
164
|
+
{copy.confirmButton}
|
|
165
|
+
</Button>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
{errorInfo && (
|
|
169
|
+
<Text className="mt-[8px] text-center text-[14px] font-[700] text-[#ff0000]" html={errorInfo} />
|
|
170
|
+
)}
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
140
173
|
</div>
|
|
141
174
|
)
|
|
142
175
|
}
|
|
@@ -116,6 +116,7 @@ function ConsumeCredits({ copy, onClose }: Props) {
|
|
|
116
116
|
: item.image,
|
|
117
117
|
itemValue: item.value,
|
|
118
118
|
itemOff: copy.off,
|
|
119
|
+
itemRules: item.rules,
|
|
119
120
|
redeemId: Number(item.redeemId),
|
|
120
121
|
userId: profile?.user_id,
|
|
121
122
|
alpcConfig,
|
|
@@ -183,7 +184,7 @@ function ConsumeCredits({ copy, onClose }: Props) {
|
|
|
183
184
|
imgClassName={hasProduct ? 'object-cover' : 'h-full w-auto object-contain'}
|
|
184
185
|
/>
|
|
185
186
|
{!hasProduct && item.value && (
|
|
186
|
-
<div className="absolute bottom-[
|
|
187
|
+
<div className="absolute bottom-[16px] left-[4px] text-[12px] font-[800] leading-none text-white">
|
|
187
188
|
{item.value} {copy.off}
|
|
188
189
|
</div>
|
|
189
190
|
)}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from 'react'
|
|
2
|
-
import { Button, Text } from '@anker-in/headless-ui'
|
|
3
|
-
import { classNames as cn } from '@anker-in/lib'
|
|
4
|
-
import { CreditsModalContainer } from '../../../credits/modal/ModalContainer'
|
|
5
|
-
import { AlpcErrorCode } from '../../../credits/context/const'
|
|
6
|
-
import { useRedeemCoupon } from './hooks/useRedeemCoupon'
|
|
7
|
-
import useCopy from '../../../credits/context/hooks/useCopy'
|
|
8
|
-
import type { RedeemCouponModalCopy, AlpcConfig } from '../../type'
|
|
9
|
-
|
|
10
|
-
type Props = {
|
|
11
|
-
isOpen: boolean
|
|
12
|
-
onClose: () => void
|
|
13
|
-
itemTitle: string
|
|
14
|
-
itemCredits: number
|
|
15
|
-
itemImage?: { url: string; alt?: string }
|
|
16
|
-
redeemId: number
|
|
17
|
-
userId?: string
|
|
18
|
-
copy: RedeemCouponModalCopy
|
|
19
|
-
pointUnit?: string
|
|
20
|
-
alpcConfig: AlpcConfig
|
|
21
|
-
onError?: (code: number) => void
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function RedeemCouponModal({
|
|
25
|
-
isOpen,
|
|
26
|
-
onClose,
|
|
27
|
-
itemTitle,
|
|
28
|
-
itemCredits,
|
|
29
|
-
itemImage,
|
|
30
|
-
redeemId,
|
|
31
|
-
userId,
|
|
32
|
-
copy,
|
|
33
|
-
pointUnit = 'pts',
|
|
34
|
-
alpcConfig,
|
|
35
|
-
onError,
|
|
36
|
-
}: Props) {
|
|
37
|
-
const [couponCode, setCouponCode] = useState<string>()
|
|
38
|
-
const [errorInfo, setErrorInfo] = useState('')
|
|
39
|
-
const [disabled, setDisabled] = useState(false)
|
|
40
|
-
const { copy: copyText, copied } = useCopy()
|
|
41
|
-
|
|
42
|
-
const { isMutating: loading, trigger } = useRedeemCoupon(alpcConfig)
|
|
43
|
-
|
|
44
|
-
const handleConfirm = useCallback(async () => {
|
|
45
|
-
setErrorInfo('')
|
|
46
|
-
const { data } = await trigger({ user_id: userId, rule_id: redeemId })
|
|
47
|
-
if (!data) {
|
|
48
|
-
setErrorInfo(copy.commonError)
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
if (data.data?.success) {
|
|
52
|
-
setCouponCode(data.data.coupon_code)
|
|
53
|
-
} else {
|
|
54
|
-
let msg = copy.commonError
|
|
55
|
-
if (data.code === AlpcErrorCode.CodeLpcShopifyCouponRuleRedeemLimit) {
|
|
56
|
-
msg = copy.redeemLimitError
|
|
57
|
-
setDisabled(true)
|
|
58
|
-
} else if (data.code === AlpcErrorCode.CodeLpcRuleInventoryNotEnough) {
|
|
59
|
-
msg = copy.inventoryNotEnough
|
|
60
|
-
setDisabled(true)
|
|
61
|
-
} else if (data.code === AlpcErrorCode.CodeLpcNotEnoughCredits) {
|
|
62
|
-
msg = copy.creditsNotEnough
|
|
63
|
-
setDisabled(true)
|
|
64
|
-
} else if (data.code === AlpcErrorCode.CodeCrossSiteError) {
|
|
65
|
-
msg = copy.crossSiteError
|
|
66
|
-
setDisabled(true)
|
|
67
|
-
}
|
|
68
|
-
setErrorInfo(msg)
|
|
69
|
-
onError?.(data.code)
|
|
70
|
-
}
|
|
71
|
-
}, [trigger, userId, redeemId, copy, onError])
|
|
72
|
-
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
if (!isOpen) {
|
|
75
|
-
setCouponCode(undefined)
|
|
76
|
-
setErrorInfo('')
|
|
77
|
-
setDisabled(false)
|
|
78
|
-
}
|
|
79
|
-
}, [isOpen])
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<CreditsModalContainer
|
|
83
|
-
isOpen={isOpen}
|
|
84
|
-
onClose={onClose}
|
|
85
|
-
className="w-[540px] md:h-auto"
|
|
86
|
-
scrollClassName="mb-[40px] px-0 min-l:px-0 md:mb-[24px]"
|
|
87
|
-
titleClassName="h-[56px] bg-[#f5f5f7]"
|
|
88
|
-
>
|
|
89
|
-
<div className="bg-[#f5f5f7] px-[48px] pb-[24px] md:px-[16px]">
|
|
90
|
-
{itemImage?.url && (
|
|
91
|
-
<div className="relative mx-auto h-[164px] w-[324px]">
|
|
92
|
-
<img src={itemImage.url} alt={itemImage.alt ?? ''} className="h-full w-full object-cover" />
|
|
93
|
-
</div>
|
|
94
|
-
)}
|
|
95
|
-
<p className={cn('mt-[30px] text-center text-[24px] font-bold md:mt-[18px] md:text-[20px]')}>
|
|
96
|
-
{itemCredits} {pointUnit}
|
|
97
|
-
</p>
|
|
98
|
-
</div>
|
|
99
|
-
|
|
100
|
-
<div className="bg-white px-[48px] pt-[24px] text-center md:px-[16px]">
|
|
101
|
-
{!couponCode ? (
|
|
102
|
-
<>
|
|
103
|
-
<Text className="block text-[24px] font-bold md:text-[20px]" html={copy.confirmTitle} />
|
|
104
|
-
<Button
|
|
105
|
-
loading={loading}
|
|
106
|
-
variant="primary"
|
|
107
|
-
size="lg"
|
|
108
|
-
className="mt-[16px] w-full"
|
|
109
|
-
onClick={handleConfirm}
|
|
110
|
-
disabled={disabled}
|
|
111
|
-
>
|
|
112
|
-
{copy.confirmButton}
|
|
113
|
-
</Button>
|
|
114
|
-
</>
|
|
115
|
-
) : (
|
|
116
|
-
<>
|
|
117
|
-
<div className="flex items-center justify-center gap-[10px]">
|
|
118
|
-
<span className="text-[24px] font-bold">{couponCode}</span>
|
|
119
|
-
<button
|
|
120
|
-
className={cn('text-[16px] font-bold underline', copied && 'pointer-events-none')}
|
|
121
|
-
onClick={() => copyText(couponCode)}
|
|
122
|
-
>
|
|
123
|
-
{copied ? 'Copied' : 'Copy'}
|
|
124
|
-
</button>
|
|
125
|
-
</div>
|
|
126
|
-
<Text className="mb-[4px] mt-[16px] text-[24px] font-bold md:text-[20px]" html={copy.successTitle} />
|
|
127
|
-
<Text className="text-[16px] font-bold text-[#6d6d6f] md:text-[14px]" html={copy.successDesc} />
|
|
128
|
-
<Button
|
|
129
|
-
variant="primary"
|
|
130
|
-
size="lg"
|
|
131
|
-
className="mt-[16px] w-full"
|
|
132
|
-
onClick={() => {
|
|
133
|
-
if (copy.successButtonUrl) window.location.href = copy.successButtonUrl
|
|
134
|
-
onClose()
|
|
135
|
-
}}
|
|
136
|
-
>
|
|
137
|
-
{copy.successButton}
|
|
138
|
-
</Button>
|
|
139
|
-
</>
|
|
140
|
-
)}
|
|
141
|
-
</div>
|
|
142
|
-
|
|
143
|
-
{errorInfo && (
|
|
144
|
-
<div className="bg-white px-[48px] py-[12px] text-center md:px-[16px]">
|
|
145
|
-
<Text className="text-[14px] font-semibold text-[#ff0000]" html={errorInfo} />
|
|
146
|
-
</div>
|
|
147
|
-
)}
|
|
148
|
-
</CreditsModalContainer>
|
|
149
|
-
)
|
|
150
|
-
}
|