@akinon/pz-gpay 2.0.0-beta.10 → 2.0.0-beta.11

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @akinon/pz-gpay
2
2
 
3
+ ## 2.0.0-beta.11
4
+
5
+ ### Minor Changes
6
+
7
+ - ac783d6: ZERO-3482: Update tailwindcss to version 4.1.11 and enhance button cursor styles
8
+
3
9
  ## 2.0.0-beta.10
4
10
 
5
11
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/pz-gpay",
3
- "version": "2.0.0-beta.10",
3
+ "version": "2.0.0-beta.11",
4
4
  "license": "MIT",
5
5
  "main": "src/index.tsx",
6
6
  "peerDependencies": {
package/readme.md CHANGED
@@ -28,7 +28,26 @@ const GPay = () => {
28
28
  'Click the button below to pay for your order using GarantiPay.',
29
29
  button: 'Pay Now'
30
30
  },
31
- titleClassName: 'text-4xl'
31
+ containerClassName: 'bg-gray-50 rounded-md',
32
+ titleClassName: 'text-2xl font-bold',
33
+ descriptionClassName: 'text-sm',
34
+ buttonClassName: 'bg-primary text-white',
35
+ customUIRender: ({ handleSubmit, onSubmit, translations }) => (
36
+ <form onSubmit={handleSubmit(onSubmit)} className="p-6 bg-white">
37
+ <h2 className="text-xl font-bold mb-2">{translations.title}</h2>
38
+ <div className="text-sm mb-4">
39
+ {translations.description.map((item, index) => (
40
+ <li key={index}>{item}</li>
41
+ ))}
42
+ </div>
43
+ <button
44
+ type="submit"
45
+ className="w-full h-9 bg-black-300 text-white"
46
+ >
47
+ {translations.button}
48
+ </button>
49
+ </form>
50
+ )
32
51
  }}
33
52
  />
34
53
  );
@@ -47,10 +66,26 @@ export default GarantiPayRedirect;
47
66
 
48
67
  ### Props
49
68
 
50
- | Properties | Type | Description |
51
- | -------------------- | ------ | ------------------------------------------ |
52
- | translations | object | The translations of the component. |
53
- | containerClassName | string | The CSS class to apply to the container. |
54
- | titleClassName | string | The CSS class to apply to the title. |
69
+ | Properties | Type | Description |
70
+ | --- | --- | --- |
71
+ | translations | object | The translations of the component. |
72
+ | containerClassName | string | The CSS class to apply to the container. |
73
+ | titleClassName | string | The CSS class to apply to the title. |
55
74
  | descriptionClassName | string | The CSS class to apply to the description. |
56
- | buttonClassName | string | The CSS class to apply to the button. |
75
+ | buttonClassName | string | The CSS class to apply to the button. |
76
+ | customUIRender | function | Custom render function for the component. Receives form handlers and translations. |
77
+
78
+ ### Default Translations
79
+
80
+ ```javascript
81
+ {
82
+ title: 'Pay with GarantiPay',
83
+ description: [
84
+ 'Click on the "GarantiPay" button. Guarantee for payment you will be redirected to the payment page.',
85
+ 'Log in to your account with your username and password on the Garanti Pay page. If you do not have a Garanti Pay membership, create a new membership you can create.',
86
+ 'Complete the payment process by selecting your card and payment type.'
87
+ ],
88
+ button: 'Pay with GarantiPay',
89
+ error: 'An error occurred during payment'
90
+ }
91
+ ```
@@ -1,9 +1,16 @@
1
1
  'use client';
2
2
 
3
3
  import * as yup from 'yup';
4
- import { ReactNode, useEffect, useState } from 'react';
4
+ import { ReactNode, ReactElement, useEffect, useState } from 'react';
5
+ import {
6
+ SubmitHandler,
7
+ useForm,
8
+ UseFormHandleSubmit,
9
+ Control,
10
+ FieldErrors
11
+ } from 'react-hook-form';
5
12
  import { RootState } from 'redux/store';
6
- import { SubmitHandler, useForm } from 'react-hook-form';
13
+ import { yupResolver } from '@hookform/resolvers/yup';
7
14
  import { useAppSelector } from '@akinon/next/redux/hooks';
8
15
  import { useSetPaymentOptionMutation } from '@akinon/next/data/client/checkout';
