@akinon/next 1.13.1 → 1.14.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/.editorconfig +7 -0
- package/CHANGELOG.md +19 -0
- package/assets/styles/index.scss +28 -28
- package/bin/pz-install-plugins.js +0 -0
- package/bin/pz-install-theme.js +0 -0
- package/bin/pz-postbuild.js +0 -0
- package/bin/pz-postdev.js +0 -0
- package/bin/pz-postinstall.js +0 -0
- package/bin/pz-poststart.js +0 -0
- package/bin/pz-prebuild.js +0 -0
- package/bin/pz-predev.js +0 -0
- package/bin/pz-prestart.js +0 -0
- package/components/accordion.tsx +52 -0
- package/components/button.tsx +46 -0
- package/components/index.ts +17 -1
- package/components/input.tsx +110 -0
- package/components/plugin-module.tsx +11 -8
- package/components/price.tsx +55 -0
- package/components/selected-payment-option-view.tsx +7 -0
- package/data/client/address.ts +107 -107
- package/data/client/api.ts +2 -1
- package/data/client/b2b.ts +106 -106
- package/data/client/checkout.ts +516 -479
- package/data/client/wishlist.ts +31 -1
- package/data/server/category.ts +6 -2
- package/data/server/form.ts +4 -4
- package/data/server/list.ts +6 -1
- package/data/urls.ts +13 -2
- package/hooks/use-payment-options.ts +2 -1
- package/package.json +2 -2
- package/plugins.js +2 -1
- package/redux/middlewares/checkout.ts +265 -260
- package/redux/reducers/checkout.ts +13 -0
- package/redux/reducers/index.ts +14 -14
- package/types/commerce/b2b.ts +117 -117
- package/types/commerce/checkout.ts +7 -0
- package/types/index.ts +37 -0
- package/utils/generate-commerce-search-params.ts +22 -22
- package/utils/get-currency.ts +29 -29
package/.editorconfig
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @akinon/next
|
|
2
2
|
|
|
3
|
+
## 1.14.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Change EOL
|
|
8
|
+
|
|
9
|
+
## 1.14.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 35bce31: ZERO-2356: Add Price component
|
|
14
|
+
- 35bce31: ZERO-2332: Add endpoints for credit payment
|
|
15
|
+
- 35bce31: ZERO-2359: Add Input component
|
|
16
|
+
- 35bce31: ZERO-2394: Add stock alert list and delete endpoints
|
|
17
|
+
- 35bce31: ZERO-2393: Limit error log message length
|
|
18
|
+
- 35bce31: ZERO-2352: Add Button component
|
|
19
|
+
- 35bce31: ZERO-2325: Fix funds transfer payment error
|
|
20
|
+
- 35bce31: ZERO-2354: Add Accordion component
|
|
21
|
+
|
|
3
22
|
## 1.13.1
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/assets/styles/index.scss
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
.checkout-payment-iframe-wrapper {
|
|
2
|
-
position: fixed;
|
|
3
|
-
top: 0;
|
|
4
|
-
left: 0;
|
|
5
|
-
width: 100%;
|
|
6
|
-
height: 100%;
|
|
7
|
-
border: none;
|
|
8
|
-
z-index: 1000;
|
|
9
|
-
background-color: white;
|
|
10
|
-
|
|
11
|
-
iframe {
|
|
12
|
-
width: 100%;
|
|
13
|
-
height: 100%;
|
|
14
|
-
border: none;
|
|
15
|
-
background-color: white;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.close-button {
|
|
19
|
-
position: fixed;
|
|
20
|
-
top: 16px;
|
|
21
|
-
right: 16px;
|
|
22
|
-
width: 32px;
|
|
23
|
-
height: 32px;
|
|
24
|
-
display: flex;
|
|
25
|
-
align-items: center;
|
|
26
|
-
justify-content: center;
|
|
27
|
-
z-index: 1001;
|
|
28
|
-
}
|
|
1
|
+
.checkout-payment-iframe-wrapper {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
border: none;
|
|
8
|
+
z-index: 1000;
|
|
9
|
+
background-color: white;
|
|
10
|
+
|
|
11
|
+
iframe {
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
border: none;
|
|
15
|
+
background-color: white;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.close-button {
|
|
19
|
+
position: fixed;
|
|
20
|
+
top: 16px;
|
|
21
|
+
right: 16px;
|
|
22
|
+
width: 32px;
|
|
23
|
+
height: 32px;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
z-index: 1001;
|
|
28
|
+
}
|
|
29
29
|
}
|
|
File without changes
|
package/bin/pz-install-theme.js
CHANGED
|
File without changes
|
package/bin/pz-postbuild.js
CHANGED
|
File without changes
|
package/bin/pz-postdev.js
CHANGED
|
File without changes
|
package/bin/pz-postinstall.js
CHANGED
|
File without changes
|
package/bin/pz-poststart.js
CHANGED
|
File without changes
|
package/bin/pz-prebuild.js
CHANGED
|
File without changes
|
package/bin/pz-predev.js
CHANGED
|
File without changes
|
package/bin/pz-prestart.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Icon } from './icon';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
|
+
import { AccordionProps } from '../types';
|
|
7
|
+
|
|
8
|
+
export const Accordion = ({
|
|
9
|
+
isCollapse = false,
|
|
10
|
+
title,
|
|
11
|
+
subTitle,
|
|
12
|
+
icons = ['chevron-up', 'chevron-down'],
|
|
13
|
+
iconSize = 16,
|
|
14
|
+
iconColor = 'fill-[#000000]',
|
|
15
|
+
children,
|
|
16
|
+
className,
|
|
17
|
+
titleClassName,
|
|
18
|
+
dataTestId
|
|
19
|
+
}: AccordionProps) => {
|
|
20
|
+
const [collapse, setCollapse] = useState(isCollapse);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
className={twMerge(
|
|
25
|
+
'flex flex-col justify-center border-b pb-4 mb-4 last:border-none',
|
|
26
|
+
className
|
|
27
|
+
)}
|
|
28
|
+
>
|
|
29
|
+
<div
|
|
30
|
+
className="flex items-center justify-between cursor-pointer"
|
|
31
|
+
onClick={() => setCollapse(!collapse)}
|
|
32
|
+
data-testid={dataTestId}
|
|
33
|
+
>
|
|
34
|
+
<div className="flex flex-col">
|
|
35
|
+
{title && (
|
|
36
|
+
<h3 className={twMerge('text-sm', titleClassName)}>{title}</h3>
|
|
37
|
+
)}
|
|
38
|
+
{subTitle && <h4 className="text-xs text-gray-700">{subTitle}</h4>}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
{icons && (
|
|
42
|
+
<Icon
|
|
43
|
+
name={collapse ? icons[0] : icons[1]}
|
|
44
|
+
size={iconSize}
|
|
45
|
+
className={`fill-[${iconColor}]}`}
|
|
46
|
+
/>
|
|
47
|
+
)}
|
|
48
|
+
</div>
|
|
49
|
+
{collapse && <div className="mt-3 text-sm">{children}</div>}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ButtonProps } from '../types/index';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
|
+
|
|
7
|
+
export const Button = (props: ButtonProps) => {
|
|
8
|
+
return (
|
|
9
|
+
<button
|
|
10
|
+
{...props}
|
|
11
|
+
className={twMerge(
|
|
12
|
+
clsx(
|
|
13
|
+
[
|
|
14
|
+
'px-4',
|
|
15
|
+
'h-10',
|
|
16
|
+
'text-xs',
|
|
17
|
+
'bg-primary',
|
|
18
|
+
'text-primary-foreground',
|
|
19
|
+
'border',
|
|
20
|
+
'border-primary',
|
|
21
|
+
'transition-all',
|
|
22
|
+
'hover:bg-white',
|
|
23
|
+
'hover:border-primary',
|
|
24
|
+
'hover:text-primary'
|
|
25
|
+
],
|
|
26
|
+
props.appearance === 'outlined' && [
|
|
27
|
+
'bg-transparent ',
|
|
28
|
+
'text-primary ',
|
|
29
|
+
'hover:bg-primary ',
|
|
30
|
+
'hover:text-primary-foreground'
|
|
31
|
+
],
|
|
32
|
+
props.appearance === 'ghost' && [
|
|
33
|
+
'bg-transparent',
|
|
34
|
+
'border-transparent',
|
|
35
|
+
'text-primary',
|
|
36
|
+
'hover:bg-primary',
|
|
37
|
+
'hover:text-primary-foreground'
|
|
38
|
+
]
|
|
39
|
+
),
|
|
40
|
+
props.className
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
{props.children}
|
|
44
|
+
</button>
|
|
45
|
+
);
|
|
46
|
+
};
|
package/components/index.ts
CHANGED
|
@@ -1 +1,17 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './accordion';
|
|
2
|
+
export * from './button';
|
|
3
|
+
export * from './client-root';
|
|
4
|
+
export * from './icon';
|
|
5
|
+
export * from './image';
|
|
6
|
+
export * from './input';
|
|
7
|
+
export * from './lazy-component';
|
|
8
|
+
export * from './loader-spinner';
|
|
9
|
+
export * from './mobile-app-toggler';
|
|
10
|
+
export * from './oauth-login';
|
|
11
|
+
export * from './plugin-module';
|
|
12
|
+
export * from './price';
|
|
13
|
+
export * from './pz-providers';
|
|
14
|
+
export * from './radio';
|
|
15
|
+
export * from './react-portal';
|
|
16
|
+
export * from './selected-payment-option-view';
|
|
17
|
+
export * from './trans';
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { forwardRef, FocusEvent, useState } from 'react';
|
|
3
|
+
import { Controller } from 'react-hook-form';
|
|
4
|
+
import NumberFormat, { NumberFormatProps } from 'react-number-format';
|
|
5
|
+
import { InputProps } from '../types';
|
|
6
|
+
import { twMerge } from 'tailwind-merge';
|
|
7
|
+
|
|
8
|
+
export const Input = forwardRef<
|
|
9
|
+
HTMLInputElement,
|
|
10
|
+
InputProps &
|
|
11
|
+
Pick<
|
|
12
|
+
NumberFormatProps,
|
|
13
|
+
'format' | 'mask' | 'allowEmptyFormatting' | 'onValueChange'
|
|
14
|
+
>
|
|
15
|
+
>((props, ref) => {
|
|
16
|
+
const [focused, setFocused] = useState(false);
|
|
17
|
+
const [hasValue, setHasValue] = useState(false);
|
|
18
|
+
const {
|
|
19
|
+
id,
|
|
20
|
+
label,
|
|
21
|
+
labelStyle,
|
|
22
|
+
error,
|
|
23
|
+
mask,
|
|
24
|
+
format,
|
|
25
|
+
required = false,
|
|
26
|
+
...rest
|
|
27
|
+
} = props;
|
|
28
|
+
const hasFloatingLabel = label && labelStyle === 'floating';
|
|
29
|
+
const inputClass = twMerge(
|
|
30
|
+
clsx(
|
|
31
|
+
'text-xs border px-2.5 h-10 placeholder:text-gray-600',
|
|
32
|
+
'focus-visible:outline-none', // disable outline on focus
|
|
33
|
+
{ 'pt-3': hasFloatingLabel },
|
|
34
|
+
error
|
|
35
|
+
? 'border-error focus:border-error'
|
|
36
|
+
: 'border-gray-500 hover:border-black focus:border-black'
|
|
37
|
+
),
|
|
38
|
+
props.className
|
|
39
|
+
);
|
|
40
|
+
const inputProps: any = {
|
|
41
|
+
id,
|
|
42
|
+
ref,
|
|
43
|
+
className: inputClass,
|
|
44
|
+
onFocus: () => setFocused(true),
|
|
45
|
+
onBlur: (event: FocusEvent<HTMLInputElement>) => {
|
|
46
|
+
setFocused(false);
|
|
47
|
+
setHasValue(!!event.target.value);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const Label = () => {
|
|
52
|
+
if (!label) return null;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<label
|
|
56
|
+
htmlFor={id}
|
|
57
|
+
className={clsx(
|
|
58
|
+
'text-xs text-gray-800',
|
|
59
|
+
{
|
|
60
|
+
'absolute left-2.5 pointer-events-none transition-all transform -translate-y-1/2':
|
|
61
|
+
hasFloatingLabel
|
|
62
|
+
},
|
|
63
|
+
{ 'mb-2': !hasFloatingLabel },
|
|
64
|
+
{ 'top-1/3': hasFloatingLabel && (focused || hasValue) },
|
|
65
|
+
{ 'top-1/2': !(hasFloatingLabel && (focused || hasValue)) }
|
|
66
|
+
)}
|
|
67
|
+
>
|
|
68
|
+
{label} {required && <span className="text-secondary">*</span>}
|
|
69
|
+
</label>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div className="flex flex-col">
|
|
75
|
+
<div className="relative flex flex-col">
|
|
76
|
+
{props.format ? (
|
|
77
|
+
<>
|
|
78
|
+
{labelStyle !== 'floating' && <Label />}
|
|
79
|
+
<Controller
|
|
80
|
+
name={props.name ?? ''}
|
|
81
|
+
control={props.control}
|
|
82
|
+
defaultValue={false}
|
|
83
|
+
render={({ field }) => (
|
|
84
|
+
<NumberFormat
|
|
85
|
+
format={format}
|
|
86
|
+
mask={mask ?? ''}
|
|
87
|
+
{...rest}
|
|
88
|
+
{...field}
|
|
89
|
+
{...inputProps}
|
|
90
|
+
/>
|
|
91
|
+
)}
|
|
92
|
+
/>
|
|
93
|
+
{labelStyle === 'floating' && <Label />}
|
|
94
|
+
</>
|
|
95
|
+
) : (
|
|
96
|
+
<>
|
|
97
|
+
{labelStyle !== 'floating' && <Label />}
|
|
98
|
+
<input {...rest} {...inputProps} />
|
|
99
|
+
{labelStyle === 'floating' && <Label />}
|
|
100
|
+
</>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
{error && (
|
|
104
|
+
<span className="mt-1 text-sm text-error">{error.message}</span>
|
|
105
|
+
)}
|
|
106
|
+
</div>
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
Input.displayName = 'Input';
|
|
@@ -11,7 +11,8 @@ enum Plugin {
|
|
|
11
11
|
CheckoutGiftPack = 'pz-checkout-gift-pack',
|
|
12
12
|
GPay = 'pz-gpay',
|
|
13
13
|
Otp = 'pz-otp',
|
|
14
|
-
BKMExpress = 'pz-bkm'
|
|
14
|
+
BKMExpress = 'pz-bkm',
|
|
15
|
+
Masterpass = 'pz-masterpass'
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export enum Component {
|
|
@@ -22,7 +23,8 @@ export enum Component {
|
|
|
22
23
|
CheckoutGiftPack = 'CheckoutGiftPack',
|
|
23
24
|
GPay = 'GPayOption',
|
|
24
25
|
Otp = 'Otp',
|
|
25
|
-
BKMExpress = 'BKMOption'
|
|
26
|
+
BKMExpress = 'BKMOption',
|
|
27
|
+
MasterpassCardList = 'MasterpassCardList'
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
const PluginComponents = new Map([
|
|
@@ -33,7 +35,8 @@ const PluginComponents = new Map([
|
|
|
33
35
|
[Plugin.CheckoutGiftPack, [Component.CheckoutGiftPack]],
|
|
34
36
|
[Plugin.GPay, [Component.GPay]],
|
|
35
37
|
[Plugin.Otp, [Component.Otp]],
|
|
36
|
-
[Plugin.BKMExpress, [Component.BKMExpress]]
|
|
38
|
+
[Plugin.BKMExpress, [Component.BKMExpress]],
|
|
39
|
+
[Plugin.Masterpass, [Component.MasterpassCardList]]
|
|
37
40
|
]);
|
|
38
41
|
|
|
39
42
|
const getPlugin = (component: Component) => {
|
|
@@ -53,10 +56,6 @@ export default function PluginModule({
|
|
|
53
56
|
}) {
|
|
54
57
|
const plugin = getPlugin(component);
|
|
55
58
|
|
|
56
|
-
if (!(plugins as string[]).includes(plugin)) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
59
|
const Component = useMemo(
|
|
61
60
|
() =>
|
|
62
61
|
dynamic(
|
|
@@ -91,8 +90,12 @@ export default function PluginModule({
|
|
|
91
90
|
},
|
|
92
91
|
{ ssr: false }
|
|
93
92
|
),
|
|
94
|
-
[plugin]
|
|
93
|
+
[plugin, component]
|
|
95
94
|
);
|
|
96
95
|
|
|
96
|
+
if (!(plugins as string[]).includes(plugin)) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
97
100
|
return <Component {...props} />;
|
|
98
101
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import NumberFormat, { NumberFormatProps } from 'react-number-format';
|
|
3
|
+
import { getCurrency } from '@akinon/next/utils';
|
|
4
|
+
|
|
5
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
6
|
+
import { PriceProps } from '../types';
|
|
7
|
+
|
|
8
|
+
export const Price = (props: NumberFormatProps & PriceProps) => {
|
|
9
|
+
const {
|
|
10
|
+
value,
|
|
11
|
+
currencyCode,
|
|
12
|
+
displayType = 'text',
|
|
13
|
+
useCurrencySymbol = false,
|
|
14
|
+
useCurrencyAfterPrice = true,
|
|
15
|
+
useCurrencySpace = true,
|
|
16
|
+
useNegative = false,
|
|
17
|
+
useNegativeSpace = true,
|
|
18
|
+
thousandSeparator = '.',
|
|
19
|
+
decimalScale = 2,
|
|
20
|
+
decimalSeparator = ',',
|
|
21
|
+
fixedDecimalScale = true,
|
|
22
|
+
...rest
|
|
23
|
+
} = props;
|
|
24
|
+
const { currency: selectedCurrencyCode } = useLocalization();
|
|
25
|
+
const currencyCode_ = currencyCode || selectedCurrencyCode;
|
|
26
|
+
|
|
27
|
+
// TODO: This is very bad practice. It broke decimalScale.
|
|
28
|
+
const _value = value?.toString().replace('.', ',');
|
|
29
|
+
|
|
30
|
+
const currency = useMemo(
|
|
31
|
+
() =>
|
|
32
|
+
getCurrency({
|
|
33
|
+
currencyCode: currencyCode_,
|
|
34
|
+
useCurrencySymbol,
|
|
35
|
+
useCurrencyAfterPrice,
|
|
36
|
+
useCurrencySpace
|
|
37
|
+
}),
|
|
38
|
+
[currencyCode_, useCurrencySymbol, useCurrencyAfterPrice, useCurrencySpace]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<NumberFormat
|
|
43
|
+
value={useNegative ? `-${useNegativeSpace}${_value}` : _value}
|
|
44
|
+
{...{
|
|
45
|
+
[useCurrencyAfterPrice ? 'suffix' : 'prefix']: currency
|
|
46
|
+
}}
|
|
47
|
+
displayType={displayType}
|
|
48
|
+
thousandSeparator={thousandSeparator}
|
|
49
|
+
decimalScale={decimalScale}
|
|
50
|
+
decimalSeparator={decimalSeparator}
|
|
51
|
+
fixedDecimalScale={fixedDecimalScale}
|
|
52
|
+
{...rest}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
@@ -50,7 +50,14 @@ export default function SelectedPaymentOptionView() {
|
|
|
50
50
|
);
|
|
51
51
|
} else if (payment_option.payment_type === 'loyalty_money') {
|
|
52
52
|
promise = import(`views/checkout/steps/payment/options/loyalty`);
|
|
53
|
+
} else if (payment_option.payment_type === 'masterpass') {
|
|
54
|
+
promise = import(
|
|
55
|
+
`views/checkout/steps/payment/options/credit-card`
|
|
56
|
+
);
|
|
53
57
|
}
|
|
58
|
+
// else if (payment_option.payment_type === 'credit_payment') {
|
|
59
|
+
// promise = import(`views/checkout/steps/payment/options/credit-payment`);
|
|
60
|
+
// }
|
|
54
61
|
// else if (payment_option.payment_type === 'gpay') {
|
|
55
62
|
// promise = import(`views/checkout/steps/payment/options/gpay`);
|
|
56
63
|
// }
|