@akinon/projectzero 1.78.0-rc.2 → 1.78.0
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 +1 -15
- package/app-template/.gitignore +0 -2
- package/app-template/CHANGELOG.md +166 -2734
- package/app-template/package.json +18 -18
- package/app-template/public/locales/en/common.json +0 -4
- package/app-template/public/locales/tr/common.json +0 -4
- package/app-template/sentry.edge.config.ts +3 -0
- package/app-template/sentry.server.config.ts +3 -0
- package/app-template/src/app/[commerce]/[locale]/[currency]/account/orders/[id]/cancellation/page.tsx +5 -94
- package/app-template/src/app/[commerce]/[locale]/[currency]/basket/page.tsx +82 -9
- package/app-template/src/app/[commerce]/[locale]/[currency]/orders/checkout/page.tsx +4 -7
- package/app-template/src/app/[commerce]/[locale]/[currency]/page.tsx +0 -8
- package/app-template/src/components/button.tsx +35 -50
- package/app-template/src/components/file-input.tsx +2 -44
- package/app-template/src/components/types/index.ts +1 -4
- package/app-template/src/middleware.ts +0 -1
- package/app-template/src/settings.js +1 -6
- package/app-template/src/views/account/address-form.tsx +2 -2
- package/app-template/src/views/account/contact-form.tsx +8 -3
- package/app-template/src/views/account/orders/order-cancellation-item.tsx +3 -4
- package/app-template/src/views/basket/basket-item.tsx +13 -16
- package/app-template/src/views/basket/summary.tsx +7 -10
- package/app-template/src/views/login/index.tsx +4 -28
- package/app-template/src/views/register/index.tsx +5 -30
- package/package.json +1 -1
- package/app-template/src/components/widget/widget-placeholder.tsx +0 -12
- package/app-template/src/views/basket/basket-content.tsx +0 -106
|
@@ -8,8 +8,7 @@ export const OrderCancellationItem = ({
|
|
|
8
8
|
item,
|
|
9
9
|
value,
|
|
10
10
|
onChange,
|
|
11
|
-
selectOption
|
|
12
|
-
fileInput
|
|
11
|
+
selectOption
|
|
13
12
|
}) => {
|
|
14
13
|
const { t } = useLocalization();
|
|
15
14
|
const checkboxStatus =
|
|
@@ -39,6 +38,7 @@ export const OrderCancellationItem = ({
|
|
|
39
38
|
<div className="flex flex-wrap justify-between border-gray border-b mb-4 pb-3">
|
|
40
39
|
<div className="flex gap-3 mb-5 lg:mb-0">
|
|
41
40
|
{checkboxStatus && (
|
|
41
|
+
// TODO: Static image will change (TR)
|
|
42
42
|
<Checkbox
|
|
43
43
|
className="m-auto"
|
|
44
44
|
data-testid="account-orders-return-checkbox"
|
|
@@ -80,7 +80,7 @@ export const OrderCancellationItem = ({
|
|
|
80
80
|
</div>
|
|
81
81
|
</div>
|
|
82
82
|
</div>
|
|
83
|
-
<div className="flex flex-wrap justify-between w-full items-start lg:items-center lg:w-
|
|
83
|
+
<div className="flex flex-wrap justify-between w-full items-start lg:items-center lg:w-auto">
|
|
84
84
|
<div className="w-full flex flex-col lg:items-center lg:flex-row">
|
|
85
85
|
{item.active_cancellation_request?.easy_return?.code && (
|
|
86
86
|
<div className="flex items-center">
|
|
@@ -93,7 +93,6 @@ export const OrderCancellationItem = ({
|
|
|
93
93
|
|
|
94
94
|
{selectOption}
|
|
95
95
|
</div>
|
|
96
|
-
<div>{fileInput}</div>
|
|
97
96
|
</div>
|
|
98
97
|
</div>
|
|
99
98
|
);
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
useUpdateQuantityMutation
|
|
4
4
|
} from '@akinon/next/data/client/basket';
|
|
5
5
|
import { useAppDispatch } from '@akinon/next/redux/hooks';
|
|
6
|
-
import {
|
|
6
|
+
import { BasketItem as BasketItemType } from '@akinon/next/types';
|
|
7
7
|
import { Price, Button, Icon, Modal, Select, Link } from '@theme/components';
|
|
8
8
|
import { useState } from 'react';
|
|
9
9
|
import { useAddFavoriteMutation } from '@akinon/next/data/client/wishlist';
|
|
@@ -19,12 +19,11 @@ import { pushRemoveFromCart } from '@theme/utils/gtm';
|
|
|
19
19
|
interface Props {
|
|
20
20
|
basketItem?: BasketItemType;
|
|
21
21
|
namespace?: string;
|
|
22
|
-
onBasketUpdate?: (basket: Basket) => void;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export const BasketItem = (props: Props) => {
|
|
26
25
|
const { t } = useLocalization();
|
|
27
|
-
const { basketItem, namespace
|
|
26
|
+
const { basketItem, namespace } = props;
|
|
28
27
|
const [updateQuantityMutation] = useUpdateQuantityMutation();
|
|
29
28
|
const dispatch = useAppDispatch();
|
|
30
29
|
const [isRemoveBasketModalOpen, setRemoveBasketModalOpen] = useState(false);
|
|
@@ -50,21 +49,19 @@ export const BasketItem = (props: Props) => {
|
|
|
50
49
|
requestParams.namespace = namespace;
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
await updateQuantityMutation(requestParams)
|
|
53
|
+
.unwrap()
|
|
54
|
+
.then((data) =>
|
|
55
|
+
dispatch(
|
|
56
|
+
basketApi.util.updateQueryData(
|
|
57
|
+
'getBasket',
|
|
58
|
+
undefined,
|
|
59
|
+
(draftBasket) => {
|
|
60
|
+
Object.assign(draftBasket, data.basket);
|
|
61
|
+
}
|
|
62
|
+
)
|
|
62
63
|
)
|
|
63
64
|
);
|
|
64
|
-
onBasketUpdate?.(response.basket);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('Error updating quantity:', error);
|
|
67
|
-
}
|
|
68
65
|
};
|
|
69
66
|
|
|
70
67
|
const deleteProduct = async (productPk?: number) => {
|
|
@@ -18,7 +18,6 @@ import clsx from 'clsx';
|
|
|
18
18
|
|
|
19
19
|
interface Props {
|
|
20
20
|
basket: Basket;
|
|
21
|
-
onBasketUpdate?: (basket: Basket) => void;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
const voucherCodeFormSchema = (t) =>
|
|
@@ -28,7 +27,7 @@ const voucherCodeFormSchema = (t) =>
|
|
|
28
27
|
|
|
29
28
|
export const Summary = (props: Props) => {
|
|
30
29
|
const { t } = useLocalization();
|
|
31
|
-
const { basket
|
|
30
|
+
const { basket } = props;
|
|
32
31
|
const router = useRouter();
|
|
33
32
|
const {
|
|
34
33
|
register,
|
|
@@ -54,7 +53,7 @@ export const Summary = (props: Props) => {
|
|
|
54
53
|
const removeVoucherCode = () => {
|
|
55
54
|
removeVoucherCodeMutation()
|
|
56
55
|
.unwrap()
|
|
57
|
-
.then((basket) =>
|
|
56
|
+
.then((basket) =>
|
|
58
57
|
dispatch(
|
|
59
58
|
basketApi.util.updateQueryData(
|
|
60
59
|
'getBasket',
|
|
@@ -63,9 +62,8 @@ export const Summary = (props: Props) => {
|
|
|
63
62
|
Object.assign(draftBasket, basket);
|
|
64
63
|
}
|
|
65
64
|
)
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
})
|
|
65
|
+
)
|
|
66
|
+
)
|
|
69
67
|
.catch((error: Error) => {
|
|
70
68
|
setError('voucherCode', { message: error.data.non_field_errors });
|
|
71
69
|
});
|
|
@@ -76,7 +74,7 @@ export const Summary = (props: Props) => {
|
|
|
76
74
|
voucher_code: data.voucherCode
|
|
77
75
|
})
|
|
78
76
|
.unwrap()
|
|
79
|
-
.then((basket) =>
|
|
77
|
+
.then((basket) =>
|
|
80
78
|
dispatch(
|
|
81
79
|
basketApi.util.updateQueryData(
|
|
82
80
|
'getBasket',
|
|
@@ -85,9 +83,8 @@ export const Summary = (props: Props) => {
|
|
|
85
83
|
Object.assign(draftBasket, basket);
|
|
86
84
|
}
|
|
87
85
|
)
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
})
|
|
86
|
+
)
|
|
87
|
+
)
|
|
91
88
|
.catch((error: Error) => {
|
|
92
89
|
setError('voucherCode', { message: error.data.non_field_errors });
|
|
93
90
|
});
|
|
@@ -103,34 +103,10 @@ export const Login = () => {
|
|
|
103
103
|
)?.data as string[];
|
|
104
104
|
|
|
105
105
|
fieldErrors?.forEach((item) => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
parsedValue = JSON.parse(item.value);
|
|
111
|
-
} catch {
|
|
112
|
-
parsedValue = [item.value];
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
parsedValue = item.value;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (Array.isArray(parsedValue)) {
|
|
119
|
-
setError(item.name as keyof LoginFormType, {
|
|
120
|
-
type: 'custom',
|
|
121
|
-
message: parsedValue.join(', '),
|
|
122
|
-
});
|
|
123
|
-
} else {
|
|
124
|
-
Object.keys(parsedValue).forEach((key) => {
|
|
125
|
-
const fieldName = key as keyof LoginFormType;
|
|
126
|
-
const errorMessages = parsedValue[key] as string[];
|
|
127
|
-
|
|
128
|
-
setError(fieldName, {
|
|
129
|
-
type: 'custom',
|
|
130
|
-
message: errorMessages.join(', '),
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
}
|
|
106
|
+
setError(item.name as keyof LoginFormType, {
|
|
107
|
+
type: 'custom',
|
|
108
|
+
message: item.value.join(', ')
|
|
109
|
+
});
|
|
134
110
|
});
|
|
135
111
|
|
|
136
112
|
if (nonFieldErrors?.length) {
|
|
@@ -143,7 +143,6 @@ export const Register = () => {
|
|
|
143
143
|
if (registerResponse.error) {
|
|
144
144
|
const errors: AuthError[] = JSON.parse(registerResponse.error);
|
|
145
145
|
|
|
146
|
-
|
|
147
146
|
if (errors.find((error) => error.type === 'captcha')) {
|
|
148
147
|
if (await validateCaptcha()) {
|
|
149
148
|
onSubmit(data);
|
|
@@ -165,34 +164,10 @@ export const Register = () => {
|
|
|
165
164
|
)?.data as string[];
|
|
166
165
|
|
|
167
166
|
fieldErrors?.forEach((item) => {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
parsedValue = JSON.parse(item.value);
|
|
173
|
-
} catch {
|
|
174
|
-
parsedValue = [item.value];
|
|
175
|
-
}
|
|
176
|
-
} else {
|
|
177
|
-
parsedValue = item.value;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (Array.isArray(parsedValue)) {
|
|
181
|
-
setError(item.name as keyof RegisterFormType, {
|
|
182
|
-
type: 'custom',
|
|
183
|
-
message: parsedValue.join(', '),
|
|
184
|
-
});
|
|
185
|
-
} else {
|
|
186
|
-
Object.keys(parsedValue).forEach((key) => {
|
|
187
|
-
const fieldName = key as keyof RegisterFormType;
|
|
188
|
-
const errorMessages = parsedValue[key] as string[];
|
|
189
|
-
|
|
190
|
-
setError(fieldName, {
|
|
191
|
-
type: 'custom',
|
|
192
|
-
message: errorMessages.join(', '),
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
}
|
|
167
|
+
setError(item.name as keyof RegisterFormType, {
|
|
168
|
+
type: 'custom',
|
|
169
|
+
message: item.value.join(', ')
|
|
170
|
+
});
|
|
196
171
|
});
|
|
197
172
|
|
|
198
173
|
if (nonFieldErrors?.length) {
|
|
@@ -328,7 +303,7 @@ export const Register = () => {
|
|
|
328
303
|
labelStyle="floating"
|
|
329
304
|
label={t('auth.register.form.phone.placeholder')}
|
|
330
305
|
className="h-14"
|
|
331
|
-
format={user_phone_format.replace(
|
|
306
|
+
format={user_phone_format.replace(/\9/g, '#')}
|
|
332
307
|
allowEmptyFormatting
|
|
333
308
|
mask="_"
|
|
334
309
|
control={control}
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import 'server-only';
|
|
2
|
-
import { DynamicWidgetContainer } from '../dynamic-widget-renderer';
|
|
3
|
-
|
|
4
|
-
export default async function WidgetPlaceholder({ slug }: { slug: string }) {
|
|
5
|
-
return (
|
|
6
|
-
<>
|
|
7
|
-
<DynamicWidgetContainer />
|
|
8
|
-
</>
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
return <div>WidgetPlaceholder</div>;
|
|
12
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useLocalization } from '@akinon/next/hooks';
|
|
4
|
-
import { Basket } from '@akinon/next/types';
|
|
5
|
-
import { Button, LoaderSpinner, Link } from '@theme/components';
|
|
6
|
-
import { BasketItem, Summary } from '@theme/views/basket';
|
|
7
|
-
import { ROUTES } from '@theme/routes';
|
|
8
|
-
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
9
|
-
import { useEffect, useState } from 'react';
|
|
10
|
-
import { pushCartView } from '@theme/utils/gtm';
|
|
11
|
-
|
|
12
|
-
interface BasketContentProps {
|
|
13
|
-
initialBasket: Basket;
|
|
14
|
-
multiBasket: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function BasketContent({
|
|
18
|
-
initialBasket,
|
|
19
|
-
multiBasket
|
|
20
|
-
}: BasketContentProps) {
|
|
21
|
-
const { t } = useLocalization();
|
|
22
|
-
const [basket, setBasket] = useState<Basket>(initialBasket);
|
|
23
|
-
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
if (basket) {
|
|
26
|
-
const products = basket.basketitem_set.map((basketItem) => ({
|
|
27
|
-
...basketItem.product
|
|
28
|
-
}));
|
|
29
|
-
pushCartView(products);
|
|
30
|
-
}
|
|
31
|
-
}, [basket]);
|
|
32
|
-
|
|
33
|
-
const handleBasketUpdate = (updatedBasket: Basket) => {
|
|
34
|
-
setBasket(updatedBasket);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
if (!basket) {
|
|
38
|
-
return (
|
|
39
|
-
<div className="flex justify-center w-full">
|
|
40
|
-
<LoaderSpinner />
|
|
41
|
-
</div>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<div className="max-w-screen-xl p-4 flex flex-col text-primary-800 lg:p-8 xl:flex-row xl:mx-auto">
|
|
47
|
-
{basket.basketitem_set && basket.basketitem_set.length > 0 ? (
|
|
48
|
-
<>
|
|
49
|
-
<div className="flex-1 xl:mr-16">
|
|
50
|
-
<div className="flex items-center justify-between py-2 border-b border-gray-200 lg:py-3">
|
|
51
|
-
<h2 className="text-xl lg:text-2xl font-light">
|
|
52
|
-
{t('basket.my_cart')}
|
|
53
|
-
</h2>
|
|
54
|
-
<Link
|
|
55
|
-
href={ROUTES.HOME}
|
|
56
|
-
className="text-xs hover:text-secondary-500"
|
|
57
|
-
>
|
|
58
|
-
{t('basket.back_to_shopping')}
|
|
59
|
-
</Link>
|
|
60
|
-
</div>
|
|
61
|
-
<ul>
|
|
62
|
-
{multiBasket ? (
|
|
63
|
-
<PluginModule
|
|
64
|
-
component={Component.MultiBasket}
|
|
65
|
-
props={{
|
|
66
|
-
BasketItem,
|
|
67
|
-
onBasketUpdate: handleBasketUpdate
|
|
68
|
-
}}
|
|
69
|
-
/>
|
|
70
|
-
) : (
|
|
71
|
-
basket.basketitem_set.map((basketItem, index) => (
|
|
72
|
-
<BasketItem
|
|
73
|
-
key={index}
|
|
74
|
-
basketItem={basketItem}
|
|
75
|
-
onBasketUpdate={handleBasketUpdate}
|
|
76
|
-
/>
|
|
77
|
-
))
|
|
78
|
-
)}
|
|
79
|
-
</ul>
|
|
80
|
-
</div>
|
|
81
|
-
<Summary basket={basket} onBasketUpdate={handleBasketUpdate} />
|
|
82
|
-
</>
|
|
83
|
-
) : (
|
|
84
|
-
<div className="flex flex-col items-center container max-w-screen-sm py-4 px-4 xs:py-6 xs:px-6 sm:py-8 sm:px-8 lg:max-w-screen-xl">
|
|
85
|
-
<h1
|
|
86
|
-
className="w-full text-xl font-light text-secondary text-center sm:text-2xl"
|
|
87
|
-
data-testid="basket-empty"
|
|
88
|
-
>
|
|
89
|
-
{t('basket.empty.title')}
|
|
90
|
-
</h1>
|
|
91
|
-
|
|
92
|
-
<div className="w-full text-sm text-black-800 text-center my-4 mb-2 sm:text-base">
|
|
93
|
-
<p>{t('basket.empty.content_first')}</p>
|
|
94
|
-
<p>{t('basket.empty.content_second')}.</p>
|
|
95
|
-
</div>
|
|
96
|
-
|
|
97
|
-
<Link href={ROUTES.HOME} passHref>
|
|
98
|
-
<Button className="px-10 mt-2" appearance="filled">
|
|
99
|
-
{t('basket.empty.button')}
|
|
100
|
-
</Button>
|
|
101
|
-
</Link>
|
|
102
|
-
</div>
|
|
103
|
-
)}
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
106
|
-
}
|