@akinon/projectzero 2.0.0-beta.1 → 2.0.0-beta.10

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 (101) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/app-template/.env.example +5 -0
  3. package/app-template/.gitignore +2 -0
  4. package/app-template/CHANGELOG.md +225 -0
  5. package/app-template/README.md +6 -0
  6. package/app-template/config/prebuild-tests.json +5 -0
  7. package/app-template/{next.config.mjs → next.config.ts} +6 -3
  8. package/app-template/package.json +30 -27
  9. package/app-template/postcss.config.mjs +8 -0
  10. package/app-template/public/locales/en/account.json +4 -0
  11. package/app-template/public/locales/en/common.json +10 -0
  12. package/app-template/public/locales/tr/account.json +4 -0
  13. package/app-template/public/locales/tr/common.json +10 -0
  14. package/app-template/src/__tests__/middleware-matcher.test.ts +135 -0
  15. package/app-template/src/app/[commerce]/[locale]/[currency]/account/orders/[id]/cancellation/page.tsx +93 -4
  16. package/app-template/src/app/[commerce]/[locale]/[currency]/account/orders/[id]/page.tsx +66 -4
  17. package/app-template/src/app/[commerce]/[locale]/[currency]/account/page.tsx +1 -1
  18. package/app-template/src/app/[commerce]/[locale]/[currency]/address/stores/page.tsx +2 -2
  19. package/app-template/src/app/[commerce]/[locale]/[currency]/auth/page.tsx +1 -1
  20. package/app-template/src/app/[commerce]/[locale]/[currency]/basket/page.tsx +2 -2
  21. package/app-template/src/app/[commerce]/[locale]/[currency]/error.tsx +12 -15
  22. package/app-template/src/app/[commerce]/[locale]/[currency]/forms/[pk]/generate/page.tsx +1 -1
  23. package/app-template/src/app/[commerce]/[locale]/[currency]/{pz-not-found/page.tsx → not-found.tsx} +2 -2
  24. package/app-template/src/app/[commerce]/[locale]/[currency]/orders/checkout/page.tsx +7 -4
  25. package/app-template/src/app/[commerce]/[locale]/[currency]/xml-sitemap/[node]/route.ts +47 -1
  26. package/app-template/src/assets/globals.scss +162 -34
  27. package/app-template/src/components/__tests__/badge.test.tsx +2 -2
  28. package/app-template/src/components/accordion.tsx +1 -1
  29. package/app-template/src/components/button.tsx +50 -35
  30. package/app-template/src/components/file-input.tsx +44 -2
  31. package/app-template/src/components/input.tsx +3 -3
  32. package/app-template/src/components/modal.tsx +1 -1
  33. package/app-template/src/components/select.tsx +2 -2
  34. package/app-template/src/components/shimmer.tsx +1 -1
  35. package/app-template/src/components/tabs.tsx +2 -2
  36. package/app-template/src/components/types/index.ts +4 -1
  37. package/app-template/src/middleware.ts +1 -0
  38. package/app-template/src/plugins.js +2 -1
  39. package/app-template/src/redux/middlewares/category.ts +1 -1
  40. package/app-template/src/redux/reducers/category.ts +1 -1
  41. package/app-template/src/redux/store.ts +4 -3
  42. package/app-template/src/settings.js +1 -2
  43. package/app-template/src/utils/convert-facet-search-params.ts +1 -1
  44. package/app-template/src/views/account/contact-form.tsx +3 -8
  45. package/app-template/src/views/account/content-header.tsx +2 -3
  46. package/app-template/src/views/account/order.tsx +1 -1
  47. package/app-template/src/views/account/orders/order-cancellation-item.tsx +5 -4
  48. package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +1 -1
  49. package/app-template/src/views/basket/basket-item.tsx +1 -0
  50. package/app-template/src/views/category/category-active-filters.tsx +1 -1
  51. package/app-template/src/views/category/category-header.tsx +12 -6
  52. package/app-template/src/views/category/category-info.tsx +4 -4
  53. package/app-template/src/views/category/filters/index.tsx +2 -2
  54. package/app-template/src/views/checkout/auth.tsx +1 -1
  55. package/app-template/src/views/checkout/layout/header.tsx +1 -1
  56. package/app-template/src/views/checkout/steps/payment/index.tsx +1 -1
  57. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +1 -1
  58. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +4 -4
  59. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +3 -3
  60. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +1 -1
  61. package/app-template/src/views/checkout/summary.tsx +2 -2
  62. package/app-template/src/views/header/action-menu.tsx +6 -3
  63. package/app-template/src/views/header/band.tsx +2 -2
  64. package/app-template/src/views/header/mini-basket.tsx +15 -4
  65. package/app-template/src/views/header/mobile-menu.tsx +6 -6
  66. package/app-template/src/views/header/navbar.tsx +1 -1
  67. package/app-template/src/views/header/pwa-back-button.tsx +1 -1
  68. package/app-template/src/views/header/search/index.tsx +16 -4
  69. package/app-template/src/views/header/search/results.tsx +1 -1
  70. package/app-template/src/views/header/user-menu.tsx +3 -1
  71. package/app-template/src/views/installment-options/index.tsx +1 -1
  72. package/app-template/src/views/login/index.tsx +30 -6
  73. package/app-template/src/views/otp-login/index.tsx +12 -14
  74. package/app-template/src/views/product/product-info.tsx +2 -2
  75. package/app-template/src/views/product/slider.tsx +1 -1
  76. package/app-template/src/views/product-pointer-banner-item.tsx +1 -1
  77. package/app-template/src/views/register/index.tsx +29 -4
  78. package/app-template/src/views/sales-contract-modal/index.tsx +17 -17
  79. package/app-template/src/widgets/footer-info.tsx +1 -1
  80. package/app-template/src/widgets/footer-menu.tsx +1 -1
  81. package/app-template/src/widgets/footer-subscription/index.tsx +1 -1
  82. package/app-template/src/widgets/home-stories-eng.tsx +1 -1
  83. package/app-template/tailwind.config.js +1 -137
  84. package/codemods/sentry-9/index.js +30 -0
  85. package/codemods/sentry-9/remove-sentry-configs.js +14 -0
  86. package/codemods/sentry-9/remove-sentry-dependency.js +25 -0
  87. package/codemods/sentry-9/replace-error-page.js +32 -0
  88. package/commands/codemod.ts +18 -0
  89. package/commands/index.ts +3 -1
  90. package/commands/plugins.ts +4 -0
  91. package/dist/codemods/sentry-9/templates/error.js +14 -0
  92. package/dist/commands/codemod.js +16 -0
  93. package/dist/commands/index.js +3 -1
  94. package/dist/commands/plugins.js +4 -0
  95. package/package.json +1 -1
  96. package/app-template/postcss.config.js +0 -6
  97. package/app-template/sentry.client.config.ts +0 -16
  98. package/app-template/sentry.edge.config.ts +0 -3
  99. package/app-template/sentry.properties +0 -4
  100. package/app-template/sentry.server.config.ts +0 -3
  101. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/loading.tsx +0 -67
