@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.
Files changed (27) hide show
  1. package/CHANGELOG.md +1 -15
  2. package/app-template/.gitignore +0 -2
  3. package/app-template/CHANGELOG.md +166 -2734
  4. package/app-template/package.json +18 -18
  5. package/app-template/public/locales/en/common.json +0 -4
  6. package/app-template/public/locales/tr/common.json +0 -4
  7. package/app-template/sentry.edge.config.ts +3 -0
  8. package/app-template/sentry.server.config.ts +3 -0
  9. package/app-template/src/app/[commerce]/[locale]/[currency]/account/orders/[id]/cancellation/page.tsx +5 -94
  10. package/app-template/src/app/[commerce]/[locale]/[currency]/basket/page.tsx +82 -9
  11. package/app-template/src/app/[commerce]/[locale]/[currency]/orders/checkout/page.tsx +4 -7
  12. package/app-template/src/app/[commerce]/[locale]/[currency]/page.tsx +0 -8
  13. package/app-template/src/components/button.tsx +35 -50
  14. package/app-template/src/components/file-input.tsx +2 -44
  15. package/app-template/src/components/types/index.ts +1 -4
  16. package/app-template/src/middleware.ts +0 -1
  17. package/app-template/src/settings.js +1 -6
  18. package/app-template/src/views/account/address-form.tsx +2 -2
  19. package/app-template/src/views/account/contact-form.tsx +8 -3
  20. package/app-template/src/views/account/orders/order-cancellation-item.tsx +3 -4
  21. package/app-template/src/views/basket/basket-item.tsx +13 -16
  22. package/app-template/src/views/basket/summary.tsx +7 -10
  23. package/app-template/src/views/login/index.tsx +4 -28
  24. package/app-template/src/views/register/index.tsx +5 -30
  25. package/package.json +1 -1
  26. package/app-template/src/components/widget/widget-placeholder.tsx +0 -12
  27. 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-80 gap-4">
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 { Basket, BasketItem as BasketItemType } from '@akinon/next/types';
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, onBasketUpdate } = props;
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
- try {
54
- const response = await updateQuantityMutation(requestParams).unwrap();
55
- dispatch(
56
- basketApi.util.updateQueryData(
57
- 'getBasket',
58
- undefined,
59
- (draftBasket) => {
60
- Object.assign(draftBasket, response.basket);
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, onBasketUpdate } = props;
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
- onBasketUpdate?.(basket);
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
- onBasketUpdate?.(basket);
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
- let parsedValue: Record<string, string[]> | string[] = [];
107
-
108
- if (typeof item.value === 'string') {
109
- try {
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
- let parsedValue: Record<string, string[]> | string[] = [];
169
-
170
- if (typeof item.value === 'string') {
171
- try {
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(/9/g, '#')}
306
+ format={user_phone_format.replace(/\9/g, '#')}
332
307
  allowEmptyFormatting
333
308
  mask="_"
334
309
  control={control}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/projectzero",
3
- "version": "1.78.0-rc.2",
3
+ "version": "1.78.0",
4
4
  "private": false,
5
5
  "description": "CLI tool to manage your Project Zero Next project",
6
6
  "bin": {
@@ -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
- }