@akinon/pz-credit-payment 2.0.0-beta.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +116 -17
- package/README.md +126 -0
- package/package.json +9 -9
- package/src/index.tsx +60 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,45 +1,144 @@
|
|
|
1
1
|
# @akinon/pz-credit-payment
|
|
2
2
|
|
|
3
|
-
## 2.0.0
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
## 2.0.0-beta.27
|
|
6
|
+
|
|
7
|
+
## 2.0.0-beta.26
|
|
8
|
+
|
|
9
|
+
## 2.0.0-beta.25
|
|
10
|
+
|
|
11
|
+
## 2.0.0-beta.24
|
|
12
|
+
|
|
13
|
+
## 2.0.0-beta.23
|
|
14
|
+
|
|
15
|
+
## 2.0.0-beta.22
|
|
16
|
+
|
|
17
|
+
## 2.0.0-beta.21
|
|
18
|
+
|
|
19
|
+
## 2.0.0-beta.20
|
|
20
|
+
|
|
21
|
+
## 1.126.0
|
|
22
|
+
|
|
23
|
+
## 1.125.2
|
|
24
|
+
|
|
25
|
+
## 1.125.1
|
|
26
|
+
|
|
27
|
+
## 1.125.0
|
|
28
|
+
|
|
29
|
+
## 1.124.0
|
|
30
|
+
|
|
31
|
+
## 1.123.0
|
|
32
|
+
|
|
33
|
+
## 1.122.0
|
|
34
|
+
|
|
35
|
+
## 1.121.0
|
|
36
|
+
|
|
37
|
+
## 1.120.0
|
|
4
38
|
|
|
5
39
|
### Minor Changes
|
|
6
40
|
|
|
7
|
-
-
|
|
41
|
+
- 6ad72e8d: ZERO-4032: Add loading state management for payment submissions across multiple components and add safe guarding
|
|
42
|
+
|
|
43
|
+
## 1.119.0
|
|
44
|
+
|
|
45
|
+
## 1.118.0
|
|
46
|
+
|
|
47
|
+
## 1.117.0
|
|
48
|
+
|
|
49
|
+
## 1.116.0
|
|
50
|
+
|
|
51
|
+
## 1.115.0
|
|
52
|
+
|
|
53
|
+
## 1.114.0
|
|
54
|
+
|
|
55
|
+
## 1.113.0
|
|
56
|
+
|
|
57
|
+
## 1.112.0
|
|
8
58
|
|
|
9
|
-
##
|
|
59
|
+
## 1.111.0
|
|
10
60
|
|
|
11
|
-
##
|
|
61
|
+
## 1.110.0
|
|
12
62
|
|
|
13
|
-
##
|
|
63
|
+
## 1.109.0
|
|
64
|
+
|
|
65
|
+
## 1.108.0
|
|
66
|
+
|
|
67
|
+
## 1.107.0
|
|
68
|
+
|
|
69
|
+
## 1.106.0
|
|
70
|
+
|
|
71
|
+
## 1.105.0
|
|
72
|
+
|
|
73
|
+
## 1.104.0
|
|
74
|
+
|
|
75
|
+
## 1.103.0
|
|
14
76
|
|
|
15
77
|
### Minor Changes
|
|
16
78
|
|
|
17
|
-
-
|
|
79
|
+
- 310556e: ZERO-3372 :Add README and enhance CreditPayment component with renderer support
|
|
18
80
|
|
|
19
|
-
##
|
|
81
|
+
## 1.102.0
|
|
20
82
|
|
|
21
|
-
##
|
|
83
|
+
## 1.101.0
|
|
22
84
|
|
|
23
|
-
##
|
|
85
|
+
## 1.100.0
|
|
24
86
|
|
|
25
|
-
##
|
|
87
|
+
## 1.99.0
|
|
26
88
|
|
|
27
89
|
### Minor Changes
|
|
28
90
|
|
|
29
|
-
-
|
|
30
|
-
|
|
91
|
+
- d58538b: ZERO-3638: Enhance RC pipeline: add fetch, merge, and pre-release setup with conditional commit
|
|
92
|
+
|
|
93
|
+
## 1.98.0
|
|
31
94
|
|
|
32
|
-
##
|
|
95
|
+
## 1.97.0
|
|
96
|
+
|
|
97
|
+
## 1.96.0
|
|
98
|
+
|
|
99
|
+
## 1.95.0
|
|
100
|
+
|
|
101
|
+
## 1.94.0
|
|
33
102
|
|
|
34
103
|
### Minor Changes
|
|
35
104
|
|
|
36
|
-
- ZERO-
|
|
105
|
+
- fec9638: ZERO-3346 :Update data-testid for Credit Payment button
|
|
106
|
+
|
|
107
|
+
## 1.93.0
|
|
108
|
+
|
|
109
|
+
## 1.92.0
|
|
110
|
+
|
|
111
|
+
## 1.91.0
|
|
112
|
+
|
|
113
|
+
## 1.90.0
|
|
114
|
+
|
|
115
|
+
## 1.89.0
|
|
116
|
+
|
|
117
|
+
## 1.88.0
|
|
118
|
+
|
|
119
|
+
## 1.87.0
|
|
120
|
+
|
|
121
|
+
## 1.86.0
|
|
122
|
+
|
|
123
|
+
## 1.85.0
|
|
124
|
+
|
|
125
|
+
## 1.84.0
|
|
126
|
+
|
|
127
|
+
## 1.83.0
|
|
128
|
+
|
|
129
|
+
## 1.82.0
|
|
130
|
+
|
|
131
|
+
## 1.81.0
|
|
132
|
+
|
|
133
|
+
## 1.80.0
|
|
134
|
+
|
|
135
|
+
## 1.79.0
|
|
37
136
|
|
|
38
|
-
##
|
|
137
|
+
## 1.78.0
|
|
39
138
|
|
|
40
|
-
|
|
139
|
+
## 1.77.0
|
|
41
140
|
|
|
42
|
-
|
|
141
|
+
## 1.76.0
|
|
43
142
|
|
|
44
143
|
## 1.75.0
|
|
45
144
|
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# @akinon/pz-credit-payment
|
|
2
|
+
|
|
3
|
+
## Installation method
|
|
4
|
+
|
|
5
|
+
You can use the following command to install the extension with the latest plugins:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
|
|
9
|
+
npx @akinon/projectzero@latest --plugins
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## CreditPayment
|
|
14
|
+
|
|
15
|
+
A customizable React component that enables customers to select a credit payment option during checkout and confirm their agreement to terms before placing the order.
|
|
16
|
+
|
|
17
|
+
### Props
|
|
18
|
+
|
|
19
|
+
#### `CreditPaymentProps`
|
|
20
|
+
|
|
21
|
+
| Prop | Type | Required | Description |
|
|
22
|
+
| --- | --- | --- | --- |
|
|
23
|
+
| `translations` | `Record<string, CreditPaymentTranslationsProps>` | Optional | Localization texts for title, button and validation message |
|
|
24
|
+
| `agreementCheckbox` | `React.ReactElement` | Required | A controlled checkbox React element (e.g., terms agreement checkbox) |
|
|
25
|
+
| `titleClassName` | `string` | Optional | Optional custom CSS class for the title area |
|
|
26
|
+
| `buttonClassName` | `string` | Optional | Optional custom CSS class for the submit button |
|
|
27
|
+
| `renderer` | `{ Content?: (props: RendererProps) => JSX.Element }` | Optional | Optional override to fully control the rendering of the component |
|
|
28
|
+
|
|
29
|
+
#### `CreditPaymentTranslationsProps`
|
|
30
|
+
|
|
31
|
+
| Key | Type | Description |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `title` | `string` | Title text shown at the top of the section |
|
|
34
|
+
| `buttonName` | `string` | Submit button label |
|
|
35
|
+
| `requiredFieldMessage` | `string` | Error message when checkbox is not checked |
|
|
36
|
+
|
|
37
|
+
#### RendererProps (for `renderer.Content`)
|
|
38
|
+
|
|
39
|
+
| Prop | Type | Description |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| `control` | `any` | React Hook Form control instance |
|
|
42
|
+
| `errors` | `any` | React Hook Form errors object |
|
|
43
|
+
| `onSubmit` | `() => void` | Submit handler |
|
|
44
|
+
| `creditPaymentOptions` | `any[]` | Available credit payment options |
|
|
45
|
+
| `selectedCreditPaymentPk` | `number \| null` | Currently selected option's primary key |
|
|
46
|
+
| `setCreditPaymentOption` | `(pk: number) => void` | Setter for selecting a payment option |
|
|
47
|
+
| `preOrder` | `RootState['checkout']['preOrder']` | Pre-order object from Redux |
|
|
48
|
+
| `agreementCheckbox` | `React.ReactElement` | Provided agreement checkbox component |
|
|
49
|
+
| `formError` | `string \| null` | Any error returned from the confirmation API |
|
|
50
|
+
|
|
51
|
+
### Usage
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
src/views/checkout/steps/payment/options/credit-payment/
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### Default Usage
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
<PluginModule
|
|
61
|
+
component={Component.CreditPayment}
|
|
62
|
+
props={{
|
|
63
|
+
agreementCheckbox: (
|
|
64
|
+
<CheckoutAgreements control={null} error={null} fieldId="agreement" />
|
|
65
|
+
)
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### Customized Usage with `renderer`
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
<PluginModule
|
|
74
|
+
component={Component.CreditPayment}
|
|
75
|
+
props={{
|
|
76
|
+
agreementCheckbox: (
|
|
77
|
+
<CheckoutAgreements control={null} error={null} fieldId="agreement" />
|
|
78
|
+
),
|
|
79
|
+
renderer: {
|
|
80
|
+
Content: ({
|
|
81
|
+
control,
|
|
82
|
+
errors,
|
|
83
|
+
onSubmit,
|
|
84
|
+
creditPaymentOptions,
|
|
85
|
+
selectedCreditPaymentPk,
|
|
86
|
+
setCreditPaymentOption,
|
|
87
|
+
preOrder,
|
|
88
|
+
agreementCheckbox,
|
|
89
|
+
formError
|
|
90
|
+
}) => (
|
|
91
|
+
<form onSubmit={onSubmit} className="p-6 bg-white rounded-lg space-y-6">
|
|
92
|
+
<h2 className="text-xl font-semibold">SHOPPING CREDIT</h2>
|
|
93
|
+
<div className="space-y-4">
|
|
94
|
+
{creditPaymentOptions.map((bank) => (
|
|
95
|
+
<label
|
|
96
|
+
key={bank.pk}
|
|
97
|
+
className="p-4 flex items-center cursor-pointer rounded-lg border-gray-480 border space-x-5 pl-5 mb-6"
|
|
98
|
+
>
|
|
99
|
+
<Radio
|
|
100
|
+
type="radio"
|
|
101
|
+
value={bank.pk}
|
|
102
|
+
checked={
|
|
103
|
+
bank.pk === selectedCreditPaymentPk ||
|
|
104
|
+
preOrder.credit_payment_option?.pk === bank.pk
|
|
105
|
+
}
|
|
106
|
+
onChange={() => setCreditPaymentOption(bank.pk)}
|
|
107
|
+
/>
|
|
108
|
+
<span>{bank.name}</span>
|
|
109
|
+
</label>
|
|
110
|
+
))}
|
|
111
|
+
</div>
|
|
112
|
+
{React.cloneElement(agreementCheckbox, {
|
|
113
|
+
control,
|
|
114
|
+
error: errors.agreement,
|
|
115
|
+
fieldId: 'agreement'
|
|
116
|
+
})}
|
|
117
|
+
{formError && <p className="text-xs text-error mt-2">{formError}</p>}
|
|
118
|
+
<Button type="submit" className="w-full bg-black text-white">
|
|
119
|
+
Place Order
|
|
120
|
+
</Button>
|
|
121
|
+
</form>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
}}
|
|
125
|
+
/>
|
|
126
|
+
```
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/pz-credit-payment",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"react": "^19.0.0",
|
|
8
|
-
"react-dom": "^19.0.0"
|
|
7
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
8
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
|
-
"@types/node": "^
|
|
12
|
-
"@types/react": "^
|
|
13
|
-
"@types/react-dom": "^
|
|
14
|
-
"react": "
|
|
15
|
-
"react-dom": "
|
|
16
|
-
"typescript": "^
|
|
11
|
+
"@types/node": "^18.7.8",
|
|
12
|
+
"@types/react": "^18.0.17",
|
|
13
|
+
"@types/react-dom": "^18.0.6",
|
|
14
|
+
"react": "19.2.5",
|
|
15
|
+
"react-dom": "19.2.5",
|
|
16
|
+
"typescript": "^4.7.4",
|
|
17
17
|
"react-hook-form": "7.31.3",
|
|
18
18
|
"@hookform/resolvers": "2.9.0"
|
|
19
19
|
}
|
package/src/index.tsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { yupResolver } from '@hookform/resolvers/yup';
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
3
|
+
import { JSX, useEffect, useState } from 'react';
|
|
4
4
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
|
5
5
|
import { useAppSelector } from '@akinon/next/redux/hooks';
|
|
6
6
|
import { RootState } from 'redux/store';
|
|
7
7
|
import { Button, Icon, Radio } from '@akinon/next/components';
|
|
8
|
+
import { checkPaymentWillRedirect } from '@akinon/next/utils';
|
|
8
9
|
import * as yup from 'yup';
|
|
9
10
|
import clsx from 'clsx';
|
|
10
11
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -26,10 +27,23 @@ const defaultTranslations = {
|
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
export interface CreditPaymentProps {
|
|
29
|
-
translations
|
|
30
|
+
translations?: Record<string, CreditPaymentTranslationsProps>;
|
|
30
31
|
agreementCheckbox: React.ReactElement;
|
|
31
32
|
titleClassName?: string;
|
|
32
33
|
buttonClassName?: string;
|
|
34
|
+
renderer?: {
|
|
35
|
+
Content?: (props: {
|
|
36
|
+
control: any;
|
|
37
|
+
errors: any;
|
|
38
|
+
onSubmit: () => void;
|
|
39
|
+
creditPaymentOptions: any[];
|
|
40
|
+
selectedCreditPaymentPk: number | null;
|
|
41
|
+
setCreditPaymentOption: (pk: number) => void;
|
|
42
|
+
preOrder: RootState['checkout']['preOrder'];
|
|
43
|
+
agreementCheckbox: React.ReactElement;
|
|
44
|
+
formError: string | null;
|
|
45
|
+
}) => JSX.Element;
|
|
46
|
+
};
|
|
33
47
|
}
|
|
34
48
|
|
|
35
49
|
const creditPaymentFormSchema = (requiredFieldMessage) =>
|
|
@@ -41,7 +55,8 @@ export const CreditPayment = ({
|
|
|
41
55
|
translations,
|
|
42
56
|
agreementCheckbox,
|
|
43
57
|
titleClassName,
|
|
44
|
-
buttonClassName
|
|
58
|
+
buttonClassName,
|
|
59
|
+
renderer
|
|
45
60
|
}: CreditPaymentProps) => {
|
|
46
61
|
const _translations = {
|
|
47
62
|
...defaultTranslations,
|
|
@@ -52,26 +67,43 @@ export const CreditPayment = ({
|
|
|
52
67
|
handleSubmit,
|
|
53
68
|
control,
|
|
54
69
|
register,
|
|
55
|
-
formState: { errors }
|
|
70
|
+
formState: { errors, isSubmitting }
|
|
56
71
|
} = useForm({
|
|
57
72
|
resolver: yupResolver(
|
|
58
73
|
creditPaymentFormSchema(_translations.requiredFieldMessage)
|
|
59
|
-
)
|
|
74
|
+
) as any
|
|
60
75
|
});
|
|
61
76
|
const [formError, setFormError] = useState<string | null>(null);
|
|
77
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
62
78
|
|
|
63
79
|
const [setCreditPaymentOption] = useSetCreditPaymentOptionMutation();
|
|
64
|
-
const [confirmationCreditPayment] =
|
|
80
|
+
const [confirmationCreditPayment, { isLoading: isCompleting }] =
|
|
81
|
+
useConfirmationCreditPaymentMutation();
|
|
82
|
+
|
|
83
|
+
const isButtonDisabled = isSubmitting || isCompleting || isProcessing;
|
|
65
84
|
|
|
66
85
|
const { creditPaymentOptions, selectedCreditPaymentPk, preOrder } =
|
|
67
86
|
useAppSelector((state: RootState) => state.checkout);
|
|
68
87
|
|
|
69
88
|
const onSubmit: SubmitHandler<any> = async () => {
|
|
70
|
-
|
|
89
|
+
if (isButtonDisabled) return;
|
|
90
|
+
|
|
91
|
+
setIsProcessing(true);
|
|
71
92
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
93
|
+
try {
|
|
94
|
+
const response = await confirmationCreditPayment().unwrap();
|
|
95
|
+
|
|
96
|
+
if (response?.errors?.non_field_errors) {
|
|
97
|
+
setFormError(response?.errors?.non_field_errors);
|
|
98
|
+
setIsProcessing(false);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (response?.errors || !checkPaymentWillRedirect(response)) {
|
|
103
|
+
setIsProcessing(false);
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
setIsProcessing(false);
|
|
75
107
|
}
|
|
76
108
|
};
|
|
77
109
|
|
|
@@ -86,6 +118,20 @@ export const CreditPayment = ({
|
|
|
86
118
|
setCreditPaymentOption
|
|
87
119
|
]);
|
|
88
120
|
|
|
121
|
+
if (renderer?.Content) {
|
|
122
|
+
return renderer.Content({
|
|
123
|
+
control,
|
|
124
|
+
errors,
|
|
125
|
+
onSubmit: handleSubmit(onSubmit),
|
|
126
|
+
creditPaymentOptions,
|
|
127
|
+
selectedCreditPaymentPk,
|
|
128
|
+
setCreditPaymentOption,
|
|
129
|
+
preOrder,
|
|
130
|
+
agreementCheckbox,
|
|
131
|
+
formError
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
89
135
|
return (
|
|
90
136
|
<form className="flex flex-col w-full" onSubmit={handleSubmit(onSubmit)}>
|
|
91
137
|
<div
|
|
@@ -132,9 +178,8 @@ export const CreditPayment = ({
|
|
|
132
178
|
<div className="px-4 sm:px-6">
|
|
133
179
|
<div className="flex items-start flex-col py-4 space-y-4">
|
|
134
180
|
{agreementCheckbox &&
|
|
135
|
-
React.cloneElement(agreementCheckbox, {
|
|
136
|
-
|
|
137
|
-
control,
|
|
181
|
+
React.cloneElement(agreementCheckbox as any, {
|
|
182
|
+
control: control as any,
|
|
138
183
|
error: errors.agreement,
|
|
139
184
|
fieldId: 'agreement'
|
|
140
185
|
})}
|
|
@@ -147,7 +192,8 @@ export const CreditPayment = ({
|
|
|
147
192
|
|
|
148
193
|
<Button
|
|
149
194
|
type="submit"
|
|
150
|
-
|
|
195
|
+
disabled={isButtonDisabled}
|
|
196
|
+
data-testid="checkout-credit-payment-button"
|
|
151
197
|
className={clsx(
|
|
152
198
|
twMerge(
|
|
153
199
|
'group uppercase mt-4 inline-flex items-center justify-center w-full',
|