@akinon/projectzero 2.0.0-beta.20 → 2.0.0-beta.22

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 (140) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/app-template/CHANGELOG.md +170 -0
  3. package/app-template/next.config.mjs +0 -1
  4. package/app-template/package.json +31 -30
  5. package/app-template/src/app/[pz]/[...prettyurl]/page.tsx +2 -2
  6. package/app-template/src/app/[pz]/account/layout.tsx +2 -1
  7. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/blog/[slug]/page.tsx +4 -2
  8. package/app-template/src/app/[pz]/category/[pk]/page.tsx +11 -1
  9. package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +2 -2
  10. package/app-template/src/app/[pz]/layout.tsx +3 -1
  11. package/app-template/src/app/[pz]/list/page.tsx +11 -1
  12. package/app-template/src/app/[pz]/page.tsx +13 -35
  13. package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
  14. package/app-template/src/app/[pz]/product/[pk]/page.tsx +2 -2
  15. package/app-template/src/app/api/barcode-search/route.ts +1 -1
  16. package/app-template/src/app/api/cache/route.ts +1 -1
  17. package/app-template/src/app/api/image-proxy/route.ts +1 -1
  18. package/app-template/src/app/api/logout/route.ts +1 -1
  19. package/app-template/src/app/api/product-categories/route.ts +1 -1
  20. package/app-template/src/app/api/similar-product-list/route.ts +1 -1
  21. package/app-template/src/app/api/similar-products/route.ts +1 -1
  22. package/app-template/src/app/api/virtual-try-on/route.ts +1 -1
  23. package/app-template/src/app/api/web-vitals/route.ts +1 -1
  24. package/app-template/src/components/quantity-selector.tsx +16 -4
  25. package/app-template/src/components/widget-content.tsx +3 -3
  26. package/app-template/src/routes/index.ts +6 -6
  27. package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
  28. package/app-template/src/utils/theme-page-context.ts +309 -0
  29. package/app-template/src/views/basket/basket-item.tsx +107 -691
  30. package/app-template/src/views/basket/index.ts +0 -2
  31. package/app-template/src/views/basket/summary.tsx +75 -496
  32. package/app-template/src/views/breadcrumb.tsx +38 -13
  33. package/app-template/src/views/category/category-header.tsx +66 -289
  34. package/app-template/src/views/category/category-info.tsx +24 -173
  35. package/app-template/src/views/category/filters/index.tsx +48 -208
  36. package/app-template/src/views/category/layout.tsx +5 -7
  37. package/app-template/src/views/checkout/index.tsx +0 -5
  38. package/app-template/src/views/checkout/steps/payment/index.tsx +2 -5
  39. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +1 -72
  40. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +40 -171
  41. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +12 -74
  42. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +45 -128
  43. package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +27 -232
  44. package/app-template/src/views/checkout/summary.tsx +29 -303
  45. package/app-template/src/views/footer.tsx +13 -415
  46. package/app-template/src/views/guest-login/index.tsx +1 -1
  47. package/app-template/src/views/header/action-menu.tsx +45 -277
  48. package/app-template/src/views/header/band.tsx +21 -6
  49. package/app-template/src/views/header/index.tsx +47 -109
  50. package/app-template/src/views/header/mini-basket.tsx +45 -820
  51. package/app-template/src/views/header/navbar.tsx +111 -178
  52. package/app-template/src/views/header/search/index.tsx +32 -71
  53. package/app-template/src/views/header/search/results.tsx +65 -127
  54. package/app-template/src/views/product/accordion-wrapper.tsx +43 -135
  55. package/app-template/src/views/product/index.ts +1 -1
  56. package/app-template/src/views/product/layout.tsx +7 -2
  57. package/app-template/src/views/product/misc-buttons.tsx +25 -339
  58. package/app-template/src/views/product/product-actions.tsx +8 -137
  59. package/app-template/src/views/product/product-info.tsx +31 -69
  60. package/app-template/src/views/product/product-share.tsx +8 -11
  61. package/app-template/src/views/product/slider.tsx +79 -117
  62. package/app-template/src/views/product-item/index.tsx +46 -119
  63. package/app-template/src/widgets/footer-social.tsx +16 -47
  64. package/app-template/src/widgets/footer-subscription/index.tsx +17 -183
  65. package/codemods/migrate-auth-v5/index.js +339 -0
  66. package/codemods/migrate-auth-v5/transform.js +86 -0
  67. package/dist/commands/plugins.js +23 -2
  68. package/package.json +1 -1
  69. package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +0 -15
  70. package/app-template/src/views/basket/basket-summary-context.tsx +0 -560
  71. package/app-template/src/views/basket/designer-context.tsx +0 -617
  72. package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +0 -190
  73. package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +0 -286
  74. package/app-template/src/views/breadcrumb/constants.ts +0 -15
  75. package/app-template/src/views/breadcrumb/index.tsx +0 -127
  76. package/app-template/src/views/category/native-widget-context.tsx +0 -257
  77. package/app-template/src/views/category/product-list-registrar.tsx +0 -665
  78. package/app-template/src/views/checkout/checkout-address-registrar.tsx +0 -254
  79. package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +0 -183
  80. package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +0 -259
  81. package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +0 -253
  82. package/app-template/src/views/checkout/checkout-summary-registrar.tsx +0 -183
  83. package/app-template/src/views/checkout/constants.ts +0 -5
  84. package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +0 -15
  85. package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +0 -18
  86. package/app-template/src/views/footer/footer-app-banner-context.tsx +0 -326
  87. package/app-template/src/views/footer/footer-bottom-context.tsx +0 -215
  88. package/app-template/src/views/footer/footer-bottom-wrapper.tsx +0 -74
  89. package/app-template/src/views/footer/footer-layout-constants.ts +0 -35
  90. package/app-template/src/views/footer/footer-layout-registrar.tsx +0 -342
  91. package/app-template/src/views/footer/footer-layout-switcher.tsx +0 -110
  92. package/app-template/src/views/footer/footer-menu-context.tsx +0 -211
  93. package/app-template/src/views/footer/footer-native-widgets.tsx +0 -60
  94. package/app-template/src/views/footer/footer-social-context.tsx +0 -254
  95. package/app-template/src/views/footer/footer-subscription-context.tsx +0 -210
  96. package/app-template/src/views/footer/footer-utils.ts +0 -43
  97. package/app-template/src/views/footer/footer-value-props-context.tsx +0 -326
  98. package/app-template/src/views/footer/logo-settings.ts +0 -183
  99. package/app-template/src/views/footer/native-widget-config.ts +0 -262
  100. package/app-template/src/views/footer/subscription-settings.ts +0 -122
  101. package/app-template/src/views/footer/use-footer-logo.ts +0 -162
  102. package/app-template/src/views/header/designer-context.tsx +0 -261
  103. package/app-template/src/views/header/header-announcement-registrar.tsx +0 -267
  104. package/app-template/src/views/header/header-client-wrapper.tsx +0 -496
  105. package/app-template/src/views/header/header-content.tsx +0 -1026
  106. package/app-template/src/views/header/header-currency-registrar.tsx +0 -348
  107. package/app-template/src/views/header/header-icons-context.tsx +0 -262
  108. package/app-template/src/views/header/header-language-registrar.tsx +0 -348
  109. package/app-template/src/views/header/header-layout-context.tsx +0 -143
  110. package/app-template/src/views/header/header-layout-registrar.tsx +0 -658
  111. package/app-template/src/views/header/header-logo-context.tsx +0 -228
  112. package/app-template/src/views/header/header-logo.tsx +0 -118
  113. package/app-template/src/views/header/header-mini-basket-context.tsx +0 -524
  114. package/app-template/src/views/header/header-search-registrar.tsx +0 -511
  115. package/app-template/src/views/header/header-text-slider-registrar.tsx +0 -382
  116. package/app-template/src/views/header/inline-search.tsx +0 -262
  117. package/app-template/src/views/header/navbar-menu-context.tsx +0 -219
  118. package/app-template/src/views/header/search/search-input.tsx +0 -61
  119. package/app-template/src/views/header/server-settings-parser.ts +0 -1105
  120. package/app-template/src/views/header/use-header-icons.ts +0 -241
  121. package/app-template/src/views/header/use-header-logo.ts +0 -213
  122. package/app-template/src/views/header/use-navbar-menu.ts +0 -179
  123. package/app-template/src/views/product/accordion-section.tsx +0 -61
  124. package/app-template/src/views/product/custom-button-group.tsx +0 -69
  125. package/app-template/src/views/product/favorites-button-section.tsx +0 -69
  126. package/app-template/src/views/product/find-in-store-section.tsx +0 -60
  127. package/app-template/src/views/product/product-info-section.tsx +0 -140
  128. package/app-template/src/views/product/quantity-section.tsx +0 -73
  129. package/app-template/src/views/product/sale-tag.tsx +0 -10
  130. package/app-template/src/views/product/share-section.tsx +0 -357
  131. package/app-template/src/views/product/variants-section.tsx +0 -126
  132. package/app-template/src/views/product-detail/constants.ts +0 -272
  133. package/app-template/src/views/product-detail/index.ts +0 -10
  134. package/app-template/src/views/product-detail/product-detail-registrar.tsx +0 -616
  135. package/app-template/src/widgets/footer-app-banner.tsx +0 -444
  136. package/app-template/src/widgets/footer-bottom.tsx +0 -127
  137. package/app-template/src/widgets/footer-menu-compact.tsx +0 -238
  138. package/app-template/src/widgets/footer-menu-two.tsx +0 -298
  139. package/app-template/src/widgets/footer-social-client.tsx +0 -251
  140. package/app-template/src/widgets/footer-value-props.tsx +0 -201
