@akinon/pz-credit-payment 1.90.0 → 1.91.0-rc.1
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 +13 -0
- package/README.md +126 -0
- package/package.json +1 -1
- package/src/index.tsx +63 -28
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# @akinon/pz-credit-payment
|
2
2
|
|
3
|
+
## 1.91.0-rc.1
|
4
|
+
|
5
|
+
## 1.91.0-rc.0
|
6
|
+
|
7
|
+
### Minor Changes
|
8
|
+
|
9
|
+
- 310556e: ZERO-3372 :Add README and enhance CreditPayment component with renderer support
|
10
|
+
- 64699d3f: ZERO-2761: Fix invalid import for plugin module
|
11
|
+
- e974d8e: ZERO-3406: Fix rc build
|
12
|
+
- 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
|
13
|
+
- 33377cfd: ZERO-3267: Refactor import statement for ROUTES in error-page component
|
14
|
+
- fec9638a: ZERO-3346 :Update data-testid for Credit Payment button
|
15
|
+
|
3
16
|
## 1.90.0
|
4
17
|
|
5
18
|
## 1.89.0
|
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
package/src/index.tsx
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
import React from 'react';
|
3
2
|
import { yupResolver } from '@hookform/resolvers/yup';
|
4
3
|
import { useEffect, useState } from 'react';
|
@@ -27,10 +26,23 @@ const defaultTranslations = {
|
|
27
26
|
};
|
28
27
|
|
29
28
|
export interface CreditPaymentProps {
|
30
|
-
translations
|
29
|
+
translations?: Record<string, CreditPaymentTranslationsProps>;
|
31
30
|
agreementCheckbox: React.ReactElement;
|
32
31
|
titleClassName?: string;
|
33
32
|
buttonClassName?: string;
|
33
|
+
renderer?: {
|
34
|
+
Content?: (props: {
|
35
|
+
control: any;
|
36
|
+
errors: any;
|
37
|
+
onSubmit: () => void;
|
38
|
+
creditPaymentOptions: any[];
|
39
|
+
selectedCreditPaymentPk: number | null;
|
40
|
+
setCreditPaymentOption: (pk: number) => void;
|
41
|
+
preOrder: RootState['checkout']['preOrder'];
|
42
|
+
agreementCheckbox: React.ReactElement;
|
43
|
+
formError: string | null;
|
44
|
+
}) => JSX.Element;
|
45
|
+
};
|
34
46
|
}
|
35
47
|
|
36
48
|
const creditPaymentFormSchema = (requiredFieldMessage) =>
|
@@ -38,14 +50,13 @@ const creditPaymentFormSchema = (requiredFieldMessage) =>
|
|
38
50
|
agreement: yup.boolean().oneOf([true], requiredFieldMessage)
|
39
51
|
});
|
40
52
|
|
41
|
-
export const CreditPayment = (
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
) => {
|
53
|
+
export const CreditPayment = ({
|
54
|
+
translations,
|
55
|
+
agreementCheckbox,
|
56
|
+
titleClassName,
|
57
|
+
buttonClassName,
|
58
|
+
renderer
|
59
|
+
}: CreditPaymentProps) => {
|
49
60
|
const _translations = {
|
50
61
|
...defaultTranslations,
|
51
62
|
...translations
|
@@ -57,21 +68,22 @@ export const CreditPayment = (
|
|
57
68
|
register,
|
58
69
|
formState: { errors }
|
59
70
|
} = useForm({
|
60
|
-
resolver: yupResolver(
|
71
|
+
resolver: yupResolver(
|
72
|
+
creditPaymentFormSchema(_translations.requiredFieldMessage)
|
73
|
+
)
|
61
74
|
});
|
62
75
|
const [formError, setFormError] = useState<string | null>(null);
|
63
76
|
|
64
77
|
const [setCreditPaymentOption] = useSetCreditPaymentOptionMutation();
|
65
78
|
const [confirmationCreditPayment] = useConfirmationCreditPaymentMutation();
|
66
79
|
|
67
|
-
const { creditPaymentOptions, selectedCreditPaymentPk, preOrder } =
|
68
|
-
(state: RootState) => state.checkout
|
69
|
-
);
|
80
|
+
const { creditPaymentOptions, selectedCreditPaymentPk, preOrder } =
|
81
|
+
useAppSelector((state: RootState) => state.checkout);
|
70
82
|
|
71
83
|
const onSubmit: SubmitHandler<any> = async () => {
|
72
84
|
const response = await confirmationCreditPayment().unwrap();
|
73
85
|
|
74
|
-
if(response?.errors?.non_field_errors) {
|
86
|
+
if (response?.errors?.non_field_errors) {
|
75
87
|
setFormError(response?.errors?.non_field_errors);
|
76
88
|
return;
|
77
89
|
}
|
@@ -81,17 +93,38 @@ export const CreditPayment = (
|
|
81
93
|
if (creditPaymentOptions?.length && !preOrder.credit_payment_option) {
|
82
94
|
setCreditPaymentOption(creditPaymentOptions[0].pk);
|
83
95
|
}
|
84
|
-
}, [
|
96
|
+
}, [
|
97
|
+
creditPaymentOptions,
|
98
|
+
selectedCreditPaymentPk,
|
99
|
+
preOrder.credit_payment_option,
|
100
|
+
setCreditPaymentOption
|
101
|
+
]);
|
102
|
+
|
103
|
+
if (renderer?.Content) {
|
104
|
+
return renderer.Content({
|
105
|
+
control,
|
106
|
+
errors,
|
107
|
+
onSubmit: handleSubmit(onSubmit),
|
108
|
+
creditPaymentOptions,
|
109
|
+
selectedCreditPaymentPk,
|
110
|
+
setCreditPaymentOption,
|
111
|
+
preOrder,
|
112
|
+
agreementCheckbox,
|
113
|
+
formError
|
114
|
+
});
|
115
|
+
}
|
85
116
|
|
86
117
|
return (
|
87
118
|
<form className="flex flex-col w-full" onSubmit={handleSubmit(onSubmit)}>
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
119
|
+
<div
|
120
|
+
className={clsx(
|
121
|
+
twMerge(
|
122
|
+
'flex justify-start items-center border-solid border-gray-400 px-4 py-2 sm:px-6 sm:py-3 sm:min-h-15',
|
123
|
+
'text-black-800 text-lg font-medium sm:text-2xl',
|
124
|
+
titleClassName
|
93
125
|
)
|
94
|
-
|
126
|
+
)}
|
127
|
+
>
|
95
128
|
{_translations.title}
|
96
129
|
</div>
|
97
130
|
|
@@ -105,7 +138,10 @@ export const CreditPayment = (
|
|
105
138
|
<Radio
|
106
139
|
type="radio"
|
107
140
|
value={bank.pk}
|
108
|
-
checked={
|
141
|
+
checked={
|
142
|
+
bank.pk === selectedCreditPaymentPk ||
|
143
|
+
preOrder.credit_payment_option?.pk === bank.pk
|
144
|
+
}
|
109
145
|
{...register('paymentType')}
|
110
146
|
onChange={() => {
|
111
147
|
setCreditPaymentOption(bank.pk);
|
@@ -123,12 +159,12 @@ export const CreditPayment = (
|
|
123
159
|
|
124
160
|
<div className="px-4 sm:px-6">
|
125
161
|
<div className="flex items-start flex-col py-4 space-y-4">
|
126
|
-
|
162
|
+
{agreementCheckbox &&
|
127
163
|
React.cloneElement(agreementCheckbox, {
|
128
164
|
control,
|
129
165
|
error: errors.agreement,
|
130
166
|
fieldId: 'agreement'
|
131
|
-
|
167
|
+
})}
|
132
168
|
|
133
169
|
{formError && (
|
134
170
|
<div className="w-full text-xs text-start px-1 mt-3 text-error">
|
@@ -138,12 +174,12 @@ export const CreditPayment = (
|
|
138
174
|
|
139
175
|
<Button
|
140
176
|
type="submit"
|
141
|
-
data-testid="checkout-
|
177
|
+
data-testid="checkout-credit-payment-button"
|
142
178
|
className={clsx(
|
143
179
|
twMerge(
|
144
180
|
'group uppercase mt-4 inline-flex items-center justify-center w-full',
|
145
181
|
buttonClassName
|
146
|
-
|
182
|
+
)
|
147
183
|
)}
|
148
184
|
>
|
149
185
|
<span>{_translations.buttonName}</span>
|
@@ -159,4 +195,3 @@ export const CreditPayment = (
|
|
159
195
|
</form>
|
160
196
|
);
|
161
197
|
};
|
162
|
-
|