@akinon/pz-pay-on-delivery 1.30.2

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/.gitattributes ADDED
@@ -0,0 +1,15 @@
1
+ *.js text eol=lf
2
+ *.jsx text eol=lf
3
+ *.ts text eol=lf
4
+ *.tsx text eol=lf
5
+ *.json text eol=lf
6
+ *.md text eol=lf
7
+
8
+ .eslintignore text eol=lf
9
+ .eslintrc text eol=lf
10
+ .gitignore text eol=lf
11
+ .prettierrc text eol=lf
12
+ .yarnrc text eol=lf
13
+
14
+ * text=auto
15
+
package/.prettierrc ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "bracketSameLine": false,
3
+ "tabWidth": 2,
4
+ "singleQuote": true,
5
+ "jsxSingleQuote": false,
6
+ "bracketSpacing": true,
7
+ "semi": true,
8
+ "useTabs": false,
9
+ "arrowParens": "always",
10
+ "endOfLine": "lf",
11
+ "proseWrap": "never",
12
+ "trailingComma": "none"
13
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @akinon/pz-pay-on-delivery
2
+
3
+ ## 1.30.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 4aa5a13: ZERO-2600: Publish pz-pay-on-delivery plugin
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@akinon/pz-pay-on-delivery",
3
+ "version": "1.30.2",
4
+ "license": "MIT",
5
+ "main": "src/index.tsx",
6
+ "peerDependencies": {
7
+ "react": "^18.0.0",
8
+ "react-dom": "^18.0.0"
9
+ },
10
+ "devDependencies": {
11
+ "@types/node": "^18.7.8",
12
+ "@types/react": "^18.0.17",
13
+ "@types/react-dom": "^18.0.6",
14
+ "react": "^18.2.0",
15
+ "react-dom": "^18.2.0",
16
+ "typescript": "^4.7.4",
17
+ "react-hook-form": "7.31.3",
18
+ "@hookform/resolvers": "2.9.0"
19
+ }
20
+ }
@@ -0,0 +1,69 @@
1
+ import { setPaymentStepBusy } from '@akinon/next/redux/reducers/checkout';
2
+ import { CheckoutContext, PreOrder } from '@akinon/next/types';
3
+ import { api } from '@akinon/next/data/client/api';
4
+ import { checkout } from '@akinon/next/data/urls';
5
+ import { buildClientRequestUrl } from '@akinon/next/utils';
6
+
7
+ interface CheckoutResponse {
8
+ pre_order?: PreOrder;
9
+ errors: {
10
+ non_field_errors: string;
11
+ };
12
+ context_list?: CheckoutContext[];
13
+ template_name?: string;
14
+ redirect_url?: string;
15
+ }
16
+
17
+ export interface PayOnDeliveryParams {
18
+ agreement: string;
19
+ paymentType: string;
20
+ }
21
+
22
+ export const checkoutApi = api.injectEndpoints({
23
+ endpoints: (build) => ({
24
+ setCompletePayOnDelivery: build.mutation<
25
+ CheckoutResponse,
26
+ PayOnDeliveryParams
27
+ >({
28
+ query: ({ paymentType }) => ({
29
+ url: buildClientRequestUrl(
30
+ `${checkout.fetchCheckout}?page=PayOnDeliveryPage`,
31
+ { useFormData: true }
32
+ ),
33
+ method: 'POST',
34
+ body: {
35
+ agreement: '1',
36
+ paymentType
37
+ }
38
+ }),
39
+ async onQueryStarted(arg, { dispatch, queryFulfilled }) {
40
+ dispatch(setPaymentStepBusy(true));
41
+ await queryFulfilled;
42
+ dispatch(setPaymentStepBusy(false));
43
+ }
44
+ }),
45
+ setPayOnDeliveryChoice: build.mutation<CheckoutResponse, string>({
46
+ query: (body) => ({
47
+ url: buildClientRequestUrl(
48
+ `${checkout.fetchCheckout}?page=PayOnDeliveryPaymentChoicePage`,
49
+ { useFormData: true }
50
+ ),
51
+ method: 'POST',
52
+ body: {
53
+ payment_choice: body
54
+ }
55
+ }),
56
+ async onQueryStarted(arg, { dispatch, queryFulfilled }) {
57
+ dispatch(setPaymentStepBusy(true));
58
+ await queryFulfilled;
59
+ dispatch(setPaymentStepBusy(false));
60
+ }
61
+ })
62
+ }),
63
+ overrideExisting: false
64
+ });
65
+
66
+ export const {
67
+ useSetCompletePayOnDeliveryMutation,
68
+ useSetPayOnDeliveryChoiceMutation
69
+ } = checkoutApi;
package/src/index.tsx ADDED
@@ -0,0 +1,193 @@
1
+ import { useAppSelector } from '@akinon/next/redux/hooks';
2
+ import { yupResolver } from '@hookform/resolvers/yup';
3
+ import { Button, Icon, Price, Radio } from '@akinon/next/components';
4
+ import React, { useEffect, useState } from 'react';
5
+ import { SubmitHandler, useForm } from 'react-hook-form';
6
+ import { RootState } from 'redux/store';
7
+ import * as yup from 'yup';
8
+ import {
9
+ useSetCompletePayOnDeliveryMutation,
10
+ useSetPayOnDeliveryChoiceMutation
11
+ } from './endpoints';
12
+
13
+ interface PayOnDeliveryTranslationsProps {
14
+ paymentInformationTitle: string;
15
+ paymentInformationSubtitle: string;
16
+ totalAmountText: string;
17
+ serviceFeeText: string;
18
+ returnInfoText: string;
19
+ refundInfoText: string;
20
+ faqInfoText: string;
21
+ placeOrderText: string;
22
+ errorMessageText: string;
23
+ requiredFieldMessage: string;
24
+ }
25
+
26
+ const defaultTranslations = {
27
+ paymentInformationTitle: 'Payment information on delivery',
28
+ paymentInformationSubtitle: 'Payment Information at the Door',
29
+ totalAmountText:
30
+ 'The amount you have to pay, including the Payment at the Door service fee, is',
31
+ serviceFeeText: 'The payment service fee at the door is',
32
+ returnInfoText:
33
+ 'If you want to return the products you have received, you must fill in the fee return form link.',
34
+ refundInfoText:
35
+ 'The amount to be refunded will be sent to your account via EFT.',
36
+ faqInfoText:
37
+ 'For all your questions about Pay at the Door, you can visit our Frequently Asked Questions page.',
38
+ placeOrderText: 'Place Order',
39
+ errorMessageText: 'Error Message',
40
+ requiredFieldMessage: 'This field is required'
41
+ };
42
+
43
+ interface PayOnDeliveryProps {
44
+ translations: Record<string, PayOnDeliveryTranslationsProps>;
45
+ agreementCheckbox?: React.ReactElement;
46
+ }
47
+
48
+ export const PayOnDelivery = ({
49
+ translations,
50
+ agreementCheckbox
51
+ }: PayOnDeliveryProps) => {
52
+ const _translations = {
53
+ ...defaultTranslations,
54
+ ...translations
55
+ };
56
+
57
+ const createPayOnDeliveryFormSchema = (
58
+ _translations: PayOnDeliveryTranslationsProps
59
+ ) => {
60
+ return yup.object().shape({
61
+ agreement: yup
62
+ .boolean()
63
+ .oneOf([true], _translations.requiredFieldMessage),
64
+ paymentType: yup.string()
65
+ });
66
+ };
67
+
68
+ const payOnDeliveryFormSchema = createPayOnDeliveryFormSchema(_translations);
69
+
70
+ const {
71
+ handleSubmit,
72
+ control,
73
+ register,
74
+ formState: { errors },
75
+ setValue
76
+ } = useForm({
77
+ resolver: yupResolver(payOnDeliveryFormSchema)
78
+ });
79
+
80
+ const [setCompletePayOnDelivery] = useSetCompletePayOnDeliveryMutation();
81
+
82
+ const [setPayOnDeliveryPaymentChoice, { isLoading }] =
83
+ useSetPayOnDeliveryChoiceMutation();
84
+ const [formError, setFormError] = useState(null);
85
+
86
+ const { preOrder, paymentChoices } = useAppSelector(
87
+ (state: RootState) => state.checkout
88
+ );
89
+
90
+ const onSubmit: SubmitHandler<null> = async (data) => {
91
+ const response = await setCompletePayOnDelivery(data).unwrap();
92
+
93
+ setFormError(response?.errors?.non_field_errors);
94
+ };
95
+
96
+ const setPayOnDeliveryChoice = async (value: string) => {
97
+ if (isLoading) return;
98
+
99
+ const response = await setPayOnDeliveryPaymentChoice(value).unwrap();
100
+ setFormError(response?.errors?.non_field_errors);
101
+ };
102
+
103
+ useEffect(() => {
104
+ if (!preOrder?.payment_choice && paymentChoices.length) {
105
+ setPayOnDeliveryChoice(paymentChoices[0].value);
106
+ } else {
107
+ setValue('paymentType', preOrder?.payment_choice?.value);
108
+ }
109
+ }, [paymentChoices, preOrder?.payment_choice]);
110
+
111
+ return (
112
+ <form
113
+ id="pay_on_delivery"
114
+ className="flex flex-col w-full"
115
+ onSubmit={handleSubmit(onSubmit)}
116
+ >
117
+ <div className="flex justify-start items-center border-solid border-gray-400 px-4 py-2 sm:px-6 sm:py-3 sm:min-h-15">
118
+ <span className="text-black-800 text-lg font-medium sm:text-2xl">
119
+ {_translations.paymentInformationTitle}
120
+ </span>
121
+ </div>
122
+
123
+ <div className="w-full bg-white">
124
+ <div className="text-xs text-black-800 p-4 sm:p-6">
125
+ <div className="mb-2">{_translations.paymentInformationSubtitle}</div>
126
+ <div className="inline-flex gap-4 mb-4">
127
+ {paymentChoices?.map((paymentChoice, index) => (
128
+ <label
129
+ className="w-full flex items-center justify-start min-w-max"
130
+ key={index}
131
+ >
132
+ <Radio
133
+ name="payment_choices"
134
+ type="radio"
135
+ value={paymentChoice.value}
136
+ data-testid={`checkout-bank-account-${paymentChoice.label}`}
137
+ {...register('paymentType')}
138
+ onChange={() => setPayOnDeliveryChoice(paymentChoice.value)}
139
+ ></Radio>
140
+
141
+ <span className="flex items-start justify-start flex-col pl-1 sm:flex-row sm:items-center">
142
+ {paymentChoice.label}
143
+ </span>
144
+ </label>
145
+ ))}
146
+ </div>
147
+ <ul className="space-y-1">
148
+ <li>
149
+ {_translations.totalAmountText}{' '}
150
+ <Price value={preOrder?.total_amount} />.
151
+ </li>
152
+ <li>
153
+ {_translations.serviceFeeText}{' '}
154
+ <Price value={preOrder?.payment_choice?.price} />.
155
+ </li>
156
+ <li>{_translations.returnInfoText}</li>
157
+ <li>{_translations.refundInfoText}</li>
158
+ <li>{_translations.faqInfoText}</li>
159
+ </ul>
160
+ </div>
161
+ </div>
162
+
163
+ <div className="px-4 sm:px-6">
164
+ <div className="flex items-start flex-col border-solid border-gray-400 py-4 space-y-4">
165
+ {agreementCheckbox &&
166
+ React.cloneElement(agreementCheckbox, {
167
+ control,
168
+ error: errors.agreement,
169
+ fieldId: 'agreement'
170
+ })}
171
+
172
+ {formError && (
173
+ <div className="w-full text-xs text-start px-1 mt-3 text-error">
174
+ {_translations.errorMessageText}
175
+ </div>
176
+ )}
177
+ <Button
178
+ className="group uppercase mt-4 inline-flex items-center justify-center w-full"
179
+ type="submit"
180
+ data-testid="checkout-bank-account-place-order"
181
+ >
182
+ <span>{_translations.placeOrderText}</span>
183
+ <Icon
184
+ size={12}
185
+ name="chevron-end"
186
+ className="fill-primary-foreground ml-2 h-3 group-hover:fill-primary"
187
+ />
188
+ </Button>
189
+ </div>
190
+ </div>
191
+ </form>
192
+ );
193
+ };