@@ -1,13 +1,38 @@
1
- /**
2
- * Breadcrumb Component
3
- *
4
- * Re-exports the Breadcrumb component from the breadcrumb folder.
5
- * This file is kept for backwards compatibility with existing imports.
6
- */
7
- export { default } from './breadcrumb/index';
8
- export type { BreadcrumbProps } from './breadcrumb/index';
9
- export {
10
- BreadcrumbRegistrar,
11
- useBreadcrumb,
12
- BreadcrumbClient
13
- } from './breadcrumb/index';
1
+ 'use client';
2
+
3
+ import { Fragment } from 'react';
4
+ import { Icon, Link } from '@theme/components';
5
+ import { ROUTES } from '@theme/routes';
6
+ import { useLocalization } from '@akinon/next/hooks';
7
+ import { BreadcrumbResultType } from '@akinon/next/types';
8
+ import { capitalize } from '@akinon/next/utils';
9
+
10
+ export interface BreadcrumbProps {
11
+ breadcrumbList?: BreadcrumbResultType[];
12
+ }
13
+
14
+ export default function Breadcrumb(props: BreadcrumbProps) {
15
+ const { t, locale } = useLocalization();
16
+ const { breadcrumbList = [] } = props;
17
+
18
+ const list = [
19
+ { url: ROUTES.HOME, text: t('common.breadcrumb.homepage') },
20
+ ...breadcrumbList.map((breadcrumb) => ({
21
+ url: breadcrumb.url,
22
+ text: breadcrumb.label
23
+ }))
24
+ ];
25
+
26
+ return (
27
+ <div className="flex items-center gap-3 text-xs leading-4 text-gray-950">
28
+ {list.map((item, index) => (
29
+ <Fragment key={index}>
30
+ <Link href={item.url}>
31
+ {capitalize(item.text.toLocaleLowerCase(locale))}
32
+ </Link>
33
+ {index !== list.length - 1 && <Icon name="chevron-end" size={8} />}
34
+ </Fragment>
35
+ ))}
36
+ </div>
37
+ );
38
+ }
@@ -1,17 +1,13 @@
1
1
  'use client';
