@akinon/projectzero 1.100.0-rc.71 → 1.100.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 (60) hide show
  1. package/CHANGELOG.md +5 -232
  2. package/app-template/.env.example +0 -1
  3. package/app-template/CHANGELOG.md +333 -4964
  4. package/app-template/README.md +1 -25
  5. package/app-template/package.json +19 -19
  6. package/app-template/public/locales/en/common.json +1 -48
  7. package/app-template/public/locales/tr/common.json +1 -48
  8. package/app-template/src/app/[commerce]/[locale]/[currency]/basket/page.tsx +82 -9
  9. package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +4 -17
  10. package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +1 -12
  11. package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +11 -29
  12. package/app-template/src/app/[commerce]/[locale]/[currency]/landing-page/[pk]/page.tsx +1 -12
  13. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +10 -28
  14. package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +1 -12
  15. package/app-template/src/app/api/form/[...id]/route.ts +7 -1
  16. package/app-template/src/assets/fonts/pz-icon.css +0 -3
  17. package/app-template/src/components/__tests__/link.test.tsx +0 -2
  18. package/app-template/src/components/accordion.tsx +19 -22
  19. package/app-template/src/components/currency-select.tsx +0 -1
  20. package/app-template/src/components/file-input.tsx +7 -27
  21. package/app-template/src/components/generate-form-fields.tsx +4 -43
  22. package/app-template/src/components/input.tsx +2 -9
  23. package/app-template/src/components/modal.tsx +16 -32
  24. package/app-template/src/components/pagination.tsx +0 -1
  25. package/app-template/src/components/select.tsx +26 -38
  26. package/app-template/src/components/types/index.ts +1 -25
  27. package/app-template/src/hooks/index.ts +0 -2
  28. package/app-template/src/plugins.js +1 -3
  29. package/app-template/src/redux/store.ts +21 -1
  30. package/app-template/src/settings.js +2 -8
  31. package/app-template/src/types/index.ts +0 -17
  32. package/app-template/src/views/account/address-form.tsx +4 -8
  33. package/app-template/src/views/account/contact-form.tsx +1 -1
  34. package/app-template/src/views/account/content-header.tsx +2 -2
  35. package/app-template/src/views/account/faq/faq-tabs.tsx +2 -8
  36. package/app-template/src/views/basket/basket-item.tsx +14 -22
  37. package/app-template/src/views/basket/summary.tsx +7 -10
  38. package/app-template/src/views/breadcrumb.tsx +2 -2
  39. package/app-template/src/views/category/category-info.tsx +0 -1
  40. package/app-template/src/views/category/filters/index.tsx +1 -1
  41. package/app-template/src/views/guest-login/index.tsx +1 -6
  42. package/app-template/src/views/header/action-menu.tsx +1 -1
  43. package/app-template/src/views/header/search/index.tsx +5 -17
  44. package/app-template/src/views/product/product-info.tsx +263 -62
  45. package/app-template/src/views/product/slider.tsx +73 -86
  46. package/app-template/src/widgets/footer-menu.tsx +2 -6
  47. package/commands/plugins.ts +16 -63
  48. package/dist/commands/plugins.js +16 -57
  49. package/package.json +1 -1
  50. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/loading.tsx +0 -67
  51. package/app-template/src/app/api/image-proxy/route.ts +0 -1
  52. package/app-template/src/app/api/similar-product-list/route.ts +0 -1
  53. package/app-template/src/app/api/similar-products/route.ts +0 -1
  54. package/app-template/src/hooks/use-product-cart.ts +0 -77
  55. package/app-template/src/hooks/use-stock-alert.ts +0 -74
  56. package/app-template/src/utils/variant-validation.ts +0 -41
  57. package/app-template/src/views/basket/basket-content.tsx +0 -106
  58. package/app-template/src/views/product/product-actions.tsx +0 -165
  59. package/app-template/src/views/product/product-share.tsx +0 -56
  60. package/app-template/src/views/product/product-variants.tsx +0 -26
