@akinon/projectzero 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 +6 -0
- package/app-template/CHANGELOG.md +26 -0
- package/app-template/docs/plugins.md +60 -25
- package/app-template/jest.config.ts +2 -2
- package/app-template/package.json +20 -20
- package/app-template/src/app/[commerce]/[locale]/[currency]/account/orders/[id]/cancellation/page.tsx +7 -4
- package/app-template/src/app/[commerce]/[locale]/[currency]/account/orders/[id]/page.tsx +47 -44
- package/app-template/src/components/button.tsx +2 -2
- package/app-template/src/components/checkbox.tsx +1 -0
- package/app-template/src/settings.js +2 -1
- package/app-template/src/views/account/order.tsx +10 -8
- package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +44 -37
- package/app-template/src/views/checkout/steps/payment/options/redirection.tsx +5 -1
- package/app-template/src/views/header/action-menu.tsx +5 -1
- package/app-template/src/views/product/price-wrapper.tsx +7 -2
- package/app-template/src/views/product/product-info.tsx +33 -3
- package/app-template/tailwind.config.js +11 -7
- package/codemods/update-tailwind-config/index.js +30 -0
- package/codemods/update-tailwind-config/transform.js +102 -0
- package/commands/codemod.ts +0 -1
- package/commands/plugins.ts +20 -30
- package/dist/commands/codemod.js +0 -1
- package/dist/commands/plugins.js +19 -20
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# projectzeronext
|
|
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
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [ac783d6]
|
|
12
|
+
- @akinon/pz-checkout-gift-pack@2.0.0-beta.11
|
|
13
|
+
- @akinon/pz-one-click-checkout@2.0.0-beta.11
|
|
14
|
+
- @akinon/pz-basket-gift-pack@2.0.0-beta.11
|
|
15
|
+
- @akinon/pz-tamara-extension@2.0.0-beta.11
|
|
16
|
+
- @akinon/pz-pay-on-delivery@2.0.0-beta.11
|
|
17
|
+
- @akinon/pz-tabby-extension@2.0.0-beta.11
|
|
18
|
+
- @akinon/pz-credit-payment@2.0.0-beta.11
|
|
19
|
+
- @akinon/pz-click-collect@2.0.0-beta.11
|
|
20
|
+
- @akinon/pz-masterpass@2.0.0-beta.11
|
|
21
|
+
- @akinon/pz-saved-card@2.0.0-beta.11
|
|
22
|
+
- @akinon/next@2.0.0-beta.11
|
|
23
|
+
- @akinon/pz-akifast@2.0.0-beta.11
|
|
24
|
+
- @akinon/pz-gpay@2.0.0-beta.11
|
|
25
|
+
- @akinon/pz-b2b@2.0.0-beta.11
|
|
26
|
+
- @akinon/pz-bkm@2.0.0-beta.11
|
|
27
|
+
- @akinon/pz-otp@2.0.0-beta.11
|
|
28
|
+
|
|
3
29
|
## 2.0.0-beta.10
|
|
4
30
|
|
|
5
31
|
### Minor Changes
|
|
@@ -15,13 +15,18 @@ The plugins selected from this list will be added to the project and ready for u
|
|
|
15
15
|
|
|
16
16
|
### Plugin List
|
|
17
17
|
|
|
18
|
-
1.
|
|
19
|
-
2.
|
|
18
|
+
1. Basket Gift Pack
|
|
19
|
+
2. Click & Collect
|
|
20
20
|
3. Checkout Gift Pack
|
|
21
|
-
4. Checkout
|
|
22
|
-
5.
|
|
23
|
-
6.
|
|
24
|
-
7.
|
|
21
|
+
4. One Click Checkout
|
|
22
|
+
5. Garanti Pay
|
|
23
|
+
6. Pay On Delivery
|
|
24
|
+
7. OTP
|
|
25
|
+
8. BKM Express
|
|
26
|
+
9. Credit Payment
|
|
27
|
+
10. Multi Basket
|
|
28
|
+
11. Tabby Payment Extension
|
|
29
|
+
12. Tamara Payment Extension
|
|
25
30
|
|
|
26
31
|
## Installation
|
|
27
32
|
|
|
@@ -33,44 +38,74 @@ The plugins selected from this list will be added to the project and ready for u
|
|
|
33
38
|
|
|
34
39
|
2. Select the plugins desire to install from the list provided.
|
|
35
40
|
|
|
36
|
-
###
|
|
41
|
+
### Basket Gift Pack
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
Adds a gift pack and/or a gift note to products in the basket. Enhances the gifting experience for customers.
|
|
39
44
|
|
|
40
|
-
[Click here for details](https://
|
|
45
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-basket-gift-pack)
|
|
41
46
|
|
|
42
|
-
###
|
|
47
|
+
### Click & Collect
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
Allows customers to place an order online and pick it up from a selected store. Reduces delivery costs and improves convenience for users.
|
|
45
50
|
|
|
46
|
-
[Click here for details](https://
|
|
51
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-click-collect)
|
|
47
52
|
|
|
48
53
|
### Checkout Gift Pack
|
|
49
54
|
|
|
50
|
-
|
|
55
|
+
Enables a gift pack option on the payment page. Customers can choose to wrap their purchases as gifts during checkout.
|
|
56
|
+
|
|
57
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-checkout-gift-pack)
|
|
58
|
+
|
|
59
|
+
### One Click Checkout
|
|
51
60
|
|
|
52
|
-
|
|
61
|
+
Simplifies the checkout process by adding one-click payment methods.
|
|
53
62
|
|
|
54
|
-
|
|
63
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-one-click-checkout)
|
|
55
64
|
|
|
56
|
-
|
|
65
|
+
### Garanti Pay
|
|
57
66
|
|
|
58
|
-
|
|
67
|
+
Allows Garanti Bank credit card users to make fast and secure payments without entering card details.
|
|
68
|
+
|
|
69
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-gpay)
|
|
70
|
+
|
|
71
|
+
### Pay On Delivery
|
|
72
|
+
|
|
73
|
+
Provides an option for customers to pay with cash or a credit card at the time of delivery.
|
|
74
|
+
|
|
75
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-pay-on-delivery)
|
|
59
76
|
|
|
60
77
|
### OTP
|
|
61
78
|
|
|
62
|
-
|
|
79
|
+
Adds SMS-based OTP (One-Time Password) verification for secure actions such as registration and updating profile information.
|
|
63
80
|
|
|
64
|
-
[Click here for details](https://
|
|
81
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-otp)
|
|
65
82
|
|
|
66
|
-
###
|
|
83
|
+
### BKM Express
|
|
67
84
|
|
|
68
|
-
|
|
85
|
+
Integrates the BKM Express payment method for users to make fast and secure payments without entering card details.
|
|
69
86
|
|
|
70
|
-
[Click here for details](https://
|
|
87
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-bkm)
|
|
71
88
|
|
|
72
|
-
###
|
|
89
|
+
### Credit Payment
|
|
90
|
+
|
|
91
|
+
Supports credit card payments with installment and non-installment options.
|
|
92
|
+
|
|
93
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-credit-payment)
|
|
94
|
+
|
|
95
|
+
### Multi Basket
|
|
96
|
+
|
|
97
|
+
Enables customers to create and manage multiple virtual baskets at the same time. Facilitates better basket organization.
|
|
98
|
+
|
|
99
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-multi-basket)
|
|
100
|
+
|
|
101
|
+
### Tabby Payment Extension
|
|
102
|
+
|
|
103
|
+
Integrates Tabby’s installment and deferred payment solutions into the checkout.
|
|
104
|
+
|
|
105
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-tabby-extension)
|
|
106
|
+
|
|
107
|
+
### Tamara Payment Extension
|
|
73
108
|
|
|
74
|
-
|
|
109
|
+
Adds Tamara’s "Buy Now, Pay Later" feature to the payment options. Customers can defer payments while ensuring a seamless checkout experience.
|
|
75
110
|
|
|
76
|
-
[Click here for details](https://
|
|
111
|
+
[Click here for details](https://www.npmjs.com/package/@akinon/pz-tamara-extension)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const nextJest = require('next/jest');
|
|
2
|
-
import type {
|
|
2
|
+
import type { JestConfigWithTsJest } from 'ts-jest';
|
|
3
3
|
|
|
4
4
|
const createJestConfig = nextJest({
|
|
5
5
|
dir: './'
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
-
const config:
|
|
8
|
+
const config: JestConfigWithTsJest = {
|
|
9
9
|
preset: 'ts-jest',
|
|
10
10
|
setupFilesAfterEnv: ['<rootDir>/setupTests.ts'],
|
|
11
11
|
transform: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projectzeronext",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.11",
|
|
4
4
|
"private": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -24,29 +24,29 @@
|
|
|
24
24
|
"test:middleware": "jest middleware-matcher.test.ts --bail"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@akinon/next": "2.0.0-beta.
|
|
28
|
-
"@akinon/pz-akifast": "2.0.0-beta.
|
|
29
|
-
"@akinon/pz-b2b": "2.0.0-beta.
|
|
30
|
-
"@akinon/pz-basket-gift-pack": "2.0.0-beta.
|
|
31
|
-
"@akinon/pz-bkm": "2.0.0-beta.
|
|
32
|
-
"@akinon/pz-checkout-gift-pack": "2.0.0-beta.
|
|
33
|
-
"@akinon/pz-click-collect": "2.0.0-beta.
|
|
34
|
-
"@akinon/pz-credit-payment": "2.0.0-beta.
|
|
35
|
-
"@akinon/pz-gpay": "2.0.0-beta.
|
|
36
|
-
"@akinon/pz-masterpass": "2.0.0-beta.
|
|
37
|
-
"@akinon/pz-one-click-checkout": "2.0.0-beta.
|
|
38
|
-
"@akinon/pz-otp": "2.0.0-beta.
|
|
39
|
-
"@akinon/pz-pay-on-delivery": "2.0.0-beta.
|
|
40
|
-
"@akinon/pz-saved-card": "2.0.0-beta.
|
|
41
|
-
"@akinon/pz-tabby-extension": "2.0.0-beta.
|
|
42
|
-
"@akinon/pz-tamara-extension": "2.0.0-beta.
|
|
27
|
+
"@akinon/next": "2.0.0-beta.11",
|
|
28
|
+
"@akinon/pz-akifast": "2.0.0-beta.11",
|
|
29
|
+
"@akinon/pz-b2b": "2.0.0-beta.11",
|
|
30
|
+
"@akinon/pz-basket-gift-pack": "2.0.0-beta.11",
|
|
31
|
+
"@akinon/pz-bkm": "2.0.0-beta.11",
|
|
32
|
+
"@akinon/pz-checkout-gift-pack": "2.0.0-beta.11",
|
|
33
|
+
"@akinon/pz-click-collect": "2.0.0-beta.11",
|
|
34
|
+
"@akinon/pz-credit-payment": "2.0.0-beta.11",
|
|
35
|
+
"@akinon/pz-gpay": "2.0.0-beta.11",
|
|
36
|
+
"@akinon/pz-masterpass": "2.0.0-beta.11",
|
|
37
|
+
"@akinon/pz-one-click-checkout": "2.0.0-beta.11",
|
|
38
|
+
"@akinon/pz-otp": "2.0.0-beta.11",
|
|
39
|
+
"@akinon/pz-pay-on-delivery": "2.0.0-beta.11",
|
|
40
|
+
"@akinon/pz-saved-card": "2.0.0-beta.11",
|
|
41
|
+
"@akinon/pz-tabby-extension": "2.0.0-beta.11",
|
|
42
|
+
"@akinon/pz-tamara-extension": "2.0.0-beta.11",
|
|
43
43
|
"@hookform/resolvers": "2.9.0",
|
|
44
44
|
"@next/third-parties": "14.1.0",
|
|
45
45
|
"@react-google-maps/api": "2.17.1",
|
|
46
46
|
"@tailwindcss/postcss": "4.0.0",
|
|
47
47
|
"dayjs": "1.11.5",
|
|
48
48
|
"lossless-json": "2.0.5",
|
|
49
|
-
"next": "15.3.
|
|
49
|
+
"next": "15.3.4",
|
|
50
50
|
"next-auth": "4.24.11",
|
|
51
51
|
"next-pwa": "5.6.0",
|
|
52
52
|
"pino": "8.11.0",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"yup": "0.32.11"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@akinon/eslint-plugin-projectzero": "2.0.0-beta.
|
|
66
|
+
"@akinon/eslint-plugin-projectzero": "2.0.0-beta.11",
|
|
67
67
|
"@semantic-release/changelog": "6.0.2",
|
|
68
68
|
"@semantic-release/exec": "6.0.3",
|
|
69
69
|
"@semantic-release/git": "10.0.1",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"stylelint-config-standard": "25.0.0",
|
|
101
101
|
"stylelint-scss": "4.2.0",
|
|
102
102
|
"stylelint-selector-bem-pattern": "2.1.1",
|
|
103
|
-
"tailwindcss": "4.1.
|
|
103
|
+
"tailwindcss": "4.1.11",
|
|
104
104
|
"ts-jest": "29.1.1",
|
|
105
105
|
"ts-node": "10.7.0",
|
|
106
106
|
"typescript": "5.7.2"
|
|
@@ -237,13 +237,13 @@ const AccountOrderCancellation = ({ params }) => {
|
|
|
237
237
|
<div>
|
|
238
238
|
<div className="pb-2 mb-3 text-lg border-gray border-b">
|
|
239
239
|
<span data-testid="account-orders-return-order-count">
|
|
240
|
-
{order
|
|
240
|
+
{order?.orderitem_set?.length}
|
|
241
241
|
</span>{' '}
|
|
242
242
|
<span>{t('account.my_orders.detail.products')}</span>
|
|
243
243
|
</div>
|
|
244
244
|
|
|
245
245
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
246
|
-
{order
|
|
246
|
+
{order?.orderitem_set?.map((item, index: number) => (
|
|
247
247
|
<Controller
|
|
248
248
|
defaultValue={[]}
|
|
249
249
|
control={control}
|
|
@@ -254,7 +254,7 @@ const AccountOrderCancellation = ({ params }) => {
|
|
|
254
254
|
return cancelItem.order_item === item.id;
|
|
255
255
|
});
|
|
256
256
|
|
|
257
|
-
const cancellationType = item
|
|
257
|
+
const cancellationType = item?.is_refundable
|
|
258
258
|
? 'refund'
|
|
259
259
|
: 'cancel';
|
|
260
260
|
|
|
@@ -270,7 +270,10 @@ const AccountOrderCancellation = ({ params }) => {
|
|
|
270
270
|
onChange={onChange}
|
|
271
271
|
value={value}
|
|
272
272
|
selectOption={selectOption}
|
|
273
|
-
fileInput={fileInputCondition(
|
|
273
|
+
fileInput={fileInputCondition(
|
|
274
|
+
item,
|
|
275
|
+
item?.product?.name
|
|
276
|
+
)}
|
|
274
277
|
/>
|
|
275
278
|
);
|
|
276
279
|
}}
|
|
@@ -33,14 +33,15 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
33
33
|
const groupedOrder = [];
|
|
34
34
|
|
|
35
35
|
if (order) {
|
|
36
|
-
const groupedData =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
groups[tracking_number]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
const groupedData =
|
|
37
|
+
order?.orderitem_set?.reduce((groups, item) => {
|
|
38
|
+
const { tracking_number } = item;
|
|
39
|
+
if (!groups[tracking_number]) {
|
|
40
|
+
groups[tracking_number] = [];
|
|
41
|
+
}
|
|
42
|
+
groups[tracking_number].push(item);
|
|
43
|
+
return groups;
|
|
44
|
+
}, {}) || {};
|
|
44
45
|
|
|
45
46
|
const result = Object.values(groupedData);
|
|
46
47
|
|
|
@@ -77,8 +78,8 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
77
78
|
|
|
78
79
|
<div>
|
|
79
80
|
<span className="text-base font-bold">
|
|
80
|
-
{order?.orderitem_set
|
|
81
|
-
{t('account.my_orders.detail.products')} {groupedOrder
|
|
81
|
+
{order?.orderitem_set?.length}{' '}
|
|
82
|
+
{t('account.my_orders.detail.products')} {groupedOrder?.length}{' '}
|
|
82
83
|
{t('account.my_orders.detail.packages')}
|
|
83
84
|
</span>
|
|
84
85
|
</div>
|
|
@@ -88,16 +89,17 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
88
89
|
className="break-words"
|
|
89
90
|
>
|
|
90
91
|
<span>{t('account.my_orders.detail.delivery_address')}</span>:{' '}
|
|
91
|
-
{order
|
|
92
|
-
{order
|
|
93
|
-
{order
|
|
92
|
+
{order?.shipping_address?.line}{' '}
|
|
93
|
+
{order?.shipping_address?.district?.name}{' '}
|
|
94
|
+
{order?.shipping_address?.township?.name}{' '}
|
|
95
|
+
{order?.shipping_address?.city?.name}
|
|
94
96
|
</div>
|
|
95
97
|
</OrderDetailHeader>
|
|
96
98
|
|
|
97
99
|
<div>
|
|
98
100
|
{groupedOrder.map((group, i) => {
|
|
99
101
|
const orderStatus = getOrderStatus(
|
|
100
|
-
group[0]
|
|
102
|
+
group[0]?.status?.value?.toString(),
|
|
101
103
|
t
|
|
102
104
|
);
|
|
103
105
|
|
|
@@ -121,8 +123,8 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
121
123
|
<div className="flex justify-between items-center lg:gap-x-12">
|
|
122
124
|
<div className="text-base">{orderStatus.label}</div>
|
|
123
125
|
|
|
124
|
-
{group[0]
|
|
125
|
-
<Link href={group[0]
|
|
126
|
+
{group[0]?.tracking_number && group[0]?.tracking_url && (
|
|
127
|
+
<Link href={group[0]?.tracking_url}>
|
|
126
128
|
<Button className="px-7" appearance="filled">
|
|
127
129
|
{t('account.my_orders.detail.track_shipment')}
|
|
128
130
|
</Button>
|
|
@@ -134,7 +136,7 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
134
136
|
<div className="px-4 lg:px-7">
|
|
135
137
|
{group.map((item, index) => {
|
|
136
138
|
const itemStatus = getOrderStatus(
|
|
137
|
-
item
|
|
139
|
+
item?.status?.value?.toString(),
|
|
138
140
|
t
|
|
139
141
|
);
|
|
140
142
|
|
|
@@ -147,15 +149,15 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
147
149
|
<div className="shrink-0">
|
|
148
150
|
<Link
|
|
149
151
|
className="block"
|
|
150
|
-
href={item
|
|
152
|
+
href={item?.product?.absolute_url}
|
|
151
153
|
>
|
|
152
154
|
<Image
|
|
153
155
|
src={
|
|
154
|
-
item
|
|
156
|
+
item?.product?.image
|
|
155
157
|
? item.product.image
|
|
156
158
|
: '/noimage.jpg'
|
|
157
159
|
}
|
|
158
|
-
alt={item
|
|
160
|
+
alt={item?.product?.name}
|
|
159
161
|
width={112}
|
|
160
162
|
height={150}
|
|
161
163
|
/>
|
|
@@ -164,33 +166,33 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
164
166
|
|
|
165
167
|
<div className="flex flex-col justify-between lg:max-w-48">
|
|
166
168
|
<div className="text-sm">
|
|
167
|
-
<Link href={item
|
|
168
|
-
{item
|
|
169
|
+
<Link href={item?.product?.absolute_url}>
|
|
170
|
+
{item?.product?.name}
|
|
169
171
|
</Link>
|
|
170
172
|
</div>
|
|
171
173
|
|
|
172
174
|
<div className="text-gray-900 text-xs">
|
|
173
|
-
{item
|
|
175
|
+
{item?.product?.attributes?.filterable_color && (
|
|
174
176
|
<div>
|
|
175
177
|
<span>
|
|
176
178
|
{t('account.my_orders.detail.color')}
|
|
177
179
|
</span>
|
|
178
|
-
: {item
|
|
180
|
+
: {item?.product?.attributes?.filterable_color}
|
|
179
181
|
</div>
|
|
180
182
|
)}
|
|
181
183
|
|
|
182
|
-
{item
|
|
184
|
+
{item?.product?.attributes?.size && (
|
|
183
185
|
<div>
|
|
184
186
|
<span>
|
|
185
187
|
{t('account.my_orders.detail.size')}
|
|
186
188
|
</span>
|
|
187
|
-
:{item
|
|
189
|
+
:{item?.product?.attributes?.size}
|
|
188
190
|
</div>
|
|
189
191
|
)}
|
|
190
192
|
|
|
191
193
|
<div>
|
|
192
194
|
<span>{t('account.my_orders.detail.code')}</span>:{' '}
|
|
193
|
-
{item
|
|
195
|
+
{item?.product?.base_code}
|
|
194
196
|
</div>
|
|
195
197
|
</div>
|
|
196
198
|
</div>
|
|
@@ -207,11 +209,11 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
207
209
|
{itemStatus.label}
|
|
208
210
|
</div>
|
|
209
211
|
|
|
210
|
-
{(item
|
|
211
|
-
order
|
|
212
|
+
{(item?.is_cancellable || item?.is_refundable) &&
|
|
213
|
+
order?.is_cancellable && (
|
|
212
214
|
<div className="lg:ml-24">
|
|
213
215
|
<Link
|
|
214
|
-
href={`${ROUTES.ACCOUNT_ORDERS}/${order
|
|
216
|
+
href={`${ROUTES.ACCOUNT_ORDERS}/${order?.id}/cancellation`}
|
|
215
217
|
>
|
|
216
218
|
<Button
|
|
217
219
|
className="px-4 uppercase font-bold h-7"
|
|
@@ -227,21 +229,21 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
227
229
|
)}
|
|
228
230
|
</div>
|
|
229
231
|
<div className="flex flex-col justify-center items-end lg:ml-6 lg:min-w-[7rem]">
|
|
230
|
-
{parseFloat(item
|
|
231
|
-
parseFloat(item
|
|
232
|
+
{parseFloat(item?.retail_price || '0') >
|
|
233
|
+
parseFloat(item?.price || '0') && (
|
|
232
234
|
<Price
|
|
233
235
|
className="font-normal line-through"
|
|
234
|
-
value={item
|
|
236
|
+
value={item?.retail_price}
|
|
235
237
|
/>
|
|
236
238
|
)}
|
|
237
239
|
|
|
238
240
|
<Price
|
|
239
241
|
className={clsx('font-normal', {
|
|
240
242
|
'text-secondary-600':
|
|
241
|
-
parseFloat(item
|
|
242
|
-
parseFloat(item
|
|
243
|
+
parseFloat(item?.retail_price || '0') >
|
|
244
|
+
parseFloat(item?.price || '0')
|
|
243
245
|
})}
|
|
244
|
-
value={item
|
|
246
|
+
value={item?.price}
|
|
245
247
|
/>
|
|
246
248
|
</div>
|
|
247
249
|
</div>
|
|
@@ -325,29 +327,29 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
325
327
|
<div className="flex justify-between text-sm text-black-700 mb-2">
|
|
326
328
|
<p>
|
|
327
329
|
<span>{t('account.my_orders.detail.subtotal')}</span> (
|
|
328
|
-
{order
|
|
330
|
+
{order?.orderitem_set?.length}{' '}
|
|
329
331
|
<span>{t('account.my_orders.detail.items')}</span>)
|
|
330
332
|
</p>
|
|
331
333
|
|
|
332
334
|
<Price
|
|
333
335
|
className="font-normal min-w-max"
|
|
334
336
|
value={
|
|
335
|
-
parseFloat(order
|
|
336
|
-
parseFloat(order
|
|
337
|
+
parseFloat(order?.amount_without_discount || '0') -
|
|
338
|
+
parseFloat(order?.shipping_amount || '0')
|
|
337
339
|
}
|
|
338
340
|
/>
|
|
339
341
|
</div>
|
|
340
342
|
|
|
341
|
-
{order
|
|
342
|
-
order
|
|
343
|
+
{order?.discountitem_set &&
|
|
344
|
+
order?.discountitem_set?.map((item, index) => (
|
|
343
345
|
<div
|
|
344
346
|
className="flex justify-between text-sm text-black-700 mb-2"
|
|
345
347
|
key={index}
|
|
346
348
|
>
|
|
347
|
-
<p>{item
|
|
349
|
+
<p>{item?.name}</p>
|
|
348
350
|
<Price
|
|
349
351
|
className="font-normal min-w-max"
|
|
350
|
-
value={item
|
|
352
|
+
value={item?.amount}
|
|
351
353
|
useNegative
|
|
352
354
|
/>
|
|
353
355
|
</div>
|
|
@@ -360,7 +362,8 @@ const AccountOrderDetail = ({ params }) => {
|
|
|
360
362
|
className="font-normal min-w-max"
|
|
361
363
|
data-testid="account-orders-detail-total"
|
|
362
364
|
value={
|
|
363
|
-
parseFloat(order
|
|
365
|
+
parseFloat(order?.amount || '0') -
|
|
366
|
+
parseFloat(order?.shipping_amount || '0')
|
|
364
367
|
}
|
|
365
368
|
/>
|
|
366
369
|
</div>
|
|
@@ -35,7 +35,7 @@ export const Button = (props: ButtonProps) => {
|
|
|
35
35
|
|
|
36
36
|
const buttonClasses = twMerge(
|
|
37
37
|
clsx(
|
|
38
|
-
'px-4 text-xs transition-all duration-200',
|
|
38
|
+
'px-4 text-xs transition-all duration-200 cursor-pointer',
|
|
39
39
|
'inline-flex gap-2 justify-center items-center',
|
|
40
40
|
variants[appearance],
|
|
41
41
|
sizes[size],
|
|
@@ -54,7 +54,7 @@ export const Button = (props: ButtonProps) => {
|
|
|
54
54
|
{children}
|
|
55
55
|
</Link>
|
|
56
56
|
) : (
|
|
57
|
-
<button {...rest} className={buttonClasses}>
|
|
57
|
+
<button data-testid="button" {...rest} className={buttonClasses}>
|
|
58
58
|
{children}
|
|
59
59
|
</button>
|
|
60
60
|
);
|
|
@@ -9,6 +9,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
|
|
9
9
|
<label className={twMerge('flex flex-col text-xs', props.className)}>
|
|
10
10
|
<div className="flex items-center">
|
|
11
11
|
<input
|
|
12
|
+
data-testid="checkbox"
|
|
12
13
|
type="checkbox"
|
|
13
14
|
{...rest}
|
|
14
15
|
ref={ref}
|
|
@@ -13,7 +13,7 @@ export const Order = (props) => {
|
|
|
13
13
|
.reverse()
|
|
14
14
|
.join(' ');
|
|
15
15
|
|
|
16
|
-
const orderStatus = getOrderStatus(props
|
|
16
|
+
const orderStatus = getOrderStatus(props?.status?.value?.toString(), t);
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
19
|
<div className="border border-gray px-5 py-4 text-sm mb-4 last:mb-0">
|
|
@@ -58,30 +58,32 @@ export const Order = (props) => {
|
|
|
58
58
|
|
|
59
59
|
<div className="w-full flex flex-col justify-between mt-6 mb-2 order-3 md:items-center md:flex-row md:order-none md:gap-20 lg:gap-40">
|
|
60
60
|
<ul className="flex flex-wrap gap-3.5 mb-6 items-center md:mb-0">
|
|
61
|
-
{props
|
|
61
|
+
{props?.orderitem_set?.slice(0, 3).map((item, index) => (
|
|
62
62
|
// TODO: Static image will change (TR)
|
|
63
63
|
<li className="shrink-0" key={index}>
|
|
64
64
|
<Image
|
|
65
|
-
src={
|
|
66
|
-
|
|
65
|
+
src={
|
|
66
|
+
item?.product?.image ? item.product.image : '/noimage.jpg'
|
|
67
|
+
}
|
|
68
|
+
alt={item?.product?.name}
|
|
67
69
|
width={64}
|
|
68
70
|
height={96}
|
|
69
71
|
/>
|
|
70
72
|
</li>
|
|
71
73
|
))}
|
|
72
|
-
{props
|
|
73
|
-
<div>+ {props
|
|
74
|
+
{props?.orderitem_set?.length > 3 && (
|
|
75
|
+
<div>+ {props?.orderitem_set?.length - 3}</div>
|
|
74
76
|
)}
|
|
75
77
|
</ul>
|
|
76
78
|
|
|
77
|
-
<span className={orderStatus
|
|
79
|
+
<span className={orderStatus?.className}>{orderStatus?.label}</span>
|
|
78
80
|
</div>
|
|
79
81
|
|
|
80
82
|
<div
|
|
81
83
|
className="order-2 flex items-end md:order-none"
|
|
82
84
|
data-testid="account-orders-count"
|
|
83
85
|
>
|
|
84
|
-
{props
|
|
86
|
+
{props?.orderitem_set?.length} {t('account.my_orders.order.items')}
|
|
85
87
|
</div>
|
|
86
88
|
</div>
|
|
87
89
|
</div>
|
|
@@ -22,14 +22,15 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
22
22
|
const groupedOrder = [];
|
|
23
23
|
|
|
24
24
|
if (order) {
|
|
25
|
-
const groupedData =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
groups[tracking_number]
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
const groupedData =
|
|
26
|
+
order?.orderitem_set?.reduce((groups, item) => {
|
|
27
|
+
const { tracking_number } = item;
|
|
28
|
+
if (!groups[tracking_number]) {
|
|
29
|
+
groups[tracking_number] = [];
|
|
30
|
+
}
|
|
31
|
+
groups[tracking_number].push(item);
|
|
32
|
+
return groups;
|
|
33
|
+
}, {}) || {};
|
|
33
34
|
|
|
34
35
|
const result = Object.values(groupedData);
|
|
35
36
|
|
|
@@ -67,8 +68,8 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
67
68
|
|
|
68
69
|
<div>
|
|
69
70
|
<span className="text-base font-bold">
|
|
70
|
-
{order
|
|
71
|
-
{t('account.my_orders.detail.products')} {groupedOrder
|
|
71
|
+
{order?.orderitem_set?.length}{' '}
|
|
72
|
+
{t('account.my_orders.detail.products')} {groupedOrder?.length}{' '}
|
|
72
73
|
{t('account.my_orders.detail.packages')}
|
|
73
74
|
</span>
|
|
74
75
|
</div>
|
|
@@ -78,17 +79,17 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
78
79
|
className="break-words"
|
|
79
80
|
>
|
|
80
81
|
<span>{t('account.my_orders.detail.delivery_address')}</span>:{' '}
|
|
81
|
-
{order?.shipping_address
|
|
82
|
-
{order?.shipping_address
|
|
83
|
-
{order?.shipping_address
|
|
84
|
-
{order?.shipping_address
|
|
82
|
+
{order?.shipping_address?.line}{' '}
|
|
83
|
+
{order?.shipping_address?.district?.name}{' '}
|
|
84
|
+
{order?.shipping_address?.township?.name}{' '}
|
|
85
|
+
{order?.shipping_address?.city?.name}
|
|
85
86
|
</div>
|
|
86
87
|
</OrderDetailHeader>
|
|
87
88
|
|
|
88
89
|
<div>
|
|
89
90
|
{groupedOrder.map((group, i) => {
|
|
90
91
|
const orderStatus = getOrderStatus(
|
|
91
|
-
group[0]
|
|
92
|
+
group[0]?.status?.value?.toString(),
|
|
92
93
|
t
|
|
93
94
|
);
|
|
94
95
|
|
|
@@ -112,8 +113,8 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
112
113
|
<div className="flex justify-between items-center lg:gap-x-12">
|
|
113
114
|
<div className="text-base">{orderStatus.label}</div>
|
|
114
115
|
|
|
115
|
-
{group[0]
|
|
116
|
-
<Link href={group[0]
|
|
116
|
+
{group[0]?.tracking_number && group[0]?.tracking_url && (
|
|
117
|
+
<Link href={group[0]?.tracking_url}>
|
|
117
118
|
<Button className="px-7" appearance="filled">
|
|
118
119
|
{t('account.my_orders.detail.track_shipment')}
|
|
119
120
|
</Button>
|
|
@@ -125,7 +126,7 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
125
126
|
<div className="px-4 lg:px-7">
|
|
126
127
|
{group.map((item, index) => {
|
|
127
128
|
const itemStatus = getOrderStatus(
|
|
128
|
-
item
|
|
129
|
+
item?.status?.value?.toString(),
|
|
129
130
|
t
|
|
130
131
|
);
|
|
131
132
|
|
|
@@ -138,15 +139,15 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
138
139
|
<div className="shrink-0">
|
|
139
140
|
<Link
|
|
140
141
|
className="block"
|
|
141
|
-
href={item
|
|
142
|
+
href={item?.product?.absolute_url}
|
|
142
143
|
>
|
|
143
144
|
<Image
|
|
144
145
|
src={
|
|
145
|
-
item
|
|
146
|
+
item?.product?.image
|
|
146
147
|
? item.product.image
|
|
147
148
|
: '/noimage.jpg'
|
|
148
149
|
}
|
|
149
|
-
alt={item
|
|
150
|
+
alt={item?.product?.name}
|
|
150
151
|
width={112}
|
|
151
152
|
height={150}
|
|
152
153
|
/>
|
|
@@ -155,27 +156,32 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
155
156
|
|
|
156
157
|
<div className="flex flex-col justify-between lg:max-w-48">
|
|
157
158
|
<div className="text-sm">
|
|
158
|
-
<Link href={item
|
|
159
|
-
{item
|
|
159
|
+
<Link href={item?.product?.absolute_url}>
|
|
160
|
+
{item?.product?.name}
|
|
160
161
|
</Link>
|
|
161
162
|
</div>
|
|
162
163
|
|
|
163
164
|
<div className="text-gray-900 text-xs">
|
|
164
|
-
{item
|
|
165
|
+
{item?.product?.attributes
|
|
166
|
+
?.filterable_color && (
|
|
165
167
|
<div>
|
|
166
168
|
<span>
|
|
167
169
|
{t('account.my_orders.detail.color')}
|
|
168
170
|
</span>
|
|
169
|
-
:
|
|
171
|
+
:{' '}
|
|
172
|
+
{
|
|
173
|
+
item?.product?.attributes
|
|
174
|
+
?.filterable_color
|
|
175
|
+
}
|
|
170
176
|
</div>
|
|
171
177
|
)}
|
|
172
178
|
|
|
173
|
-
{item
|
|
179
|
+
{item?.product?.attributes?.size && (
|
|
174
180
|
<div>
|
|
175
181
|
<span>
|
|
176
182
|
{t('account.my_orders.detail.size')}
|
|
177
183
|
</span>
|
|
178
|
-
:{item
|
|
184
|
+
:{item?.product?.attributes?.size}
|
|
179
185
|
</div>
|
|
180
186
|
)}
|
|
181
187
|
|
|
@@ -183,7 +189,7 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
183
189
|
<span>
|
|
184
190
|
{t('account.my_orders.detail.code')}
|
|
185
191
|
</span>
|
|
186
|
-
: {item
|
|
192
|
+
: {item?.product?.base_code}
|
|
187
193
|
</div>
|
|
188
194
|
</div>
|
|
189
195
|
</div>
|
|
@@ -202,7 +208,7 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
202
208
|
|
|
203
209
|
{(item.is_cancellable || item.is_refundable) &&
|
|
204
210
|
order.is_cancellable &&
|
|
205
|
-
item
|
|
211
|
+
item?.status?.value == '400' && (
|
|
206
212
|
<div className="lg:ml-24">
|
|
207
213
|
<Link
|
|
208
214
|
href={`${ROUTES.ACCOUNT_ORDERS}/${order.id}/cancellation`}
|
|
@@ -256,29 +262,29 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
256
262
|
<div className="flex justify-between text-sm text-black-700 mb-2">
|
|
257
263
|
<p>
|
|
258
264
|
<span>{t('account.my_orders.detail.subtotal')}</span> (
|
|
259
|
-
{order?.orderitem_set
|
|
265
|
+
{order?.orderitem_set?.length}{' '}
|
|
260
266
|
<span>{t('account.my_orders.detail.items')}</span>)
|
|
261
267
|
</p>
|
|
262
268
|
|
|
263
269
|
<Price
|
|
264
270
|
className="font-normal min-w-max"
|
|
265
271
|
value={
|
|
266
|
-
parseFloat(order
|
|
267
|
-
parseFloat(order
|
|
272
|
+
parseFloat(order?.amount_without_discount || '0') -
|
|
273
|
+
parseFloat(order?.shipping_amount || '0')
|
|
268
274
|
}
|
|
269
275
|
/>
|
|
270
276
|
</div>
|
|
271
277
|
|
|
272
|
-
{order
|
|
273
|
-
order
|
|
278
|
+
{order?.discountitem_set &&
|
|
279
|
+
order?.discountitem_set?.map((item, index) => (
|
|
274
280
|
<div
|
|
275
281
|
className="flex justify-between text-sm text-black-700 mb-2"
|
|
276
282
|
key={index}
|
|
277
283
|
>
|
|
278
|
-
<p>{item
|
|
284
|
+
<p>{item?.name}</p>
|
|
279
285
|
<Price
|
|
280
286
|
className="font-normal min-w-max"
|
|
281
|
-
value={item
|
|
287
|
+
value={item?.amount}
|
|
282
288
|
useNegative
|
|
283
289
|
/>
|
|
284
290
|
</div>
|
|
@@ -291,7 +297,8 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
|
|
|
291
297
|
className="font-normal min-w-max"
|
|
292
298
|
data-testid="account-orders-detail-total"
|
|
293
299
|
value={
|
|
294
|
-
parseFloat(order
|
|
300
|
+
parseFloat(order?.amount || '0') -
|
|
301
|
+
parseFloat(order?.shipping_amount || '0')
|
|
295
302
|
}
|
|
296
303
|
/>
|
|
297
304
|
</div>
|
|
@@ -65,6 +65,7 @@ export default function RedirectionPayment() {
|
|
|
65
65
|
|
|
66
66
|
<Checkbox
|
|
67
67
|
className="px-4 md:px-0"
|
|
68
|
+
data-testid="checkout-agreement"
|
|
68
69
|
{...register('agreement')}
|
|
69
70
|
error={errors.agreement}
|
|
70
71
|
>
|
|
@@ -88,7 +89,10 @@ export default function RedirectionPayment() {
|
|
|
88
89
|
</div>
|
|
89
90
|
)}
|
|
90
91
|
|
|
91
|
-
<Button
|
|
92
|
+
<Button
|
|
93
|
+
data-testid="checkout-submit-button"
|
|
94
|
+
className={twMerge('w-full md:w-36 px-4 md:px-0')}
|
|
95
|
+
>
|
|
92
96
|
{payment_option.name}
|
|
93
97
|
</Button>
|
|
94
98
|
</form>
|
|
@@ -92,7 +92,11 @@ export default function ActionMenu() {
|
|
|
92
92
|
ref={menu.miniBasket ? miniBasketRef : null}
|
|
93
93
|
>
|
|
94
94
|
{menu.action ? (
|
|
95
|
-
<button
|
|
95
|
+
<button
|
|
96
|
+
onClick={menu.action}
|
|
97
|
+
data-testid={menu.dataTestId}
|
|
98
|
+
className="cursor-pointer"
|
|
99
|
+
>
|
|
96
100
|
<Icon name={menu.icon} size={24} />
|
|
97
101
|
{menu.badge}
|
|
98
102
|
</button>
|
|
@@ -13,7 +13,8 @@ export interface PriceProps {
|
|
|
13
13
|
export default function PriceWrapper(props: PriceProps) {
|
|
14
14
|
const { t } = useLocalization();
|
|
15
15
|
const { price, retailPrice } = props;
|
|
16
|
-
const hasRetailPrice =
|
|
16
|
+
const hasRetailPrice =
|
|
17
|
+
parseFloat(retailPrice || '0') > parseFloat(price || '0');
|
|
17
18
|
|
|
18
19
|
return (
|
|
19
20
|
<div className="flex items-center gap-3 justify-center h-full">
|
|
@@ -31,7 +32,11 @@ export default function PriceWrapper(props: PriceProps) {
|
|
|
31
32
|
{hasRetailPrice && (
|
|
32
33
|
<div className="flex flex-col items-center w-9 py-0.5 text-xs text-white bg-secondary">
|
|
33
34
|
<span className="font-bold">
|
|
34
|
-
{Math.round(
|
|
35
|
+
{Math.round(
|
|
36
|
+
100 -
|
|
37
|
+
(parseInt(price || '0') / parseInt(retailPrice || '1')) * 100
|
|
38
|
+
)}
|
|
39
|
+
%
|
|
35
40
|
</span>
|
|
36
41
|
<span>{t('product.off')}</span>
|
|
37
42
|
</div>
|
|
@@ -23,6 +23,7 @@ export default function ProductInfo({ data }: ProductPageProps) {
|
|
|
23
23
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
24
24
|
const [stockAlertResponseMessage, setStockAlertResponseMessage] =
|
|
25
25
|
useState(null);
|
|
26
|
+
const [isVariantLoading, setIsVariantLoading] = useState(false);
|
|
26
27
|
|
|
27
28
|
const [addProduct, { isLoading: isAddToCartLoading }] =
|
|
28
29
|
useAddProductToBasket();
|
|
@@ -30,6 +31,18 @@ export default function ProductInfo({ data }: ProductPageProps) {
|
|
|
30
31
|
useAddStockAlertMutation();
|
|
31
32
|
const inStock = data.selected_variant !== null || data.product.in_stock;
|
|
32
33
|
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
isVariantSelectionComplete() && setIsVariantLoading(false);
|
|
36
|
+
|
|
37
|
+
!inStock && setIsVariantLoading(false);
|
|
38
|
+
}, [data]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (isVariantLoading) {
|
|
42
|
+
setProductError(null);
|
|
43
|
+
}
|
|
44
|
+
}, [isVariantLoading]);
|
|
45
|
+
|
|
33
46
|
useEffect(() => {
|
|
34
47
|
setCurrentUrl(window.location.href);
|
|
35
48
|
}, [currentUrl]);
|
|
@@ -82,6 +95,12 @@ export default function ProductInfo({ data }: ProductPageProps) {
|
|
|
82
95
|
return true;
|
|
83
96
|
};
|
|
84
97
|
|
|
98
|
+
const isVariantSelectionComplete = () => {
|
|
99
|
+
return data?.variants.every((variant) =>
|
|
100
|
+
variant?.options.some((opt) => opt.is_selected)
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
85
104
|
const addProductToStockAlertList = async () => {
|
|
86
105
|
try {
|
|
87
106
|
await addStockAlert({
|
|
@@ -174,7 +193,10 @@ export default function ProductInfo({ data }: ProductPageProps) {
|
|
|
174
193
|
key={variant.attribute_key}
|
|
175
194
|
{...variant}
|
|
176
195
|
className="items-center mt-8"
|
|
177
|
-
onChange={() =>
|
|
196
|
+
onChange={() => {
|
|
197
|
+
setProductError(null);
|
|
198
|
+
setIsVariantLoading(true);
|
|
199
|
+
}}
|
|
178
200
|
/>
|
|
179
201
|
))}
|
|
180
202
|
</div>
|
|
@@ -186,7 +208,9 @@ export default function ProductInfo({ data }: ProductPageProps) {
|
|
|
186
208
|
)}
|
|
187
209
|
|
|
188
210
|
<Button
|
|
189
|
-
disabled={
|
|
211
|
+
disabled={
|
|
212
|
+
isAddToCartLoading || isAddToStockAlertLoading || isVariantLoading
|
|
213
|
+
}
|
|
190
214
|
className={clsx(
|
|
191
215
|
'fixed bottom-0 right-0 w-1/2 h-14 z-20 flex items-center justify-center fill-primary-foreground',
|
|
192
216
|
'hover:fill-primary sm:relative sm:w-full sm:mt-3 sm:font-semibold sm:h-12'
|
|
@@ -202,7 +226,13 @@ export default function ProductInfo({ data }: ProductPageProps) {
|
|
|
202
226
|
}}
|
|
203
227
|
data-testid="product-add-to-cart"
|
|
204
228
|
>
|
|
205
|
-
{
|
|
229
|
+
{isVariantLoading ? (
|
|
230
|
+
<Icon
|
|
231
|
+
name="spinner"
|
|
232
|
+
size={20}
|
|
233
|
+
className="animate-spin mr-4 fill-primary"
|
|
234
|
+
/>
|
|
235
|
+
) : inStock ? (
|
|
206
236
|
<span>{t('product.add_to_cart')}</span>
|
|
207
237
|
) : (
|
|
208
238
|
<>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const getAkinonNextContent = require('@akinon/next/tailwind/content');
|
|
1
2
|
const deepMerge = require('@akinon/next/utils/deep-merge');
|
|
2
3
|
const plugins = require('./src/plugins');
|
|
3
4
|
const fs = require('fs');
|
|
@@ -18,13 +19,16 @@ if (themeName !== 'default' && fs.existsSync(themeConfigPath)) {
|
|
|
18
19
|
|
|
19
20
|
const defaultConfig = {
|
|
20
21
|
content: [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
'./src/app/**/*.{js,ts,jsx,tsx}',
|
|
23
|
+
'./src/pages/**/*.{js,ts,jsx,tsx}',
|
|
24
|
+
'./src/components/**/*.{js,ts,jsx,tsx}',
|
|
25
|
+
'./src/views/**/*.{js,ts,jsx,tsx}',
|
|
26
|
+
'./src/widgets/**/*.{js,ts,jsx,tsx}',
|
|
27
|
+
'./src/hooks/**/*.{js,ts,jsx,tsx}',
|
|
28
|
+
'./src/utils/**/*.{js,ts,jsx,tsx}',
|
|
29
|
+
...getAkinonNextContent(plugins)
|
|
30
|
+
],
|
|
31
|
+
plugins: [require('@tailwindcss/typography')]
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
if (Object.keys(themeOverrides).length === 0) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const jscodeshift = require('jscodeshift/src/Runner');
|
|
3
|
+
|
|
4
|
+
const codemodScript = path.resolve(__dirname, 'transform.js');
|
|
5
|
+
|
|
6
|
+
const transform = () => {
|
|
7
|
+
const workingDir = path.resolve(process.cwd());
|
|
8
|
+
|
|
9
|
+
jscodeshift
|
|
10
|
+
.run(codemodScript, [workingDir], {
|
|
11
|
+
verbose: 0,
|
|
12
|
+
dry: false,
|
|
13
|
+
print: false,
|
|
14
|
+
extensions: 'js',
|
|
15
|
+
ignorePattern: '**/node_modules/**',
|
|
16
|
+
filter: '**/tailwind.config.js'
|
|
17
|
+
})
|
|
18
|
+
.then(
|
|
19
|
+
(stats) => {
|
|
20
|
+
console.log(`Codemod completed. Stats:`, stats);
|
|
21
|
+
},
|
|
22
|
+
(error) => {
|
|
23
|
+
console.error(`Error executing codemod: ${error.message}`);
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
transform
|
|
30
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
function transform(fileInfo, api) {
|
|
2
|
+
const j = api.jscodeshift;
|
|
3
|
+
const root = j(fileInfo.source);
|
|
4
|
+
|
|
5
|
+
if (!fileInfo.path.includes('tailwind.config.js')) {
|
|
6
|
+
return fileInfo.source;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
console.log(`Processing file: ${fileInfo.path}`);
|
|
10
|
+
|
|
11
|
+
const hasAkinonNextImport = root.find(j.VariableDeclarator, {
|
|
12
|
+
id: { name: 'getAkinonNextContent' }
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
if (hasAkinonNextImport.size() === 0) {
|
|
16
|
+
const requireStatement = j.variableDeclaration('const', [
|
|
17
|
+
j.variableDeclarator(
|
|
18
|
+
j.identifier('getAkinonNextContent'),
|
|
19
|
+
j.callExpression(j.identifier('require'), [
|
|
20
|
+
j.literal('@akinon/next/tailwind/content')
|
|
21
|
+
])
|
|
22
|
+
)
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
root.get().node.program.body.unshift(requireStatement);
|
|
26
|
+
|
|
27
|
+
console.log(`Added getAkinonNextContent import to ${fileInfo.path}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const defaultConfig = root
|
|
31
|
+
.find(j.VariableDeclarator, {
|
|
32
|
+
id: { name: 'defaultConfig' },
|
|
33
|
+
init: { type: 'ObjectExpression' }
|
|
34
|
+
})
|
|
35
|
+
.paths()[0];
|
|
36
|
+
|
|
37
|
+
if (!defaultConfig) {
|
|
38
|
+
console.log(`No defaultConfig found in ${fileInfo.path}`);
|
|
39
|
+
return fileInfo.source;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const contentArray = defaultConfig.value.init.properties.find(
|
|
43
|
+
(prop) =>
|
|
44
|
+
prop.key.name === 'content' && prop.value.type === 'ArrayExpression'
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (!contentArray) {
|
|
48
|
+
console.log(`No content array found in defaultConfig`);
|
|
49
|
+
return fileInfo.source;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const pluginsVarName = root
|
|
53
|
+
.find(j.VariableDeclarator, {
|
|
54
|
+
id: { name: 'plugins' },
|
|
55
|
+
init: {
|
|
56
|
+
type: 'CallExpression',
|
|
57
|
+
callee: { name: 'require' }
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
.paths()[0]?.value.id.name;
|
|
61
|
+
|
|
62
|
+
if (!pluginsVarName) {
|
|
63
|
+
console.log(`No plugins variable found in ${fileInfo.path}`);
|
|
64
|
+
return fileInfo.source;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const contentElements = contentArray.value.elements;
|
|
68
|
+
|
|
69
|
+
const filteredElements = contentElements.filter((element) => {
|
|
70
|
+
if (element.type === 'SpreadElement') {
|
|
71
|
+
if (
|
|
72
|
+
element.argument.type === 'CallExpression' &&
|
|
73
|
+
element.argument.callee.object?.callee.object.name === 'plugins'
|
|
74
|
+
) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (
|
|
79
|
+
element.argument.type === 'CallExpression' &&
|
|
80
|
+
element.argument.callee.name === 'getAkinonNextContent'
|
|
81
|
+
) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
filteredElements.push(
|
|
89
|
+
j.spreadElement(
|
|
90
|
+
j.callExpression(j.identifier('getAkinonNextContent'), [
|
|
91
|
+
j.identifier(pluginsVarName)
|
|
92
|
+
])
|
|
93
|
+
)
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
contentArray.value.elements = filteredElements;
|
|
97
|
+
|
|
98
|
+
console.log(`Successfully updated ${fileInfo.path}`);
|
|
99
|
+
return root.toSource();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = transform;
|
package/commands/codemod.ts
CHANGED
package/commands/plugins.ts
CHANGED
|
@@ -2,8 +2,7 @@ import * as fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import semver from 'semver';
|
|
5
|
-
|
|
6
|
-
const Prompt = require('prompt-checkbox');
|
|
5
|
+
import { checkbox } from '@inquirer/prompts';
|
|
7
6
|
|
|
8
7
|
const rootDir = path.resolve(process.cwd());
|
|
9
8
|
|
|
@@ -120,36 +119,25 @@ export default async () => {
|
|
|
120
119
|
}
|
|
121
120
|
];
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
answer.replace(/\d\)\s/, '')
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
const values = formattedAnswers.map(
|
|
139
|
-
(answer) => definedPlugins.find((p) => p.name === answer)?.value
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
if (formattedAnswers.length) {
|
|
143
|
-
console.log(`\nInstalling ${formattedAnswers.join(', ')}.`);
|
|
144
|
-
} else {
|
|
145
|
-
console.log(`\nUninstalling all plugins.`);
|
|
122
|
+
try {
|
|
123
|
+
const answers = await checkbox({
|
|
124
|
+
message: 'Please check/uncheck plugins to install/uninstall.',
|
|
125
|
+
choices: definedPlugins.map((plugin) => ({
|
|
126
|
+
name: plugin.name,
|
|
127
|
+
value: plugin.value,
|
|
128
|
+
checked: installedPlugins.includes(plugin.value)
|
|
129
|
+
}))
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (!answers.length) {
|
|
133
|
+
console.log('\x1b[33m%s\x1b[0m', `\nUninstalling all plugins.`);
|
|
146
134
|
}
|
|
147
135
|
|
|
148
|
-
console.log(`\nPlease wait...`);
|
|
136
|
+
console.log('\x1b[36m%s\x1b[0m', `\nPlease wait...`);
|
|
149
137
|
|
|
150
138
|
fs.writeFileSync(
|
|
151
139
|
pluginsFilePath,
|
|
152
|
-
`module.exports = ${JSON.stringify(
|
|
140
|
+
`module.exports = ${JSON.stringify(answers)};\n`,
|
|
153
141
|
{
|
|
154
142
|
encoding: 'utf-8'
|
|
155
143
|
}
|
|
@@ -159,11 +147,13 @@ export default async () => {
|
|
|
159
147
|
|
|
160
148
|
console.log(
|
|
161
149
|
'\x1b[32m%s\x1b[0m',
|
|
162
|
-
`\n
|
|
163
|
-
|
|
150
|
+
`\n✓ ${
|
|
151
|
+
answers.length
|
|
164
152
|
? 'Installed selected plugins'
|
|
165
153
|
: 'Uninstalled all plugins'
|
|
166
154
|
}.\n`
|
|
167
155
|
);
|
|
168
|
-
})
|
|
156
|
+
} catch (error) {
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
169
159
|
};
|
package/dist/commands/codemod.js
CHANGED
|
@@ -8,7 +8,6 @@ const yargs = require('yargs/yargs');
|
|
|
8
8
|
const { hideBin } = require('yargs/helpers');
|
|
9
9
|
const args = yargs(hideBin(process.argv)).argv;
|
|
10
10
|
exports.default = () => {
|
|
11
|
-
const workingDir = path_1.default.resolve(process.cwd());
|
|
12
11
|
const codemodName = args.codemod;
|
|
13
12
|
const codemodPath = path_1.default.resolve(__dirname, `../../codemods/${codemodName}/index.js`);
|
|
14
13
|
const codemod = require(codemodPath);
|
package/dist/commands/plugins.js
CHANGED
|
@@ -49,7 +49,7 @@ const fs = __importStar(require("fs"));
|
|
|
49
49
|
const path_1 = __importDefault(require("path"));
|
|
50
50
|
const child_process_1 = require("child_process");
|
|
51
51
|
const semver_1 = __importDefault(require("semver"));
|
|
52
|
-
const
|
|
52
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
53
53
|
const rootDir = path_1.default.resolve(process.cwd());
|
|
54
54
|
function checkVersion(pkg) {
|
|
55
55
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -143,29 +143,28 @@ exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
143
143
|
value: 'pz-tamara-extension'
|
|
144
144
|
}
|
|
145
145
|
];
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
console.log(`\nInstalling ${formattedAnswers.join(', ')}.`);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
console.log(`\nUninstalling all plugins.`);
|
|
146
|
+
try {
|
|
147
|
+
const answers = yield (0, prompts_1.checkbox)({
|
|
148
|
+
message: 'Please check/uncheck plugins to install/uninstall.',
|
|
149
|
+
choices: definedPlugins.map((plugin) => ({
|
|
150
|
+
name: plugin.name,
|
|
151
|
+
value: plugin.value,
|
|
152
|
+
checked: installedPlugins.includes(plugin.value)
|
|
153
|
+
}))
|
|
154
|
+
});
|
|
155
|
+
if (!answers.length) {
|
|
156
|
+
console.log('\x1b[33m%s\x1b[0m', `\nUninstalling all plugins.`);
|
|
161
157
|
}
|
|
162
|
-
console.log(`\nPlease wait...`);
|
|
163
|
-
fs.writeFileSync(pluginsFilePath, `module.exports = ${JSON.stringify(
|
|
158
|
+
console.log('\x1b[36m%s\x1b[0m', `\nPlease wait...`);
|
|
159
|
+
fs.writeFileSync(pluginsFilePath, `module.exports = ${JSON.stringify(answers)};\n`, {
|
|
164
160
|
encoding: 'utf-8'
|
|
165
161
|
});
|
|
166
162
|
(0, child_process_1.execSync)('yarn install', { stdio: 'pipe' });
|
|
167
|
-
console.log('\x1b[32m%s\x1b[0m', `\n
|
|
163
|
+
console.log('\x1b[32m%s\x1b[0m', `\n✓ ${answers.length
|
|
168
164
|
? 'Installed selected plugins'
|
|
169
165
|
: 'Uninstalled all plugins'}.\n`);
|
|
170
|
-
}
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
171
170
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/projectzero",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "CLI tool to manage your Project Zero Next project",
|
|
6
6
|
"bin": {
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
"@types/temp": "0.9.4"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
+
"jscodeshift": "^0.15.1",
|
|
23
|
+
"@inquirer/prompts": "7.5.0",
|
|
22
24
|
"loading-spinner": "1.2.1",
|
|
23
|
-
"prompt-checkbox": "2.2.0",
|
|
24
25
|
"semver": "7.6.2",
|
|
25
26
|
"temp": "0.9.4",
|
|
26
27
|
"yargs": "^17.6.0"
|