2
2
 
3
- import React, { useMemo, useState, useTransition, CSSProperties } from 'react';
3
+ import React, { useMemo } from 'react';
4
4
  import { usePathname, useSearchParams } from 'next/navigation';
5
5
  import clsx from 'clsx';
6
6
 
7
7
  import { Button, Icon, Select, Link } from '@theme/components';
8
8
  import { SortOption } from '@akinon/next/types';
9
- import { useAppSelector } from '@akinon/next/redux/hooks';
10
- import { FilterItem } from './filters/filter-item';
11
9
 
12
10
  import { useRouter, useLocalization } from '@akinon/next/hooks';
13
- import { useProductList } from './product-list-registrar';
14
- import { useNativeWidget } from './native-widget-context';
15
11
 
16
12
  interface Props {
17
13
  totalCount: number;
@@ -32,76 +28,16 @@ export const CategoryHeader = (props: Props) => {
32
28
  ];
33
29
  const { totalCount, setMenuStatus, sortOptions } = props;
34
30
  const router = useRouter();
35
- const facets = useAppSelector((state) => state.category.facets);
36
- const [openDropdown, setOpenDropdown] = useState<string | null>(null);
37
- const [isPending, startTransition] = useTransition();
38
31
 
39
32
  const searchParams = useSearchParams();
40
33
  const pathname = usePathname();
41
34
 
42
- // Get styles and properties from both contexts
43
- const {
44
- isDesigner,
45
- filterStyles: registrarStyles,
46
- filterProperties: registrarProps,
47
- productsProperties: registrarProductsProps
48
- } = useProductList();
49
- const {
50
- filterStyles: widgetStyles,
51
- filterProperties: widgetProps,
52
- productsProperties: widgetProductsProps
53
- } = useNativeWidget();
54
-
55
- // Use registrar data in designer mode, widget data otherwise
56
- const filterStyles = isDesigner ? registrarStyles : widgetStyles;
57
-
58
- // Merge properties - registrar props override widget props for live updates
59
- const filterProperties = {
60
- ...widgetProps,
61
- ...registrarProps
62
- };
63
-
64
- const layout = (filterProperties.layout as string) || 'top';
65
- const containerStyles = filterStyles as CSSProperties;
66
-
67
- // Get products properties - merge widget and registrar
68
- const productsProperties = {
69
- ...widgetProductsProps,
70
- ...registrarProductsProps
71
- };
72
- const showLayoutButtons = productsProperties['show-layout-buttons'] !== false;
73
- const availableLayouts = productsProperties['available-layouts'] || [
74
- '2',
75
- '3',
76
- '4'
77
- ];
78
-
79
- // Parse item properties
80
- const itemPaddingY =
81
- typeof filterProperties['item-padding-y'] === 'number'
82
- ? filterProperties['item-padding-y']
83
- : typeof filterProperties['item-padding-y'] === 'string'
84
- ? parseInt(filterProperties['item-padding-y'], 10)
85
- : 6;
86
- const itemPaddingX =
87
- typeof filterProperties['item-padding-x'] === 'number'
88
- ? filterProperties['item-padding-x']
89
- : typeof filterProperties['item-padding-x'] === 'string'
90
- ? parseInt(filterProperties['item-padding-x'], 10)
91
- : 0;
92
- const itemMarginBottom =
93
- typeof filterProperties['item-margin-bottom'] === 'number'
94
- ? filterProperties['item-margin-bottom']
95
- : typeof filterProperties['item-margin-bottom'] === 'string'
96
- ? parseInt(filterProperties['item-margin-bottom'], 10)
97
- : 0;
98
-
99
35
  const pageSize = useMemo(
100
36
  () => searchParams.get('page_size') ?? 48,
101
37
  [searchParams]
102
38
  );
103
39
  const layoutSize = useMemo(
104
- () => searchParams.get('layout') ?? '3',
40
+ () => searchParams.get('layout') ?? 3,
105
41
  [searchParams]
106
42
  );
107
43
 
@@ -119,241 +55,82 @@ export const CategoryHeader = (props: Props) => {
119
55
  router.push(pathname + '?' + urlSearchParams.toString());
120
56
  };
121
57
 
122
- const facetButtonStyles = {
123
- paddingTop: `${itemPaddingY}px`,
124
- paddingBottom: `${itemPaddingY}px`,
125
- paddingLeft: `${itemPaddingX}px`,
126
- paddingRight: `${itemPaddingX}px`,
127
- marginRight: `${itemMarginBottom}px`
128
- };
129
-
130
58
  return (
131
- <div className="w-full flex flex-col gap-4 text-gray-950 text-sm">
132
- {layout === 'top' && (
133
- <div
134
- className="hidden lg:flex items-center gap-6 text-sm"
135
- style={containerStyles}
136
- data-section-id="filters-section"
137
- >
138
- <span className="text-black-750 text-sm">
139
- {t('category.filters.title')}:
140
- </span>
141
- {facets?.map((facet) => (
142
- <div key={facet.key} className="relative" style={facetButtonStyles}>
143
- <Button
144
- onClick={() =>
145
- setOpenDropdown(openDropdown === facet.key ? null : facet.key)
146
- }
147
- appearance="ghost"
148
- className="flex items-center gap-2 p-0 text-sm text-black-750 hover:bg-transparent hover:text-black-750"
149
- >
150
- <span>{facet.name}</span>
151
- <Icon
152
- name="chevron-down"
153
- size={16}
154
- className={clsx(
155
- 'transition-transform',
156
- openDropdown === facet.key && 'rotate-180'
157
- )}
158
- />
159
- </Button>
160
- {openDropdown === facet.key && (
161
- <>
162
- <div
163
- className="fixed inset-0 z-10"
164
- onClick={() => setOpenDropdown(null)}
165
- />
166
- <div className="absolute top-full left-0 mt-2 w-64 bg-white border border-gray-200 rounded shadow-lg z-20 max-h-96 overflow-y-auto">
167
- <FilterItem
168
- facet={facet}
169
- isPending={isPending}
170
- startTransition={startTransition}
171
- isDropdown
172
- itemPaddingY={itemPaddingY}
173
- itemPaddingX={itemPaddingX}
174
- itemMarginBottom={itemMarginBottom}
175
- />
176
- </div>
177
- </>
178
- )}
179
- </div>
180
- ))}
181
- <div className="ml-auto flex items-center gap-2 text-black-750 text-sm">
182
- <span>{t('category.header.sort_by')}:</span>
183
- <Select
184
- options={sortOptions}
185
- value={sortOptions?.find(({ is_selected }) => is_selected)?.value}
186
- data-testid="list-sorter"
187
- onChange={(e) => {
188
- handleSelectFilter({
189
- key: 'sorter',
190
- value: e.currentTarget.value
191
- });
192
- }}
193
- className="text-black-750 text-sm border-0"
194
- borderless={false}
195
- />
196
- {showLayoutButtons && availableLayouts.length > 0 && (
197
- <div className="flex items-center gap-2">
198
- {availableLayouts.map((cols) => (
199
- <Button
200
- key={cols}
201
- onClick={() =>
202
- handleSelectFilter({
203
- key: 'layout',
204
- value: cols
205
- })
206
- }
207
- appearance="ghost"
208
- className={clsx(
209
- 'p-2 hover:bg-gray-100',
210
- layoutSize === cols && 'bg-gray-200'
211
- )}
212
- data-section-id="products-section"
213
- >
214
- <svg
215
- width="20"
216
- height="20"
217
- viewBox="0 0 20 20"
218
- fill="none"
219
- xmlns="http://www.w3.org/2000/svg"
220
- >
221
- {Array.from({ length: parseInt(cols) }).map((_, i) => {
222
- const colWidth = 20 / parseInt(cols);
223
- const gap = 2;
224
- const rectWidth = colWidth - gap;
225
- return (
226
- <g key={i}>
227
- <rect
228
- x={i * colWidth}
229
- y="0"
230
- width={rectWidth}
231
- height="8"
232
- fill="currentColor"
233
- />
234
- <rect
235
- x={i * colWidth}
236
- y="10"
237
- width={rectWidth}
238
- height="8"
239
- fill="currentColor"
240
- />
241
- </g>
242
- );
243
- })}
244
- </svg>
245
- </Button>
246
- ))}
247
- </div>
248
- )}
249
- <span>
250
- <span data-testid="list-count">{totalCount}</span>{' '}
251
- {t('category.header.results')}
252
- </span>
253
- </div>
254
- </div>
255
- )}
59
+ <div className="flex flex-col gap-4 mb-4 text-gray-950 text-sm">
60
+ <div className="flex items-center">
61
+ <span className="hidden lg:block">
62
+ <span data-testid="list-count">{totalCount}</span>{' '}
63
+ {t('category.header.results')}
64
+ </span>
256
65
 
257
- {/* Sidebar layout - show sorting and product count */}
258
- {layout === 'sidebar' && (
259
- <div
260
- className="hidden lg:flex items-center justify-between"
261
- style={containerStyles}
262
- data-section-id="filters-section"
263
- >
264
- <div className="flex items-center gap-2 text-black-750 text-sm">
265
- <span>{t('category.header.sort_by')}:</span>
266
- <Select
267
- options={sortOptions}
268
- value={sortOptions?.find(({ is_selected }) => is_selected)?.value}
269
- data-testid="list-sorter"
270
- onChange={(e) => {
66
+ <div className="hidden lg:flex gap-5 ml-auto mr-7 px-5 py-2 border border-gray-100">
67
+ <span> {t('category.header.view')}</span>
68
+ {PAGE_SIZE.map(({ label, value }) => (
69
+ <a
70
+ key={value}
71
+ onClick={() => {
271
72
  handleSelectFilter({
272
- key: 'sorter',
273
- value: e.currentTarget.value
73
+ key: 'page_size',
74
+ value: String(value)
274
75
  });
275
76
  }}
276
- className="text-black-750 text-sm border-0"
277
- borderless={false}
278
- />
279
- </div>
280
- <span className="text-black-750 text-sm">
281
- <span data-testid="list-count">{totalCount}</span>{' '}
282
- {t('category.header.results')}
283
- </span>
284
- {showLayoutButtons && availableLayouts.length > 0 && (
285
- <div className="flex items-center gap-2">
286
- {availableLayouts.map((cols) => (
287
- <Button
288
- key={cols}
289
- onClick={() =>
290
- handleSelectFilter({
291
- key: 'layout',
292
- value: cols
293
- })
77
+ className={clsx('cursor-pointer', {
78
+ 'text-black font-semibold': Number(pageSize) === value
79
+ })}
80
+ >
81
+ {label}
82
+ </a>
83
+ ))}
84
+ <div className="flex items-center gap-2 pl-5 border-l border-gray-400">
85
+ {LAYOUTS.map(({ icon, value }) => (
86
+ <a
87
+ key={value}
88
+ onClick={() => {
89
+ handleSelectFilter({
90
+ key: 'layout',
91
+ value: String(value)
92
+ });
93
+ }}
94
+ className="cursor-pointer"
95
+ >
96
+ <Icon
97
+ key={value}
98
+ name={icon}
99
+ size={16}
100
+ className={
101
+ Number(layoutSize) === value
102
+ ? 'text-black'
103
+ : 'text-gray-500'
294
104
  }
295
- appearance="ghost"
296
- className={clsx(
297
- 'p-2 hover:bg-gray-100',
298
- layoutSize === cols && 'bg-gray-200'
299
- )}
300
- data-section-id="products-section"
301
- >
302
- <svg
303
- width="20"
304
- height="20"
305
- viewBox="0 0 20 20"
306
- fill="none"
307
- xmlns="http://www.w3.org/2000/svg"
308
- >
309
- {Array.from({ length: parseInt(cols) }).map((_, i) => {
310
- const colWidth = 20 / parseInt(cols);
311
- const gap = 2;
312
- const rectWidth = colWidth - gap;
313
- return (
314
- <g key={i}>
315
- <rect
316
- x={i * colWidth}
317
- y="0"
318
- width={rectWidth}
319
- height="8"
320
- fill="currentColor"
321
- />
322
- <rect
323
- x={i * colWidth}
324
- y="10"
325
- width={rectWidth}
326
- height="8"
327
- fill="currentColor"
328
- />
329
- </g>
330
- );
331
- })}
332
- </svg>
333
- </Button>
334
- ))}
335
- </div>
336
- )}
105
+ />
106
+ </a>
107
+ ))}
108
+ </div>
337
109
  </div>
338
- )}
339
-
340
- <div className="flex items-center w-full justify-between lg:hidden">
341
110
  <Button
342
- className="relative p-0 hover:bg-transparent hover:text-black"
111
+ className="relative border-gray-100 text-left mr-5 bg-white text-primary-100 w-40 lg:hidden lg:mr-0"
343
112
  onClick={() => setMenuStatus()}
344
- appearance="ghost"
345
113
  data-testid="list-filter"
346
114
  >
347
- <Icon name="filter-and-sort" size={20} />
348
- <span className="lg:hidden text-sm">
349
- {t('category.filters.mobile_title')}
350
- </span>
351
- <span className="hidden lg:block">{t('category.filters.title')}</span>
115
+ {t('category.filters.title')}
116
+ <Icon
117
+ name="chevron-down"
118
+ size={10}
119
+ className="absolute right-1 top-1/2 transform -translate-y-1/2"
120
+ />
352
121
  </Button>
353
- <span>
354
- <span data-testid="list-count">{totalCount}</span>{' '}
355
- {t('category.header.results')}
356
- </span>
122
+ <Select
123
+ options={sortOptions}
124
+ value={sortOptions?.find(({ is_selected }) => is_selected)?.value}
125
+ data-testid="list-sorter"
126
+ onChange={(e) => {
127
+ handleSelectFilter({
128
+ key: 'sorter',
129
+ value: e.currentTarget.value
130
+ });
131
+ }}
132
+ borderless={false}
133
+ />
357
134
  </div>
358
135
  {totalCount === 0 && (
359
136
  <div className="h-40 flex items-center justify-center flex-col bg-gray-200 p-4">