@@ -5,7 +5,7 @@ describe('Badge Component', () => {
5
5
  let badge;
6
6
 
7
7
  beforeEach(() => {
8
- render(<Badge className="text-md rounded-sm">%90 off</Badge>);
8
+ render(<Badge className="text-md rounded-xs">%90 off</Badge>);
9
9
 
10
10
  badge = screen.getByText('%90 off');
11
11
  });
@@ -15,6 +15,6 @@ describe('Badge Component', () => {
15
15
  });
16
16
 
17
17
  it('should be classname checked', () => {
18
- expect(badge).toHaveClass('text-md rounded-sm');
18
+ expect(badge).toHaveClass('text-md rounded-xs');
19
19
  });
20
20
  });
@@ -34,7 +34,7 @@ export const Accordion = ({
34
34
  return (
35
35
  <div
36
36
  className={twMerge(
37
- 'flex flex-col justify-center border-b pb-4 mb-4 last:border-none',
37
+ 'flex flex-col justify-center border-b border-gray-200 pb-4 mb-4 last:border-none',
38
38
  className
39
39
  )}
40
40
  >
@@ -1,46 +1,61 @@
1
1
  'use client';
2
2
 
3
+ import { Link } from '@theme/components';
3
4
  import { ButtonProps } from '@theme/components/types';
4
5
  import clsx from 'clsx';
5
6
  import { twMerge } from 'tailwind-merge';
6
7
 
7
8
  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
- )}
9
+ const {
10
+ appearance = 'filled',
11
+ size = 'md',
12
+ href,
13
+ target,
14
+ children,
15
+ className,
16
+ ...rest
17
+ } = props;
18
+
19
+ const variants = {
20
+ filled:
21
+ 'bg-primary text-primary-foreground border border-primary hover:bg-white hover:border-primary hover:text-primary',
22
+ outlined:
23
+ 'bg-transparent text-primary hover:bg-primary hover:text-primary-foreground',
24
+ ghost:
25
+ 'bg-transparent border-transparent text-primary hover:bg-primary hover:text-primary-foreground',
26
+ link: 'px-0 h-auto underline underline-offset-2'
27
+ };
28
+
29
+ const sizes = {
30
+ sm: 'h-8',
31
+ md: 'h-10',
32
+ lg: 'h-12',
33
+ xl: 'h-14'
34
+ };
35
+
36
+ const buttonClasses = twMerge(
37
+ clsx(
38
+ 'px-4 text-xs transition-all duration-200',
39
+ 'inline-flex gap-2 justify-center items-center',
40
+ variants[appearance],
41
+ sizes[size],
42
+ className
43
+ ),
44
+ className
45
+ );
46
+
47
+ return props.href ? (
48
+ <Link
49
+ prefetch={false}
50
+ target={target}
51
+ href={href}
52
+ className={buttonClasses}
42
53
  >
43
- {props.children}
54
+ {children}
55
+ </Link>
56
+ ) : (
57
+ <button {...rest} className={buttonClasses}>
58
+ {children}
44
59
  </button>
45
60
  );
46
61
  };
