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

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 (223) hide show
  1. package/CHANGELOG.md +9 -7
  2. package/app-template/CHANGELOG.md +251 -204
  3. package/app-template/akinon.json +1 -1
  4. package/app-template/package.json +28 -28
  5. package/app-template/public/amex.svg +12 -0
  6. package/app-template/public/apple-pay.svg +16 -0
  7. package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
  8. package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
  9. package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
  10. package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
  11. package/app-template/public/google-pay.svg +16 -0
  12. package/app-template/public/locales/en/account.json +6 -3
  13. package/app-template/public/locales/en/auth.json +6 -7
  14. package/app-template/public/locales/en/basket.json +6 -6
  15. package/app-template/public/locales/en/blog.json +7 -0
  16. package/app-template/public/locales/en/category.json +3 -1
  17. package/app-template/public/locales/en/checkout.json +5 -4
  18. package/app-template/public/locales/en/common.json +11 -2
  19. package/app-template/public/locales/en/forgot_password.json +6 -7
  20. package/app-template/public/locales/en/product.json +4 -3
  21. package/app-template/public/locales/tr/account.json +6 -3
  22. package/app-template/public/locales/tr/auth.json +16 -17
  23. package/app-template/public/locales/tr/basket.json +4 -4
  24. package/app-template/public/locales/tr/blog.json +7 -0
  25. package/app-template/public/locales/tr/category.json +3 -1
  26. package/app-template/public/locales/tr/checkout.json +39 -38
  27. package/app-template/public/locales/tr/common.json +10 -1
  28. package/app-template/public/locales/tr/forgot_password.json +12 -13
  29. package/app-template/public/locales/tr/product.json +1 -0
  30. package/app-template/public/logo.svg +3 -27
  31. package/app-template/public/mastercard.svg +14 -0
  32. package/app-template/public/promotion-banner.jpg +0 -0
  33. package/app-template/public/shop-pay.svg +12 -0
  34. package/app-template/public/visa.svg +12 -0
  35. package/app-template/src/app/[commerce]/[locale]/[currency]/blog/[slug]/page.tsx +118 -0
  36. package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +15 -0
  37. package/app-template/src/app/api/theme-settings/route.ts +12 -0
  38. package/app-template/src/assets/fonts/pz-icon.css +211 -49
  39. package/app-template/src/assets/fonts/pz-icon.eot +0 -0
  40. package/app-template/src/assets/fonts/pz-icon.html +486 -0
  41. package/app-template/src/assets/fonts/pz-icon.scss +373 -49
  42. package/app-template/src/assets/fonts/pz-icon.svg +215 -53
  43. package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
  44. package/app-template/src/assets/fonts/pz-icon.woff +0 -0
  45. package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
  46. package/app-template/src/assets/globals.scss +4 -0
  47. package/app-template/src/assets/icons/arrow-right.svg +3 -0
  48. package/app-template/src/assets/icons/cart.svg +4 -12
  49. package/app-template/src/assets/icons/check.svg +2 -18
  50. package/app-template/src/assets/icons/chevron-down.svg +2 -7
  51. package/app-template/src/assets/icons/delete.svg +3 -0
  52. package/app-template/src/assets/icons/facebook.svg +2 -8
  53. package/app-template/src/assets/icons/fav-off.svg +5 -0
  54. package/app-template/src/assets/icons/fav-on.svg +5 -0
  55. package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
  56. package/app-template/src/assets/icons/heart.svg +3 -0
  57. package/app-template/src/assets/icons/instagram.svg +2 -13
  58. package/app-template/src/assets/icons/materials.svg +3 -0
  59. package/app-template/src/assets/icons/person.svg +4 -0
  60. package/app-template/src/assets/icons/pinterest.svg +5 -11
  61. package/app-template/src/assets/icons/ruler.svg +3 -0
  62. package/app-template/src/assets/icons/search.svg +8 -11
  63. package/app-template/src/assets/icons/share.svg +2 -9
  64. package/app-template/src/assets/icons/snapchat.svg +3 -0
  65. package/app-template/src/assets/icons/tiktok.svg +3 -0
  66. package/app-template/src/assets/icons/tumblr.svg +6 -0
  67. package/app-template/src/assets/icons/twitter.svg +2 -10
  68. package/app-template/src/assets/icons/vimeo.svg +3 -0
  69. package/app-template/src/assets/icons/youtube.svg +3 -0
  70. package/app-template/src/assets/icons/zoom.svg +8 -0
  71. package/app-template/src/components/accordion.tsx +33 -11
  72. package/app-template/src/components/action-tooltip.tsx +160 -0
  73. package/app-template/src/components/currency-select.tsx +149 -4
  74. package/app-template/src/components/icon.tsx +5 -6
  75. package/app-template/src/components/index.ts +4 -1
  76. package/app-template/src/components/language-select.tsx +88 -2
  77. package/app-template/src/components/pagination.tsx +132 -20
  78. package/app-template/src/components/quantity-input.tsx +63 -0
  79. package/app-template/src/components/quantity-selector.tsx +203 -0
  80. package/app-template/src/components/route-handler.tsx +50 -0
  81. package/app-template/src/components/select.tsx +89 -69
  82. package/app-template/src/components/types/index.ts +26 -0
  83. package/app-template/src/components/widget-content.tsx +323 -0
  84. package/app-template/src/data/server/theme.ts +70 -0
  85. package/app-template/src/hooks/use-fav-button.tsx +5 -2
  86. package/app-template/src/hooks/use-product-cart.ts +11 -8
  87. package/app-template/src/hooks/use-theme-settings.ts +42 -0
  88. package/app-template/src/lib/fonts.ts +149 -0
  89. package/app-template/src/settings.js +2 -2
  90. package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
  91. package/app-template/src/types/widget.ts +169 -0
  92. package/app-template/src/utils/formatDate.ts +48 -0
  93. package/app-template/src/utils/styles.ts +71 -0
  94. package/app-template/src/views/account/contact-form.tsx +147 -130
  95. package/app-template/src/views/basket/basket-item.tsx +691 -107
  96. package/app-template/src/views/basket/basket-summary-context.tsx +560 -0
  97. package/app-template/src/views/basket/designer-context.tsx +617 -0
  98. package/app-template/src/views/basket/index.ts +2 -0
  99. package/app-template/src/views/basket/summary.tsx +496 -75
  100. package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +190 -0
  101. package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +286 -0
  102. package/app-template/src/views/breadcrumb/constants.ts +15 -0
  103. package/app-template/src/views/breadcrumb/index.tsx +127 -0
  104. package/app-template/src/views/breadcrumb.tsx +13 -38
  105. package/app-template/src/views/category/category-banner.tsx +4 -23
  106. package/app-template/src/views/category/category-header.tsx +289 -66
  107. package/app-template/src/views/category/category-info.tsx +173 -24
  108. package/app-template/src/views/category/filters/filter-item.tsx +138 -42
  109. package/app-template/src/views/category/filters/index.tsx +208 -48
  110. package/app-template/src/views/category/layout.tsx +7 -4
  111. package/app-template/src/views/category/native-widget-context.tsx +257 -0
  112. package/app-template/src/views/category/product-list-registrar.tsx +665 -0
  113. package/app-template/src/views/checkout/auth.tsx +64 -40
  114. package/app-template/src/views/checkout/checkout-address-registrar.tsx +254 -0
  115. package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +183 -0
  116. package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +259 -0
  117. package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +253 -0
  118. package/app-template/src/views/checkout/checkout-summary-registrar.tsx +183 -0
  119. package/app-template/src/views/checkout/constants.ts +5 -0
  120. package/app-template/src/views/checkout/index.tsx +5 -0
  121. package/app-template/src/views/checkout/layout/header.tsx +9 -5
  122. package/app-template/src/views/checkout/steps/payment/index.tsx +5 -2
  123. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +72 -1
  124. package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +15 -0
  125. package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +18 -0
  126. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +171 -40
  127. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +74 -12
  128. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +128 -45
  129. package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +232 -27
  130. package/app-template/src/views/checkout/summary.tsx +303 -29
  131. package/app-template/src/views/footer/footer-app-banner-context.tsx +326 -0
  132. package/app-template/src/views/footer/footer-bottom-context.tsx +215 -0
  133. package/app-template/src/views/footer/footer-bottom-wrapper.tsx +74 -0
  134. package/app-template/src/views/footer/footer-layout-constants.ts +35 -0
  135. package/app-template/src/views/footer/footer-layout-registrar.tsx +342 -0
  136. package/app-template/src/views/footer/footer-layout-switcher.tsx +110 -0
  137. package/app-template/src/views/footer/footer-menu-context.tsx +211 -0
  138. package/app-template/src/views/footer/footer-native-widgets.tsx +60 -0
  139. package/app-template/src/views/footer/footer-social-context.tsx +254 -0
  140. package/app-template/src/views/footer/footer-subscription-context.tsx +210 -0
  141. package/app-template/src/views/footer/footer-utils.ts +43 -0
  142. package/app-template/src/views/footer/footer-value-props-context.tsx +326 -0
  143. package/app-template/src/views/footer/logo-settings.ts +183 -0
  144. package/app-template/src/views/footer/native-widget-config.ts +262 -0
  145. package/app-template/src/views/footer/subscription-settings.ts +122 -0
  146. package/app-template/src/views/footer/use-footer-logo.ts +162 -0
  147. package/app-template/src/views/footer.tsx +415 -13
  148. package/app-template/src/views/guest-login/index.tsx +62 -58
  149. package/app-template/src/views/header/action-menu.tsx +277 -45
  150. package/app-template/src/views/header/band.tsx +6 -21
  151. package/app-template/src/views/header/designer-context.tsx +261 -0
  152. package/app-template/src/views/header/header-announcement-registrar.tsx +267 -0
  153. package/app-template/src/views/header/header-client-wrapper.tsx +496 -0
  154. package/app-template/src/views/header/header-content.tsx +1026 -0
  155. package/app-template/src/views/header/header-currency-registrar.tsx +348 -0
  156. package/app-template/src/views/header/header-icons-context.tsx +262 -0
  157. package/app-template/src/views/header/header-language-registrar.tsx +348 -0
  158. package/app-template/src/views/header/header-layout-context.tsx +143 -0
  159. package/app-template/src/views/header/header-layout-registrar.tsx +658 -0
  160. package/app-template/src/views/header/header-logo-context.tsx +228 -0
  161. package/app-template/src/views/header/header-logo.tsx +118 -0
  162. package/app-template/src/views/header/header-mini-basket-context.tsx +524 -0
  163. package/app-template/src/views/header/header-search-registrar.tsx +511 -0
  164. package/app-template/src/views/header/header-text-slider-registrar.tsx +382 -0
  165. package/app-template/src/views/header/index.tsx +109 -47
  166. package/app-template/src/views/header/inline-search.tsx +262 -0
  167. package/app-template/src/views/header/mini-basket.tsx +819 -44
  168. package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
  169. package/app-template/src/views/header/mobile-menu.tsx +12 -0
  170. package/app-template/src/views/header/navbar-menu-context.tsx +219 -0
  171. package/app-template/src/views/header/navbar.tsx +178 -111
  172. package/app-template/src/views/header/search/index.tsx +71 -32
  173. package/app-template/src/views/header/search/results.tsx +127 -65
  174. package/app-template/src/views/header/search/search-input.tsx +61 -0
  175. package/app-template/src/views/header/server-settings-parser.ts +1105 -0
  176. package/app-template/src/views/header/use-header-icons.ts +241 -0
  177. package/app-template/src/views/header/use-header-logo.ts +213 -0
  178. package/app-template/src/views/header/use-navbar-menu.ts +179 -0
  179. package/app-template/src/views/login/index.tsx +54 -46
  180. package/app-template/src/views/product/accordion-section.tsx +61 -0
  181. package/app-template/src/views/product/accordion-wrapper.tsx +135 -43
  182. package/app-template/src/views/product/custom-button-group.tsx +69 -0
  183. package/app-template/src/views/product/favorites-button-section.tsx +69 -0
  184. package/app-template/src/views/product/find-in-store-section.tsx +60 -0
  185. package/app-template/src/views/product/index.ts +1 -0
  186. package/app-template/src/views/product/layout.tsx +6 -5
  187. package/app-template/src/views/product/misc-buttons.tsx +339 -25
  188. package/app-template/src/views/product/price-wrapper.tsx +3 -29
  189. package/app-template/src/views/product/product-actions.tsx +137 -8
  190. package/app-template/src/views/product/product-info-section.tsx +140 -0
  191. package/app-template/src/views/product/product-info.tsx +69 -31
  192. package/app-template/src/views/product/product-share.tsx +13 -8
  193. package/app-template/src/views/product/product-variants.tsx +2 -2
  194. package/app-template/src/views/product/quantity-section.tsx +73 -0
  195. package/app-template/src/views/product/sale-tag.tsx +10 -0
  196. package/app-template/src/views/product/share-section.tsx +357 -0
  197. package/app-template/src/views/product/slider.tsx +117 -79
  198. package/app-template/src/views/product/variant.tsx +69 -41
  199. package/app-template/src/views/product/variants-section.tsx +126 -0
  200. package/app-template/src/views/product-detail/constants.ts +272 -0
  201. package/app-template/src/views/product-detail/index.ts +10 -0
  202. package/app-template/src/views/product-detail/product-detail-registrar.tsx +616 -0
  203. package/app-template/src/views/product-item/index.tsx +119 -46
  204. package/app-template/src/views/register/index.tsx +14 -25
  205. package/app-template/src/views/share/index.tsx +9 -6
  206. package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
  207. package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
  208. package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
  209. package/app-template/src/widgets/footer-app-banner.tsx +444 -0
  210. package/app-template/src/widgets/footer-bottom.tsx +127 -0
  211. package/app-template/src/widgets/footer-menu-compact.tsx +238 -0
  212. package/app-template/src/widgets/footer-menu-two.tsx +298 -0
  213. package/app-template/src/widgets/footer-social-client.tsx +251 -0
  214. package/app-template/src/widgets/footer-social.tsx +47 -16
  215. package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
  216. package/app-template/src/widgets/footer-subscription/index.tsx +183 -17
  217. package/app-template/src/widgets/footer-value-props.tsx +201 -0
  218. package/app-template/src/widgets/index.ts +7 -0
  219. package/app-template/src/widgets/schemas/about-us.json +46 -0
  220. package/app-template/src/widgets/schemas/blog-list.json +37 -0
  221. package/app-template/src/widgets/schemas/blog.json +29 -0
  222. package/app-template/tailwind.config.js +18 -2
  223. package/package.json +1 -1