9
16
  import {
@@ -11,39 +18,62 @@ import {
11
18
  useSetGPayMethodMutation
12
19
  } from '../endpoints';
13
20
  import { twMerge } from 'tailwind-merge';
14
- import { yupResolver } from '@hookform/resolvers/yup';
15
21
  import { Button } from '@akinon/next/components/button';
16
22
  import { getPosError } from '@akinon/next/utils';
17
23
 
24
+ type GPayForm = Record<string, never>;
25
+
18
26
  const gpayFormSchema = yup.object();
19
27
 
20
- enum Elements {
21
- container,
22
- title,
23
- description,
24
- button
25
- }
28
+ type GPayTranslations = {
29
+ title: string;
30
+ description: string[];
31
+ button: string;
32
+ error: string;
33
+ };
26
34
 
27
- type ElementClassKey = `${keyof typeof Elements}ClassName`;
35
+ type GPayOptionProps = {
36
+ containerClassName?: string;
37
+ titleClassName?: string;
38
+ descriptionClassName?: string;
39
+ buttonClassName?: string;
40
+ translations?: Partial<GPayTranslations>;
41
+ customUIRender?: (params: {
42
+ handleSubmit: UseFormHandleSubmit<GPayForm>;
43
+ onSubmit: SubmitHandler<GPayForm>;
44
+ control: Control<GPayForm>;
45
+ errors: FieldErrors<GPayForm>;
46
+ translations: GPayTranslations;
47
+ }) => ReactElement;
48
+ };
28
49
 
29
- type GpayOptionProps = {
30
- [key in ElementClassKey]?: string;
31
- } & {
32
- translations?: {
33
- [element in keyof typeof Elements]?: string | ReactNode;
34
- };
50
+ const defaultTranslations: GPayTranslations = {
51
+ title: 'Pay with GarantiPay',
52
+ description: [
53
+ 'Click on the "Pay with GarantiPay" button. Guarantee for payment you will be redirected to the payment page.',
54
+ 'Log in to your account with your username and password on the Garanti Pay page. If you do not have a Garanti Pay membership, create a new membership you can create.',
55
+ 'Complete the payment process by selecting your card and payment type.'
56
+ ],
57
+ button: 'Pay with GarantiPay',
58
+ error: 'An error occurred during payment'
35
59
  };
36
60
 
37
- export function GPayOption(props: GpayOptionProps) {
38
- const [formError, setFormError] = useState(null);
39
- const [errors, setErrors] = useState([]);
61
+ export function GPayOption(props: GPayOptionProps) {
62
+ const [formError, setFormError] = useState<string | null>(null);
63
+ const [errors, setErrors] = useState<string[]>([]);
64
+
65
+ const translations = { ...defaultTranslations, ...props.translations };
40
66
 
41
67
  const { preOrder } = useAppSelector((state: RootState) => state.checkout);
42
68
  const isPaymentStepBusy = useAppSelector(
43
69
  (state: RootState) => state.checkout.steps.payment.busy
44
70
  );
45
71
 
46
- const { handleSubmit } = useForm({
72
+ const {
73
+ handleSubmit,
74
+ control,
75
+ formState: { errors: formErrors }
76
+ } = useForm<GPayForm>({
47
77
  resolver: yupResolver(gpayFormSchema)
48
78
  });
49
79
 
@@ -51,21 +81,19 @@ export function GPayOption(props: GpayOptionProps) {
51
81
  const [setGPayMethod] = useSetGPayMethodMutation();
52
82
  const [setCompleteGPay] = useSetCompleteGPayMutation();
53
83
 
54
- const onSubmit: SubmitHandler<null> = async () => {
84
+ const onSubmit: SubmitHandler<GPayForm> = async () => {
55
85
  if (isPaymentStepBusy) return;
56
86
 
57
- setFormError([]);
58
-
87
+ setFormError(null);
59
88
  await setGPayMethod();
60
89
 
61
90
  const response = await setCompleteGPay().unwrap();
62
91
 
63
92
  if (response?.errors?.non_field_errors) {
64
- setFormError(response?.errors?.non_field_errors);
93
+ setFormError(response.errors.non_field_errors);
65
94
  }
66
95
  };
67
96
 
68
- // this is necessary because we need to set the payment_option after the redirect
69
97
  useEffect(() => {
70
98
  const posErrors = getPosError();
71
99
 
@@ -79,6 +107,16 @@ export function GPayOption(props: GpayOptionProps) {
79
107
  // eslint-disable-next-line react-hooks/exhaustive-deps
80
108
  }, []);
81
109
 
110
+ if (props.customUIRender) {
111
+ return props.customUIRender({
112
+ handleSubmit,
113
+ onSubmit,
114
+ control,
115
+ errors: formErrors,
116
+ translations
117
+ });
118
+ }
119
+
82
120
  return (
83
121
  <form
84
122
  id="gpay_payment"
@@ -86,38 +124,30 @@ export function GPayOption(props: GpayOptionProps) {
86
124
  onSubmit={handleSubmit(onSubmit)}
87
125
  >
88
126
  <h1 className={twMerge('text-2xl font-bold', props.titleClassName)}>
89
- {props.translations?.title ?? 'Pay with GarantiPay'}
127
+ {translations.title}
90
128
  </h1>
129
+
91
130
  <div className={twMerge('text-sm', props.descriptionClassName)}>
92
- {props.translations?.description ? (
93
- props.translations.description
94
- ) : (
95
- <>
96
- <li>
97
- Click on the “Pay with GarantiPay” button. Guarantee for payment
98
- you will be redirected to the payment page.
99
- </li>
100
- <li>
101
- Log in to your account with your username and password on the
102
- Garanti Pay page. If you do not have a Garanti Pay membership,
103
- create a new membership you can create.
104
- </li>
105
- <li>
106
- Complete the payment process by selecting your card and payment
107
- type.
108
- </li>
109
- </>
110
- )}
131
+ {translations.description.map((item, index) => (
132
+ <li key={index}>{item}</li>
133
+ ))}
111
134
  </div>
112
- <Button className={twMerge('w-full mt-3', props.buttonClassName)}>
113
- {props.translations?.button ?? 'Pay with GarantiPay'}
135
+
136
+ <Button
137
+ data-testid="gpay-payment-button"
138
+ className={twMerge('w-full mt-3', props.buttonClassName)}
139
+ type="submit"
140
+ >
141
+ {translations.button}
114
142
  </Button>
143
+
115
144
  {formError && (
116
145
  <div className="w-full text-xs text-start px-1 mt-3 text-error">
117
146
  {formError}
118
147
  </div>
119
148
  )}
120
- {errors && (
149
+
150
+ {errors.length > 0 && (
121
151
  <div className="w-full text-xs text-start px-1 mt-3 text-error">
122
152
  {errors.map((error) => (
123
153
  <div key={error}>{error}</div>