@@ -1,8 +1,50 @@
1
+ import { useState } from 'react';
1
2
  import { forwardRef } from 'react';
2
3
  import { FileInputProps } from '@theme/components/types';
4
+ import clsx from 'clsx';
5
+ import { useLocalization } from '@akinon/next/hooks';
3
6
 
4
7
  export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
5
- function fileInput(props, ref) {
6
- return <input type="file" {...props} ref={ref} />;
8
+ function FileInput({ className, onChange, ...props }, ref) {
9
+ const { t } = useLocalization();
10
+ const [fileNames, setFileNames] = useState<string[]>([]);
11
+
12
+ const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
13
+ const files = Array.from(event.target.files || []);
14
+ setFileNames(files.map((file) => file.name));
15
+
16
+ if (onChange) {
17
+ onChange(event);
18
+ }
19
+ };
20
+
21
+ return (
22
+ <div className="relative">
23
+ <input
24
+ type="file"
25
+ {...props}
26
+ ref={ref}
27
+ className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
28
+ onChange={handleFileChange}
29
+ />
30
+ <button
31
+ type="button"
32
+ className={clsx('bg-primary text-white py-2 px-4 text-sm', className)}
33
+ >
34
+ {t('common.file_input.select_file')}
35
+ </button>
36
+ <div className="mt-1 text-gray-500">
37
+ {fileNames.length > 0 ? (
38
+ <ul className="list-disc pl-4 text-xs">
39
+ {fileNames.map((name, index) => (
40
+ <li key={index}>{name}</li>
41
+ ))}
42
+ </ul>
43
+ ) : (
44
+ <span className="text-xs">{t('common.file_input.no_file')}</span>
45
+ )}
46
+ </div>
47
+ </div>
48
+ );
7
49
  }
8
50
  );
@@ -39,8 +39,8 @@ export const Input = forwardRef<
39
39
  const hasFloatingLabel = label && labelStyle === 'floating';