@@ -1,34 +1,15 @@
1
1
  'use client';
2
2
 
3
3
  import { Category } from '@akinon/next/types';
4
- import { Image } from '@akinon/next/components/image';
5
4
 
6
- export const CategoryBanner = (
7
- props: Category['attributes']['category_banner']
8
- ) => {
5
+ export const CategoryBanner = (props: Category['attributes']['banner']) => {
9
6
  if (Object.keys(props).length === 0) {
10
7
  return null;
11
8
  }
12
9
 
13
10
  return (
14
- <>
15
- <Image
16
- src={props.kwargs.value.image_mobile.url}
17
- alt="Category Banner"
18
- aspectRatio={768 / 375}
19
- sizes="768px"
20
- fill
21
- className="block md:hidden"
22
- />
23
-
24
- <Image
25
- src={props.kwargs.value.image_desktop.url}
26
- alt="Category Banner"
27
- aspectRatio={1370 / 400}
28
- sizes="1370px"
29
- fill
30
- className="hidden md:block"
31
- />
32
- </>
11
+ <h1 className="text-3xl lg:text-[40px] mb-5 lg:mb-10">
12
+ {props.value.title}
13
+ </h1>
33
14
  );
34
15
  };
@@ -1,13 +1,17 @@
1
1
  'use client';
2
2
 
3
- import React, { useMemo } from 'react';
3
+ import React, { useMemo, useState, useTransition, CSSProperties } 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';
9
11
 
10
12
  import { useRouter, useLocalization } from '@akinon/next/hooks';
13
+ import { useProductList } from './product-list-registrar';
14
+ import { useNativeWidget } from './native-widget-context';
11
15
 
12
16
  interface Props {
13
17
  totalCount: number;
@@ -28,16 +32,76 @@ export const CategoryHeader = (props: Props) => {
28
32
  ];
29
33
  const { totalCount, setMenuStatus, sortOptions } = props;
30
34
  const router = useRouter();
35
+ const facets = useAppSelector((state) => state.category.facets);
36
+ const [openDropdown, setOpenDropdown] = useState<string | null>(null);
37
+ const [isPending, startTransition] = useTransition();
31
38
 
32
39
  const searchParams = useSearchParams();
33
40
  const pathname = usePathname();
34
41
 
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
+
35
99
  const pageSize = useMemo(
36
100
  () => searchParams.get('page_size') ?? 48,
37
101
  [searchParams]
38
102
  );
39
103
  const layoutSize = useMemo(
40
- () => searchParams.get('layout') ?? 3,
104
+ () => searchParams.get('layout') ?? '3',
41
105
  [searchParams]
42
106
  );
43
107
 
@@ -55,82 +119,241 @@ export const CategoryHeader = (props: Props) => {
55
119
  router.push(pathname + '?' + urlSearchParams.toString());
56
120
  };
57
121
 
58
- return (
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>
122
+ const facetButtonStyles = {
123
+ paddingTop: `${itemPaddingY}px`,
124
+ paddingBottom: `${itemPaddingY}px`,
125
+ paddingLeft: `${itemPaddingX}px`,
126
+ paddingRight: `${itemPaddingX}px`,
127
+ marginRight: `${itemMarginBottom}px`
128
+ };
65
129
 
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={() => {
72
- handleSelectFilter({
73
- key: 'page_size',
74
- value: String(value)
75
- });
76
- }}
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"
130
+ 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"
95
149
  >
150
+ <span>{facet.name}</span>
96
151
  <Icon
97
- key={value}
98
- name={icon}
152
+ name="chevron-down"
99
153
  size={16}
100
- className={
101
- Number(layoutSize) === value
102
- ? 'text-black'
103
- : 'text-gray-500'
104
- }
154
+ className={clsx(
155
+ 'transition-transform',
156
+ openDropdown === facet.key && 'rotate-180'
157
+ )}
105
158
  />
106
- </a>
107
- ))}
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>
108
253
  </div>
109
254
  </div>
255
+ )}
256
+
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) => {
271
+ handleSelectFilter({
272
+ key: 'sorter',
273
+ value: e.currentTarget.value
274
+ });
275
+ }}
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
+ })
294
+ }
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
+ )}
337
+ </div>
338
+ )}
339
+
340
+ <div className="flex items-center w-full justify-between lg:hidden">
110
341
  <Button
111
- className="relative border-gray-100 text-left mr-5 bg-white text-primary-100 w-40 lg:hidden lg:mr-0"
342
+ className="relative p-0 hover:bg-transparent hover:text-black"
112
343
  onClick={() => setMenuStatus()}
344
+ appearance="ghost"
113
345
  data-testid="list-filter"
114
346
  >
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
- />
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>
121
352
  </Button>
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
- />
353
+ <span>
354
+ <span data-testid="list-count">{totalCount}</span>{' '}
355
+ {t('category.header.results')}
356
+ </span>
134
357
  </div>
135
358
  {totalCount === 0 && (
136
359
  <div className="h-40 flex items-center justify-center flex-col bg-gray-200 p-4">