@@ -1,21 +1,11 @@
1
1
  import { useState } from 'react';
2
2
  import { forwardRef } from 'react';
3
3
  import { FileInputProps } from '@theme/components/types';
4
+ import clsx from 'clsx';
4
5
  import { useLocalization } from '@akinon/next/hooks';
5
- import { twMerge } from 'tailwind-merge';
6
6
 
7
7
  export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
8
- function FileInput(
9
- {
10
- buttonClassName,
11
- onChange,
12
- fileClassName,
13
- fileNameWrapperClassName,
14
- fileInputClassName,
15
- ...props
16
- },
17
- ref
18
- ) {
8
+ function FileInput({ className, onChange, ...props }, ref) {
19
9
  const { t } = useLocalization();
20
10
  const [fileNames, setFileNames] = useState<string[]>([]);
21
11
 
@@ -34,34 +24,24 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
34
24
  type="file"
35
25
  {...props}
36
26
  ref={ref}
37
- className={twMerge(
38
- 'absolute inset-0 w-full h-full opacity-0 cursor-pointer',
39
- fileInputClassName
40
- )}
27
+ className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
41
28
  onChange={handleFileChange}
42
29
  />
43
30
  <button
44
31
  type="button"
45
- className={twMerge(
46
- 'bg-primary text-white py-2 px-4 text-sm',
47
- buttonClassName
48
- )}
32
+ className={clsx('bg-primary text-white py-2 px-4 text-sm', className)}
49
33
  >
50
34
  {t('common.file_input.select_file')}
51
35
  </button>
52
- <div
53
- className={twMerge('mt-1 text-gray-500', fileNameWrapperClassName)}
54
- >
36
+ <div className="mt-1 text-gray-500">
55
37
  {fileNames.length > 0 ? (
56
- <ul className={twMerge('list-disc pl-4 text-xs', fileClassName)}>
38
+ <ul className="list-disc pl-4 text-xs">
57
39
  {fileNames.map((name, index) => (
58
40
  <li key={index}>{name}</li>
59
41
  ))}
60
42
  </ul>
61
43
  ) : (
62
- <span className={twMerge('text-xs', fileClassName)}>
63
- {t('common.file_input.no_file')}
64
- </span>
44
+ <span className="text-xs">{t('common.file_input.no_file')}</span>
65
45
  )}
66
46
  </div>
67
47
  </div>
@@ -7,7 +7,6 @@ import { useForm } from 'react-hook-form';
7
7
  import { yupResolver } from '@hookform/resolvers/yup';
8
8
  import * as yup from 'yup';
9
9
  import DynamicForm from './dynamic-form';
10
-
11
10
  import {
12
11
  AllFieldClassesType,
13
12
  FieldPropertiesType,
@@ -15,7 +14,6 @@ import {
15
14
  FormPropertiesType,
16
15
  Schema
17
16
  } from '@akinon/next/types';
18
- import { useLocalization } from '@akinon/next/hooks';
19
17
 
20
18
  export function GenerateFormFields({
21
19
  schema,
@@ -30,14 +28,8 @@ export function GenerateFormFields({
30
28
  formProperties: FormPropertiesType;
31
29
  submitButtonText: string;
32
30
  }) {
33
- const { t } = useLocalization();
34
31
  const [fields, setFields] = useState([]);
35
32
  const [loading, setIsLoading] = useState(true);
36
- const [isSubmitting, setIsSubmitting] = useState(false);
37
- const [submitStatus, setSubmitStatus] = useState<
38
- 'idle' | 'success' | 'error'
39
- >('idle');
40
- const [submitMessage, setSubmitMessage] = useState('');
41
33
 
42
34
  const generateValidationSchema = () => {
43
35
  const schemaObject = {};
@@ -88,7 +80,6 @@ export function GenerateFormFields({
88
80
  const {
89
81
  handleSubmit,
90
82
  register,
91
- reset,
92
83
  formState: { errors }
93
84
  } = useForm<FormField>({
94
85
  resolver: yupResolver(generateValidationSchema())
@@ -117,10 +108,6 @@ export function GenerateFormFields({
117
108
  }, [schema, fieldProperties]);
118
109
 
119
110
  const onSubmit = async (data) => {
120
- setIsSubmitting(true);
121
- setSubmitStatus('idle');
122
- setSubmitMessage('');
123
-
124
111
  try {
125
112
  const formData = new FormData();
126
113
 
@@ -128,25 +115,12 @@ export function GenerateFormFields({
128
115
  formData.append(key, data[key]);
129
116
  });
130
117
 
131
- const response = await fetch(formProperties.actionUrl, {
118
+ fetch(formProperties.actionUrl, {
132
119
  method: 'POST',
133
120
  body: formData
134
121
  });
135
-
136
- if (response.ok) {
137
- setSubmitStatus('success');
138
- setSubmitMessage(t('common.forms.success'));
139
- reset();
140
- } else {
141
- setSubmitStatus('error');
142
- setSubmitMessage(t('common.forms.error'));
143
- }
144
122
  } catch (error) {
145
- console.error(t('common.forms.submit_error'), error);
146
- setSubmitStatus('error');
147
- setSubmitMessage(t('common.forms.error'));
148
- } finally {
149
- setIsSubmitting(false);
123
+ console.error('Form submit error:', error);
150
124
  }
151
125
  };
152
126
 
@@ -363,22 +337,9 @@ export function GenerateFormFields({
363
337
  <LoaderSpinner />
364
338
  ) : (
365
339
  <>
366
- {submitStatus === 'success' && (
367
- <div className="mb-4 p-3 bg-green-100 border border-green-400 text-green-700 rounded">
368
- {submitMessage}
369
- </div>
370
- )}
371
-
372
- {submitStatus === 'error' && (
373
- <div className="mb-4 p-3 bg-red-100 border border-red-400 text-red-700 rounded">
374
- {submitMessage}
375
- </div>
376
- )}
377
-
378
340
  {fields.map((field: FormField) => generateField(field))}
379
-
380
- <Button type="submit" className="w-full" disabled={isSubmitting}>
381
- {isSubmitting ? t('common.forms.sending') : submitButtonText}
341
+ <Button type="submit" className="w-full">
342
+ {submitButtonText}
382
343
  </Button>
383
344
  </>
384
345
  )}
@@ -48,13 +48,7 @@ export const Input = forwardRef<
48
48
  props.className
49
49
  );
50
50
 
51
- const inputProps: {
52
- id?: string;
53
- ref?: Ref<HTMLInputElement>;
54
- className?: string;
55
- onFocus?: () => void;
56
- onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
57
- } = {
51
+ const inputProps: any = {
58
52
  id,
59
53
  ref,
60
54
  className: inputClass,
@@ -78,8 +72,7 @@ export const Input = forwardRef<
78
72
  hasFloatingLabel,
79
73
  'mb-2': !hasFloatingLabel,
80
74
  '-translate-y-2 bg-white inline-flex h-auto':
81
- hasFloatingLabel &&
82
- (focused || hasValue || props.value || props.format)
75
+ hasFloatingLabel && (focused || hasValue)
83
76
  })
84
77
  )}
85
78
  >
@@ -4,7 +4,16 @@ import ReactPortal from './react-portal';
4
4
  import { Icon } from './icon';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { useEffect } from 'react';
7
- import { ModalProps } from '@theme/types';
7
+
8
+ export interface ModalProps {
9
+ portalId: string;
10
+ children?: React.ReactNode;
11
+ open?: boolean;
12
+ setOpen?: (open: boolean) => void;
13
+ title?: React.ReactNode;
14
+ showCloseButton?: React.ReactNode;
15
+ className?: string;
16
+ }
8
17
 
9
18
  export const Modal = (props: ModalProps) => {
10
19
  const {
@@ -14,14 +23,7 @@ export const Modal = (props: ModalProps) => {
14
23
  setOpen,
15
24
  title = '',
16
25
  showCloseButton = true,
17
- className,
18
- overlayClassName,
19
- headerWrapperClassName,
20
- titleClassName,
21
- closeButtonClassName,
22
- iconName = 'close',
23
- iconSize = 16,
24
- iconClassName
26
+ className
25
27
  } = props;
26
28
 
27
29
  useEffect(() => {
@@ -36,12 +38,7 @@ export const Modal = (props: ModalProps) => {
36
38
 
37
39
  return (
38
40
  <ReactPortal wrapperId={portalId}>
39
- <div
40
- className={twMerge(
41
- 'fixed top-0 left-0 w-screen h-screen bg-primary bg-opacity-60 z-50',
42
- overlayClassName
43
- )}
44
- />
41
+ <div className="fixed top-0 left-0 w-screen h-screen bg-primary bg-opacity-60 z-50" />
45
42
  <section
46
43
  className={twMerge(
47
44
  'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 bg-white',
@@ -49,28 +46,15 @@ export const Modal = (props: ModalProps) => {
49
46
  )}
50
47
  >
51
48
  {(showCloseButton || title) && (
52
- <div
53
- className={twMerge(
54
- 'flex px-6 py-4 border-b border-gray-400',
55
- headerWrapperClassName
56
- )}
57
- >
58
- {title && (
59
- <h3 className={twMerge('text-lg font-light', titleClassName)}>
60
- {title}
61
- </h3>
62
- )}
49
+ <div className="flex px-6 py-4 border-b border-gray-400">
50
+ {title && <h3 className="text-lg font-light">{title}</h3>}
63
51
  {showCloseButton && (
64
52
  <button
65
53
  type="button"
66
54
  onClick={() => setOpen(false)}
67
- className={twMerge('ml-auto', closeButtonClassName)}
55
+ className="ml-auto"
68
56
  >
69
- <Icon
70
- name={iconName}
71
- size={iconSize}
72
- className={iconClassName}
73
- />
57
+ <Icon name="close" size={16} />
74
58
  </button>
75
59
  )}
76
60
  </div>
@@ -125,7 +125,6 @@ export const Pagination = (props: PaginationProps) => {
125
125
  setPrevPage(1);
126
126
  setNextPage(1);
127
127
  }
128
- // eslint-disable-next-line react-hooks/exhaustive-deps
129
128
  }, [page]);
130
129
 
131
130
  useEffect(() => {
@@ -14,18 +14,14 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
14
14
  error,
15
15
  label,
16
16
  required = false,
17
- labelClassName,
18
17
  ...rest
19
18
  } = props;
20
19
 
21
20
  return (
22
21
  <label
23
- className={twMerge(
24
- clsx('flex flex-col relative text-xs text-gray-800', {
25
- 'pl-7': icon
26
- }),
27
- labelClassName
28
- )}
22
+ className={clsx('flex flex-col relative text-xs text-gray-800', {
23
+ 'pl-7': icon
24
+ })}
29
25
  >
30
26
  {icon && (
31
27
  <Icon
@@ -36,40 +32,32 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
36
32
  )}
37
33
 
38
34
  {label && (
39
- <span className={twMerge('mb-1', labelClassName)}>
35
+ <span className="mb-1">
40
36
  {label} {required && <span className="text-secondary">*</span>}
41
37
  </span>
42
38
  )}
43
- <div className="relative">
44
- <select
45
- {...rest}
46
- ref={ref}
47
- className={twMerge(
48
- clsx(
49
- 'cursor-pointer truncate h-10 w-40 px-2.5 shrink-0 outline-none',
50
- !borderless &&
51
- 'border border-gray-200 transition-all duration-150 hover:border-primary',
52
- 'appearance-none bg-transparent'
53
- ),
54
- className
55
- )}
56
- >
57
- {options?.map((option) => (
58
- <option
59
- key={option.value}
60
- value={option.value}
61
- className={option.class}
62
- >
63
- {option.label}
64
- </option>
65
- ))}
66
- </select>
67
- <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
68
- <svg className="h-4 w-4 fill-current" viewBox="0 0 20 20">
69
- <path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
70
- </svg>
71
- </div>
72
- </div>
39
+ <select
40
+ {...rest}
41
+ ref={ref}
42
+ className={twMerge(
43
+ clsx(
44
+ 'cursor-pointer truncate h-10 w-40 px-2.5 shrink-0 outline-none',
45
+ !borderless &&
46
+ 'border border-gray-200 transition-all duration-150 hover:border-primary'
47
+ ),
48
+ className
49
+ )}
50
+ >
51
+ {options?.map((option) => (
52
+ <option
53
+ key={option.value}
54
+ value={option.value}
55
+ className={option.class}
56
+ >
57
+ {option.label}
58
+ </option>
59
+ ))}
60
+ </select>
73
61
  {error && (
74
62
  <span className="mt-1 text-sm text-error">{error.message}</span>
75
63
  )}
@@ -29,13 +29,7 @@ export interface PaginationProps {
29
29
  isLoading?: boolean;
30
30
  }
31
31
 
32
- export interface FileInputProps extends React.HTMLProps<HTMLInputElement> {
33
- fileClassName?: string;
34
- fileNameWrapperClassName?: string;
35
- fileInputClassName?: string;
36
- onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
37
- buttonClassName?: string;
38
- }
32
+ export type FileInputProps = React.HTMLProps<HTMLInputElement>;
39
33
 
40
34
  export type RadioProps = React.HTMLProps<HTMLInputElement>;
41
35
 
@@ -64,7 +58,6 @@ export interface SelectProps extends React.HTMLProps<HTMLSelectElement> {
64
58
  iconSize?: number;
65
59
  error?: FieldError | undefined;
66
60
  required?: boolean;
67
- labelClassName?: string;
68
61
  }
69
62
  export interface IconProps extends React.ComponentPropsWithRef<'i'> {
70
63
  name: string;
@@ -98,20 +91,3 @@ export interface BadgeProps {
98
91
  children: ReactNode;
99
92
  className?: string;
100
93
  }
101
-
102
- export type AccordionProps = {
103
- isCollapse?: boolean;
104
- collapseClassName?: string;
105
- title?: string;
106
- subTitle?: string;
107
- icons?: string[];
108
- iconSize?: number;
109
- iconColor?: string;
110
- children?: ReactNode;
111
- headerClassName?: string;
112
- className?: string;
113
- titleClassName?: string;
114
- subTitleClassName?: string;
115
- dataTestId?: string;
116
- contentClassName?: string;
117
- };
@@ -1,3 +1 @@
1
- export * from './use-contract';
2
- export * from './use-fav-button';
3
1
  export * from './use-add-product-to-basket';
@@ -14,7 +14,5 @@ module.exports = [
14
14
  'pz-akifast',
15
15
  'pz-saved-card',
16
16
  'pz-tabby-extension',
17
- 'pz-tamara-extension',
18
- 'pz-hepsipay',
19
- 'pz-similar-products'
17
+ 'pz-tamara-extension'
20
18
  ];
@@ -14,6 +14,11 @@ import {
14
14
  import categoryReducer from '@theme/redux/reducers/category';
15
15
  import categoryMiddleware from '@theme/redux/middlewares/category';
16
16
 
17
+ // Import all action creators from akinon-next
18
+ import * as defaultActions from '@akinon/next/redux/actions';
19
+ import { rtkApiActionCreators } from '@akinon/next/redux/actions';
20
+ import * as categorySlice from './reducers/category';
21
+
17
22
  const _middlewares: Middleware[] = [...middlewares, categoryMiddleware];
18
23
 
19
24
  const _reducers = {
@@ -21,13 +26,28 @@ const _reducers = {
21
26
  category: categoryReducer
22
27
  };
23
28
 
29
+ const actionCreators = {
30
+ // Slice actions (automatically extracted from akinon-next)
31
+ ...defaultActions,
32
+ // RTK Query API endpoints from akinon-next
33
+ ...rtkApiActionCreators,
34
+ // Local category slice actions
35
+ ...categorySlice
36
+ };
37
+
24
38
  export const makeStore = (): Store<{
25
39
  [key in keyof typeof _reducers]: ReturnType<typeof _reducers[key]>;
26
40
  }> =>
27
41
  configureStore({
28
42
  reducer: _reducers,
29
43
  middleware: (getDefaultMiddleware) =>
30
- getDefaultMiddleware().concat(_middlewares)
44
+ getDefaultMiddleware().concat(_middlewares),
45
+ devTools:
46
+ process.env.NODE_ENV !== 'production'
47
+ ? {
48
+ actionCreators
49
+ }
50
+ : false
31
51
  });
32
52
 
33
53
  export type AppStore = ReturnType<typeof makeStore>;
@@ -1,10 +1,6 @@
1
1
  const { LocaleUrlStrategy } = require('@akinon/next/localization');
2
2
  const { ROUTES } = require('@theme/routes');
3
3
 
4
- /* IMPORTANT *
5
- * In order to use one locale in the locales array and hide the default locale in the URL, you need to set the localeUrlStrategy to LocaleUrlStrategy.ShowAllLocales.
6
- */
7
-
8
4
  const commerceUrl = encodeURI(process.env.SERVICE_BACKEND_URL ?? 'default');
9
5
 
10
6
  /** @type {import('@akinon/next/types').Settings} */
@@ -18,7 +14,6 @@ module.exports = {
18
14
  { translationKey: 'size', key: 'size' }
19
15
  ],
20
16
  localization: {
21
- // If there is one locale in the locales array, the default locale will be hidden in the URL.
22
17
  locales: [
23
18
  {
24
19
  label: 'EN',
@@ -46,7 +41,7 @@ module.exports = {
46
41
  }
47
42
  ],
48
43
  defaultLocaleValue: 'en',
49
- localeUrlStrategy: LocaleUrlStrategy.HideDefaultLocale, // If there is one locale in the locales array, the default locale will be hidden in the URL and localeUrlStrategy should be set to LocaleUrlStrategy.ShowAllLocales.
44
+ localeUrlStrategy: LocaleUrlStrategy.HideDefaultLocale,
50
45
  redirectToDefaultLocale: true,
51
46
  defaultCurrencyCode: 'usd'
52
47
  },
@@ -67,6 +62,5 @@ module.exports = {
67
62
  redis: {
68
63
  defaultExpirationTime: 900 // 15 min
69
64
  },
70
- customNotFoundEnabled: false,
71
- commerceRedirectionIgnoreList: ['/users/reset']
65
+ customNotFoundEnabled: false
72
66
  };
@@ -125,20 +125,3 @@ export interface SeoProps {
125
125
  ogPriceAmount?: string;
126
126
  ogPriceCurrency?: string;
127
127
  }
128
-
129
- export interface ModalProps {
130
- portalId: string;
131
- children?: React.ReactNode;
132
- open?: boolean;
133
- setOpen?: (open: boolean) => void;
134
- title?: React.ReactNode;
135
- showCloseButton?: React.ReactNode;
136
- className?: string;
137
- overlayClassName?: string;
138
- headerWrapperClassName?: string;
139
- titleClassName?: string;
140
- closeButtonClassName?: string;
141
- iconName?: string;
142
- iconSize?: number;
143
- iconClassName?: string;
144
- }
@@ -259,25 +259,23 @@ export const AddressForm = (props: Props) => {
259
259
  {/* TODO: Fix select and textarea components */}
260
260
 
261
261
  <Select
262
- className="w-full border-gray-500 text-sm"
262
+ className="w-full border-gray-500 text-sm mt-2"
263
263
  options={countryOptions}
264
264
  {...register('country')}
265
265
  error={errors.country}
266
266
  data-testid="address-form-country"
267
267
  label={t('account.address_book.form.country.title')}
268
- labelClassName="mb-3"
269
268
  required
270
269
  />
271
270
 
272
271
  {city && (
273
272
  <Select
274
- className="w-full border-gray-500 text-sm"
273
+ className="w-full border-gray-500 text-sm mt-2"
275
274
  options={cityOptions}
276
275
  {...register('city')}
277
276
  error={errors.city}
278
277
  data-testid="address-form-city"
279
278
  label={t('account.address_book.form.province.title')}
280
- labelClassName="mb-3"
281
279
  required
282
280
  />
283
281
  )}
@@ -285,26 +283,24 @@ export const AddressForm = (props: Props) => {
285
283
  <div className="flex gap-4">
286
284
  <div className="flex-1">
287
285
  <Select
288
- className="w-full border-gray-500 text-sm"
286
+ className="w-full border-gray-500 text-sm mt-2"
289
287
  options={townshipOptions}
290
288
  {...register('township')}
291
289
  error={errors.township}
292
290
  data-testid="address-form-township"
293
291
  label={t('account.address_book.form.township.title')}
294
- labelClassName="mb-3"
295
292
  required
296
293
  />
297
294
  </div>
298
295
  {district && (
299
296
  <div className="flex-1">
300
297
  <Select
301
- className="w-full border-gray-500 text-sm"
298
+ className="w-full border-gray-500 text-sm mt-2"
302
299
  options={districtOptions}
303
300
  {...register('district')}
304
301
  error={errors.district}
305
302
  data-testid="address-form-district"
306
303
  label={t('account.address_book.form.district.title')}
307
- labelClassName="mb-3"
308
304
  required
309
305
  />
310
306
  </div>
@@ -111,7 +111,7 @@ const ContactForm = () => {
111
111
  resolver: yupResolver(contactFormSchema(t))
112
112
  });
113
113
 
114
- const onSubmit: SubmitHandler<ContactFormType> = (data) => {
114
+ const onSubmit: SubmitHandler<ContactFormType> = (data, event) => {
115
115
  const formData = new FormData();
116
116
 
117
117
  Object.keys(data ?? {}).forEach((key) => {
@@ -31,13 +31,13 @@ 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 text-xs"
34
+ className="w-full mb-4 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
- 'w-full md:w-56 md:ms-4',
40
+ 'w-full md:w-56',
41
41
  isButtonDisabled &&
42
42
  'hover:bg-black hover:text-white disabled:opacity-75'
43
43
  )}
@@ -3,7 +3,6 @@
3
3
  import { Accordion, LoaderSpinner, TabPanel, Tabs } from '@theme/components';
4
4
  import React from 'react';
5
5
  import { useGetWidgetQuery } from '@akinon/next/data/client/misc';
6
- import { useLocalization } from '@akinon/next/hooks';
7
6
 
8
7
  interface Props {
9
8
  searchKey?: string;
@@ -12,7 +11,6 @@ interface Props {
12
11
  export function FaqTabs(props: Props) {
13
12
  const { searchKey } = props;
14
13
  const { data, isLoading } = useGetWidgetQuery('faq');
15
- const { locale } = useLocalization();
16
14
 
17
15
  if (isLoading) {
18
16
  return <LoaderSpinner className="mt-4" />;
@@ -31,12 +29,8 @@ export function FaqTabs(props: Props) {
31
29
  {data?.attributes?.faq_contents
32
30
  ?.filter(
33
31
  (faq) =>
34
- faq.value.content
35
- .toLocaleLowerCase(locale)
36
- .includes(searchKey) ||
37
- faq.value.title
38
- .toLocaleLowerCase(locale)
39
- .includes(searchKey)
32
+ faq.value.content.toLocaleLowerCase().includes(searchKey) ||
33
+ faq.value.title.toLocaleLowerCase().includes(searchKey)
40
34
  )
41
35
  .map((faq, index) => {
42
36
  if (faq.value.category == item.value.category_id) {