40
40
  const inputClass = twMerge(
41
41
  clsx(
42
- 'text-xs border px-2.5 h-10 placeholder:text-gray-600 peer',
43
- 'focus-visible:outline-none', // disable outline on focus
42
+ 'text-xs border px-2.5 h-10 placeholder:text-gray-600 peer disabled:bg-gray-50',
43
+ 'focus-visible:outline-hidden', // disable outline on focus
44
44
  error
45
45
  ? 'border-error focus:border-error'
46
46
  : 'border-gray-500 hover:border-black focus:border-black'
@@ -68,7 +68,7 @@ export const Input = forwardRef<
68
68
  className={twMerge(
69
69
  'text-xs text-gray-800 transition-all',
70
70
  clsx({
71
- 'absolute left-2.5 pointer-events-none transform flex items-center h-full !top-0 peer-placeholder-shown:-translate-y-2 peer-placeholder-shown:bg-white peer-placeholder-shown:inline-flex peer-placeholder-shown:h-auto':
71
+ 'absolute left-2.5 pointer-events-none transform flex items-center h-full top-0! peer-placeholder-shown:-translate-y-2 peer-placeholder-shown:bg-white peer-placeholder-shown:inline-flex peer-placeholder-shown:h-auto':
72
72
  hasFloatingLabel,
73
73
  'mb-2': !hasFloatingLabel,
74
74
  '-translate-y-2 bg-white inline-flex h-auto':
@@ -38,7 +38,7 @@ export const Modal = (props: ModalProps) => {
38
38
 
39
39
  return (
40
40
  <ReactPortal wrapperId={portalId}>
41
- <div className="fixed top-0 left-0 w-screen h-screen bg-primary bg-opacity-60 z-50" />
41
+ <div className="fixed top-0 left-0 w-screen h-screen bg-primary/60 z-50" />
42
42
  <section
43
43
  className={twMerge(
44
44
  'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 bg-white',
@@ -41,14 +41,14 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
41
41
  ref={ref}
42
42
  className={twMerge(
43
43
  clsx(
44
- 'cursor-pointer truncate h-10 w-40 px-2.5 shrink-0 outline-none',
44
+ 'cursor-pointer truncate h-10 w-40 px-2.5 shrink-0 outline-hidden',
45
45
  !borderless &&
46
46
  'border border-gray-200 transition-all duration-150 hover:border-primary'
47
47
  ),
48
48
  className
49
49
  )}
50
50
  >
51
- {options.map((option) => (
51
+ {options?.map((option) => (
52
52
  <option
53
53
  key={option.value}
54
54
  value={option.value}
@@ -12,7 +12,7 @@ export const Shimmer: React.FC<ShimmerProps> = ({ className }) => {
12
12
  >
13
13
  <div
14
14
  className={twMerge(
15
- 'w-full h-full bg-black bg-opacity-20 shadow-[0 0 30px 30px rgba(255,255,255,0.2)]',
15
+ 'w-full h-full bg-black/20 shadow-[0 0 30px 30px rgba(255,255,255,0.2)]',
16
16
  className
17
17
  )}
18
18
  ></div>
@@ -39,7 +39,7 @@ export const Tabs = (props: Props) => {
39
39
  tabBarPosition === 'left' || tabBarPosition === 'right'
40
40
  })}
41
41
  >
42
- {children.map((item, index) => (
42
+ {children?.map((item, index) => (
43
43
  <Tab
44
44
  key={item.props.title}
45
45
  title={item.props.title}
@@ -52,7 +52,7 @@ export const Tabs = (props: Props) => {
52
52
  ))}
53
53
  </ul>
54
54
 
55
- <div className="w-full">{children[selectedTabIndex]}</div>
55
+ <div className="w-full">{children?.[selectedTabIndex]}</div>
56
56
  </div>
57
57
  );
58
58
  };
@@ -4,7 +4,10 @@ import { UsePaginationType } from '@akinon/next/hooks/use-pagination';
4
4
 
5
5
  export interface ButtonProps
6
6
  extends React.ButtonHTMLAttributes<HTMLButtonElement> {
7
- appearance?: 'filled' | 'outlined' | 'ghost';
7
+ appearance?: 'filled' | 'outlined' | 'ghost' | 'link' | string;
8
+ size?: 'sm' | 'md' | 'lg' | 'xl';
9
+ href?: string;
10
+ target?: '_blank' | '_self' | '_parent' | '_top';
8
11
  }
9
12
 
10
13
  export interface PaginationProps {
@@ -9,6 +9,7 @@ import { NextMiddleware, NextResponse } from 'next/server';
9
9
  */
10
10
 
11
11
  export const config = {
12
+ // For .xml.gz type sitemap urls, update '/(.*sitemap\\.xml)' with this regex '/(.*sitemap\\.xml|sitemap/.*.xml(?:.gz)?)/',
12
13
  matcher: [
13
14
  '/((?!api|_next|[\\w-\\/*]+\\.\\w+).*)',
14
15
  '/(.*sitemap\\.xml)',
@@ -13,5 +13,6 @@ module.exports = [
13
13
  'pz-b2b',
14
14
  'pz-akifast',
15
15
  'pz-saved-card',
16
- 'pz-tabby-extension'
16
+ 'pz-tabby-extension',
17
+ 'pz-tamara-extension'
17
18
  ];
@@ -4,7 +4,7 @@ import { setSelectedFacets } from '@theme/redux/reducers/category';
4
4
 
5
5
  const getSelectedFacets = (facets: Array<Facet>) => {
6
6
  return facets
7
- .map((facet) => {
7
+ ?.map((facet) => {
8
8
  return {
9
9
  ...facet,
10
10
  data: {
@@ -32,7 +32,7 @@ const categorySlice = createSlice({
32
32
  toggleFacet(state, action) {
33
33
  const facets = JSON.parse(JSON.stringify(state.facets));
34
34
 
35
- state.selectedFacets = facets.map((facet) => {
35
+ state.selectedFacets = facets?.map((facet) => {
36
36
  if (facet.key === action.payload.facet.key) {
37
37
  facet.data.choices = facet.data.choices
38
38
  .map((choice) => {
@@ -6,6 +6,7 @@ import {
6
6
  Action,
7
7
  AnyAction,
8
8
  configureStore,
9
+ Middleware,
9
10
  Store,
10
11
  ThunkAction,
11
12
  ThunkDispatch
@@ -13,20 +14,20 @@ import {
13
14
  import categoryReducer from '@theme/redux/reducers/category';
14
15
  import categoryMiddleware from '@theme/redux/middlewares/category';
15
16
 
17
+ const _middlewares: Middleware[] = [...middlewares, categoryMiddleware];
18
+
16
19
  const _reducers = {
17
20
  ...reducers,
18
21
  category: categoryReducer
19
22
  };
20
23
 
21
- const _middlewares = [...middlewares, categoryMiddleware];
22
-
23
24
  export const makeStore = (): Store<{
24
25
  [key in keyof typeof _reducers]: ReturnType<typeof _reducers[key]>;
25
26
  }> =>
26
27
  configureStore({
27
28
  reducer: _reducers,
28
29
  middleware: (getDefaultMiddleware) =>
29
- getDefaultMiddleware().concat([..._middlewares])
30
+ getDefaultMiddleware().concat(_middlewares)
30
31
  });
31
32
 
32
33
  export type AppStore = ReturnType<typeof makeStore>;
@@ -61,6 +61,5 @@ module.exports = {
61
61
  ],
62
62
  redis: {
63
63
  defaultExpirationTime: 900 // 15 min
64
- },
65
- customNotFoundEnabled: false
64
+ }
66
65
  };
@@ -1,7 +1,7 @@
1
1
  import { Facet } from '@akinon/next/types';
2
2
 
3
3
  const convertFacetSearchParams = (facets: Facet[]) => {
4
- const _facets: string[][] = facets.flatMap((facet) => {
4
+ const _facets: string[][] = facets?.flatMap((facet) => {
5
5
  return [
6
6
  ...facet.data.choices.map((choice) => {
7
7
  return [facet.search_key, choice.value as string];
@@ -242,7 +242,7 @@ const ContactForm = () => {
242
242
  <span className="text-secondary">*</span>
243
243
  </label>
244
244
  <textarea
245
- className="border-gray-500 border w-full text-xs p-2.5 focus-visible:outline-none focus:border-black hover:border-black"
245
+ className="border-gray-500 border w-full text-xs p-2.5 focus-visible:outline-hidden focus:border-black hover:border-black"
246
246
  rows={7}
247
247
  name="message"
248
248
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -255,13 +255,8 @@ const ContactForm = () => {
255
255
  <label className="text-xs text-gray-800 mb-2 block">
256
256
  {t('account.contact.form.file.title')}
257
257
  </label>
258
- <FileInput
259
- name="file"
260
- title="file"
261
- className="w-full mb-5"
262
- {...register('file')}
263
- />
264
- <Button type="submit" className="w-full font-medium">
258
+ <FileInput name="file" title="file" {...register('file')} />
259
+ <Button type="submit" className="w-full font-medium mt-4">
265
260
  {t('account.contact.form.submit_button')}
266
261
  </Button>
267
262
  </form>
@@ -31,15 +31,14 @@ export const ContentHeader = (props: Props) => {
31
31
  </h3>
32
32
  <Select
33
33
  onChange={handleChange}
34
- className="w-full mb-4 md:mb-0 md:w-56 md:mr-4 text-xs"
34
+ className="w-full mb-4 bg-white md:mb-0 md:w-56 md:mr-4 text-xs"
35
35
  options={orders}
36
36
  data-testid="account-orders-header-select"
37
37
  ></Select>
38
38
  <Button
39
39
  className={clsx(
40
40
  'w-full md:w-56',
41
- isButtonDisabled &&
42
- 'hover:bg-black hover:text-white disabled:opacity-75'
41
+ isButtonDisabled && 'hover:bg-black/75 hover:text-white'
43
42
  )}
44
43
  onClick={handleClick}
45
44
  data-testid="account-orders-header-button"
@@ -60,7 +60,7 @@ export const Order = (props) => {
60
60
  <ul className="flex flex-wrap gap-3.5 mb-6 items-center md:mb-0">
61
61
  {props.orderitem_set.slice(0, 3).map((item, index) => (
62
62
  // TODO: Static image will change (TR)
63
- <li className="flex-shrink-0" key={index}>
63
+ <li className="shrink-0" key={index}>
64
64
  <Image
65
65
  src={item.product.image ? item.product.image : '/noimage.jpg'}
66
66
  alt={item.product.name}
@@ -8,7 +8,8 @@ export const OrderCancellationItem = ({
8
8
  item,
9
9
  value,
10
10
  onChange,
11
- selectOption
11
+ selectOption,
12
+ fileInput
12
13
  }) => {
13
14
  const { t } = useLocalization();
14
15
  const checkboxStatus =
@@ -38,14 +39,13 @@ export const OrderCancellationItem = ({
38
39
  <div className="flex flex-wrap justify-between border-gray border-b mb-4 pb-3">
39
40
  <div className="flex gap-3 mb-5 lg:mb-0">
40
41
  {checkboxStatus && (
41
- // TODO: Static image will change (TR)
42
42
  <Checkbox
43
43
  className="m-auto"
44
44
  data-testid="account-orders-return-checkbox"
45
45
  onClick={handleClick}
46
46
  />
47
47
  )}
48
- <div className="flex-shrink-0">
48
+ <div className="shrink-0">
49
49
  <Link href={item.product.absolute_url}>
50
50
  <Image
51
51
  src={item.product.image ? item.product.image : '/noimage.jpg'}
@@ -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-auto">
83
+ <div className="flex flex-wrap justify-between w-full items-start lg:items-center lg:w-80 gap-4">
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,6 +93,7 @@ export const OrderCancellationItem = ({
93
93
 
94
94
  {selectOption}
95
95
  </div>
96
+ <div>{fileInput}</div>
96
97
  </div>
97
98
  </div>
98
99
  );
@@ -135,7 +135,7 @@ export const AnonymousTrackingOrderDetail = ({ order }) => {
135
135
  key={index}
136
136
  >
137
137
  <div className="flex gap-3 mb-5 lg:mb-0">
138
- <div className="flex-shrink-0">
138
+ <div className="shrink-0">
139
139
  <Link
140
140
  className="block"
141
141
  href={item.product.absolute_url}
@@ -87,6 +87,7 @@ export const BasketItem = (props: Props) => {
87
87
  <li
88
88
  key={basketItem.id}
89
89
  className="flex border-b border-gray-200 py-3 relative"
90
+ data-testid="basket-item"
90
91
  >
91
92
  <div className="w-20 lg:w-[105px] mr-4 shrink-0">
92
93
  <Link href={basketItem.product.absolute_url} passHref>
@@ -69,7 +69,7 @@ const CategoryActiveFilters = () => {
69
69
 
70
70
  return (
71
71
  <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-2 mb-4">
72
- {facets.map((facet) =>
72
+ {facets?.map((facet) =>
73
73
  facet?.data?.choices
74
74
  ?.filter((choice) => choice.is_selected)
75
75
  ?.map(
@@ -91,12 +91,18 @@ export const CategoryHeader = (props: Props) => {
91
91
  value: String(value)
92
92
  });
93
93
  }}
94
- className={clsx(
95
- 'cursor-pointer',
96
- Number(layoutSize) === value ? 'fill-black' : 'fill-gray-500'
97
- )}
94
+ className="cursor-pointer"
98
95
  >
99
- <Icon key={value} name={icon} size={16} />
96
+ <Icon
97
+ key={value}
98
+ name={icon}
99
+ size={16}
100
+ className={
101
+ Number(layoutSize) === value
102
+ ? 'text-black'
103
+ : 'text-gray-500'
104
+ }
105
+ />
100
106
  </a>
101
107
  ))}
102
108
  </div>
@@ -115,7 +121,7 @@ export const CategoryHeader = (props: Props) => {
115
121
  </Button>
116
122
  <Select
117
123
  options={sortOptions}
118
- value={sortOptions.find(({ is_selected }) => is_selected).value}
124
+ value={sortOptions?.find(({ is_selected }) => is_selected)?.value}
119
125
  data-testid="list-sorter"
120
126
  onChange={(e) => {
121
127
  handleSelectFilter({
@@ -79,7 +79,7 @@ export default function ListPage(props: ListPageProps) {
79
79
  className={clsx(
80
80
  'transition-opacity duration-300 ease-linear lg:hidden',
81
81
  isMenuOpen
82
- ? 'fixed bg-black bg-opacity-60 inset-0 z-10 opacity-100'
82
+ ? 'fixed bg-black/60 inset-0 z-10 opacity-100'
83
83
  : 'opacity-0'
84
84
  )}
85
85
  ></div>
@@ -102,7 +102,7 @@ export default function ListPage(props: ListPageProps) {
102
102
  </div>
103
103
  )}
104
104
 
105
- {data.products.length === 0 && page > 1 && <LoaderSpinner />}
105
+ {data.products?.length === 0 && page > 1 && <LoaderSpinner />}
106
106
 
107
107
  <div
108
108
  className={clsx('grid gap-x-4 gap-y-12 grid-cols-2', {
@@ -111,7 +111,7 @@ export default function ListPage(props: ListPageProps) {
111
111
  'lg:grid-cols-3': layoutSize === 3
112
112
  })}
113
113
  >
114
- {data.products.map((product, index) => (
114
+ {data?.products?.map((product, index) => (
115
115
  <ProductItem
116
116
  key={product.pk}
117
117
  product={product}
@@ -121,7 +121,7 @@ export default function ListPage(props: ListPageProps) {
121
121
  />
122
122
  ))}
123
123
  </div>
124
- {data.products.length > 0 && (
124
+ {data?.products?.length > 0 && (
125
125
  <Pagination
126
126
  total={data.pagination.total_count}
127
127
  limit={data.pagination.page_size}
@@ -23,7 +23,7 @@ export const Filters = (props: Props) => {
23
23
  const [isPending, startTransition] = useTransition();
24
24
 
25
25
  const haveFilter = useMemo(() => {
26
- return facets.some((facet) =>
26
+ return facets?.some((facet) =>
27
27
  facet?.data?.choices?.some((choice) => choice.is_selected)
28
28
  );
29
29
  }, [facets]);
@@ -50,7 +50,7 @@ export const Filters = (props: Props) => {
50
50
  <span>{t('category.filters.ready_to_wear')}</span>
51
51
  </div>
52
52
 
53
- {facets.map((facet) => {
53
+ {facets?.map((facet) => {
54
54
  return (
55
55
  <FilterItem
56
56
  key={facet.key}
@@ -24,7 +24,7 @@ const CheckoutAuth = () => {
24
24
 
25
25
  return (
26
26
  <div className="flex flex-col w-full my-5 lg:flex-row">
27
- <div className="flex-1 flex-shrink-0">
27
+ <div className="flex-1 shrink-0">
28
28
  <Login />
29
29
  <div className="text-center text-sm text-gray-600 uppercase mt-5">
30
30
  <span>
@@ -6,7 +6,7 @@ import { Image } from '@akinon/next/components/image';
6
6
 
7
7
  const CheckoutHeader = () => {
8
8
  return (
9
- <div className="relative border-b border-gray-100 shadow">
9
+ <div className="relative border-b border-gray-100 shadow-sm">
10
10
  <header
11
11
  className={clsx(['py-8', 'px-4', 'mx-auto', 'container', 'md:px-0'])}
12
12
  >
@@ -18,7 +18,7 @@ const PaymentStep = () => {
18
18
  'pointer-events-none opacity-30': isPaymentStepBusy
19
19
  })}
20
20
  >
21
- <div className="w-full mt-4 flex justify-start border border-gray-400 -mb-px z-10 md:mt-0 md:border-r-0 md:border-b-0 md:w-auto order-2 md:order-none">
21
+ <div className="w-full mt-4 flex justify-start border border-gray-400 -mb-px z-10 md:mt-0 md:border-r-0 md:border-b-0 md:w-auto order-2 md:order-none overflow-x-auto">
22
22
  <PaymentOptionButtons />
23
23
  </div>
24
24
  <div className="w-full border border-solid border-gray-400 bg-white">
@@ -319,7 +319,7 @@ const CheckoutCreditCard = () => {
319
319
  size={16}
320
320
  className="leading-none ml-2"
321
321
  />
322
- <div className="hidden group-hover:block absolute right-0 bottom-5 w-[11rem] lg:w-[21rem] lg:left-auto lg:right-auto border-2">
322
+ <div className="hidden group-hover:block absolute right-0 bottom-5 w-[11rem] lg:w-[21rem] lg:left-auto lg:right-auto border-2 border-gray-200">
323
323
  {/* TODO: Fix this */}
324
324
  <Image
325
325
  src="/cvv.jpg"
@@ -44,7 +44,7 @@ const PaymentOptionButtons = () => {
44
44
  {displayedPaymentOptions.map((option) => (
45
45
  <label
46
46
  key={`payment-option-${option.pk}`}
47
- className="border px-4 py-3 mt-3 flex h-12"
47
+ className="border border-gray-200 px-4 py-3 mt-3 flex h-12"
48
48
  onClick={scrollToTop}
49
49
  >
50
50
  <Radio
@@ -69,10 +69,10 @@ const PaymentOptionButtons = () => {
69
69
  onClick={() => onClickHandler(option)}
70
70
  className={clsx(
71
71
  'flex items-center justify-center border-r border-b border-solid',
72
- 'border-gray-400 text-xs uppercase text-black-800 font-medium',
73
- 'text-opacity-60 bg-white h-11 px-5 transition-colors sm:h-15 sm:px-8 sm:py-8 hover:text-secondary',
72
+ 'border-gray-400 text-xs uppercase text-black-800/60 font-medium',
73
+ 'bg-white h-11 px-5 transition-colors sm:h-15 sm:px-8 sm:py-8 hover:text-secondary',
74
74
  {
75
- 'text-opacity-100 border-b-transparent':
75
+ 'text-black-800/100 border-b-transparent':
76
76
  preOrder?.payment_option?.pk === option.pk
77
77
  }
78
78
  )}