Loading...
;
+ }
+
+ if (error) {
+ return (
+
+
+
+
{title}
+
{products.length} models
+
+
+ handleSort(value as SortType)}
+ options={[
+ { value: 'age', label: 'Newest' },
+ { value: 'name', label: 'Alphabetically' },
+ { value: 'price', label: 'Cheapest' },
+ ]}
+ width={sortWidth}
+ />
+
+
+
+
+ {visibleProducts.length === 0 ? (
+
There are no {category} yet
+ ) : (
+
+ {visibleProducts.map(product => (
+
+ ))}
+
+ )}
+
+ {totalPages > 1 && (
+
+
+
+ {getVisiblePages().map(p => (
+
+ ))}
+
+
+
+ )}
+
+ );
+};
diff --git a/src/modules/shared/components/ProductsSlider/ProductsSlider.module.scss b/src/modules/shared/components/ProductsSlider/ProductsSlider.module.scss
new file mode 100644
index 00000000000..78757625428
--- /dev/null
+++ b/src/modules/shared/components/ProductsSlider/ProductsSlider.module.scss
@@ -0,0 +1,101 @@
+@use '../../../../styles/variables' as *;
+
+.slider {
+ margin-top: $spacing-xl;
+
+ @media (min-width: $breakpoint-tablet) {
+ margin-top: $spacing-2xl;
+ }
+
+ @media (min-width: $breakpoint-desktop) {
+ margin-top: $spacing-3xl;
+ }
+}
+
+.header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: $spacing-md;
+}
+
+.title {
+ font-size: $font-size-xl;
+ font-weight: 800;
+ color: var(--color-primary);
+ max-width: 136px;
+
+ @media (min-width: $breakpoint-tablet) {
+ max-width: none;
+ }
+
+ @media (min-width: $breakpoint-desktop) {
+ font-size: $font-size-2xl;
+ }
+}
+
+.buttons {
+ display: flex;
+ gap: $spacing-sm;
+}
+
+.btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border: 1px solid var(--color-elements);
+ transition: $transition;
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+
+ &:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+
+ &:hover:not(:disabled) {
+ border-color: var(--color-primary);
+ }
+
+}
+
+.listWrapper {
+ overflow: hidden;
+ width: 100%;
+
+ // @media (min-width: $breakpoint-tablet) {
+ // margin-right: -$container-padding-tablet;
+ // }
+
+ // @media (min-width: $breakpoint-desktop) {
+ // margin-right: 0;
+ // width: 100%;
+
+ // }
+}
+
+.list {
+ display: flex;
+ flex-wrap: nowrap;
+ gap: $spacing-sm;
+ transition: transform 0.3s ease;
+ transform: translateX(calc(-1 * var(--mobile-offset, 0px)));
+
+ @media (min-width: $breakpoint-tablet) {
+ transform: translateX(calc(-1 * var(--tablet-offset, 0px)));
+ }
+
+ @media (min-width: $breakpoint-desktop) {
+ transform: translateX(calc(-1 * var(--desktop-offset, 0px)));
+ }
+
+}
+
+.item {
+ min-width: 0;
+}
diff --git a/src/modules/shared/components/ProductsSlider/ProductsSlider.tsx b/src/modules/shared/components/ProductsSlider/ProductsSlider.tsx
new file mode 100644
index 00000000000..694bbc13ee7
--- /dev/null
+++ b/src/modules/shared/components/ProductsSlider/ProductsSlider.tsx
@@ -0,0 +1,93 @@
+import React, { useState, useRef } from 'react';
+import { Product } from '../../../../types';
+import { ProductCard } from '../ProductCard/ProductCard';
+import { getImg } from '../../../../utils/getImageUrl';
+import styles from './ProductsSlider.module.scss';
+
+type Props = {
+ title: string;
+ products: Product[];
+ showFullPriceOnly?: boolean;
+};
+
+export const ProductsSlider = ({
+ title,
+ products,
+ showFullPriceOnly = false,
+}: Props) => {
+ const [startIndex, setStartIndex] = useState(0);
+ const mobileCardWidth = 212 + 16;
+ const tabletCardWidth = 237 + 16;
+ const desktopCardWidth = 272 + 16;
+ const visibleCount = 4;
+ const listWrapperRef = useRef