diff --git a/.eslintrc.js b/.eslintrc.js
index cefb7cc..6bea878 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,26 +1,26 @@
-module.exports = {
- parser: '@typescript-eslint/parser',
- extends: ['@mate-academy/eslint-config-react-typescript'],
- plugins: ['@typescript-eslint', 'react-hooks', 'prettier'],
- parserOptions: {
- ecmaVersion: 2018,
- sourceType: 'module',
- ecmaFeatures: {
- jsx: true,
- },
- },
- env: {
- browser: true,
- node: true,
- es6: true,
- jest: true,
- },
- rules: {
- 'linebreak-style': 'off',
- },
- settings: {
- react: {
- version: 'detect',
- },
- },
-};
+module.exports = {
+ parser: '@typescript-eslint/parser',
+ extends: ['@mate-academy/eslint-config-react-typescript'],
+ plugins: ['@typescript-eslint', 'react-hooks', 'prettier'],
+ parserOptions: {
+ ecmaVersion: 2018,
+ sourceType: 'module',
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ env: {
+ browser: true,
+ node: true,
+ es6: true,
+ jest: true,
+ },
+ rules: {
+ 'linebreak-style': 'off',
+ },
+ settings: {
+ react: {
+ version: 'detect',
+ },
+ },
+};
diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 43bf5e1..05e0512 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -1,45 +1,45 @@
-name: Checking with lint
-
-on:
- pull_request:
- branches: [ master ]
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- strategy:
- matrix:
- node-version: [14.x]
-
- steps:
- - name: Checkout repository ๐
- uses: actions/checkout@v3
-
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
- with:
- node-version: ${{ matrix.node-version }}
-
- - name: Cache dependencies ๐ฆ
- uses: actions/cache@v3
- with:
- path: |
- **/node_modules
- key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
-
- - name: Install dependencies ๐
- run: npm install
-
- - name: Run the lint ๐งช
- run: npm run lint
-
- - name: Build ๐ง
- run: npm run build
-
- env:
- user_name: 'github-actions[bot]'
- user_email: 'github-actions[bot]@users.noreply.github.com'
- github_token: ${{ secrets.ACTIONS_DEPLOY_ACCESS_TOKEN }}
- repository: ${{ github.repository }}
+name: Checking with lint
+
+on:
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ node-version: [14.x]
+
+ steps:
+ - name: Checkout repository ๐
+ uses: actions/checkout@v3
+
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ matrix.node-version }}
+
+ - name: Cache dependencies ๐ฆ
+ uses: actions/cache@v3
+ with:
+ path: |
+ **/node_modules
+ key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
+
+ - name: Install dependencies ๐
+ run: npm install
+
+ - name: Run the lint ๐งช
+ run: npm run lint
+
+ - name: Build ๐ง
+ run: npm run build
+
+ env:
+ user_name: 'github-actions[bot]'
+ user_email: 'github-actions[bot]@users.noreply.github.com'
+ github_token: ${{ secrets.ACTIONS_DEPLOY_ACCESS_TOKEN }}
+ repository: ${{ github.repository }}
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 8689578..9a74794 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -1,51 +1,51 @@
-name: Auto deploy
-
-on:
- push:
- branches: [ master ]
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- strategy:
- matrix:
- node-version: [14.x]
-
- steps:
- - name: Checkout repository ๐
- uses: actions/checkout@v3
-
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
- with:
- node-version: ${{ matrix.node-version }}
-
- - name: Cache dependencies ๐ฆ
- uses: actions/cache@v3
- with:
- path: |
- **/node_modules
- key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
-
- - name: Install dependencies ๐
- run: npm install
-
- - name: Run the lint ๐งช
- run: npm run lint
-
- - name: Build ๐ง
- run: npm run build
-
- - name: Deploy ๐
- run: |
- git config --global user.name $user_name
- git config --global user.email $user_email
- git remote set-url origin https://${github_token}@github.com/${repository}
- npm run deploy
- env:
- user_name: 'github-actions[bot]'
- user_email: 'github-actions[bot]@users.noreply.github.com'
- github_token: ${{ secrets.ACTIONS_DEPLOY_ACCESS_TOKEN }}
- repository: ${{ github.repository }}
+name: Auto deploy
+
+on:
+ push:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ node-version: [14.x]
+
+ steps:
+ - name: Checkout repository ๐
+ uses: actions/checkout@v3
+
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ matrix.node-version }}
+
+ - name: Cache dependencies ๐ฆ
+ uses: actions/cache@v3
+ with:
+ path: |
+ **/node_modules
+ key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
+
+ - name: Install dependencies ๐
+ run: npm install
+
+ - name: Run the lint ๐งช
+ run: npm run lint
+
+ - name: Build ๐ง
+ run: npm run build
+
+ - name: Deploy ๐
+ run: |
+ git config --global user.name $user_name
+ git config --global user.email $user_email
+ git remote set-url origin https://${github_token}@github.com/${repository}
+ npm run deploy
+ env:
+ user_name: 'github-actions[bot]'
+ user_email: 'github-actions[bot]@users.noreply.github.com'
+ github_token: ${{ secrets.ACTIONS_DEPLOY_ACCESS_TOKEN }}
+ repository: ${{ github.repository }}
diff --git a/.prettierrc b/.prettierrc
index e73e0b5..e84c7e8 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,8 +1,8 @@
-{
- "printWidth": 80,
- "tabWidth": 2,
- "singleQuote": true,
- "semi": true,
- "trailingComma": "all",
- "bracketSpacing": true
-}
+{
+ "printWidth": 80,
+ "tabWidth": 2,
+ "singleQuote": true,
+ "semi": true,
+ "trailingComma": "all",
+ "bracketSpacing": true
+}
diff --git a/package-lock.json b/package-lock.json
index 01856f3..f5a937a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12054,9 +12054,9 @@
}
},
"typescript": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
- "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
+ "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true
},
"unbox-primitive": {
diff --git a/public/banner-accessories.png b/public/banner-accessories.png
deleted file mode 100644
index 28b5c4c..0000000
Binary files a/public/banner-accessories.png and /dev/null differ
diff --git a/public/banner-phones.png b/public/banner-phones.png
deleted file mode 100644
index 09b0654..0000000
Binary files a/public/banner-phones.png and /dev/null differ
diff --git a/public/banner-tablets.png b/public/banner-tablets.png
deleted file mode 100644
index 45e303b..0000000
Binary files a/public/banner-tablets.png and /dev/null differ
diff --git a/public/banners/banner-accessories.webp b/public/banners/banner-accessories.webp
new file mode 100644
index 0000000..d9e69fe
Binary files /dev/null and b/public/banners/banner-accessories.webp differ
diff --git a/public/banners/banner-phones.webp b/public/banners/banner-phones.webp
new file mode 100644
index 0000000..6498893
Binary files /dev/null and b/public/banners/banner-phones.webp differ
diff --git a/public/banners/banner-tablets.webp b/public/banners/banner-tablets.webp
new file mode 100644
index 0000000..05ca339
Binary files /dev/null and b/public/banners/banner-tablets.webp differ
diff --git a/public/icons/Buttons/Icons/ArrowLeft.svg b/public/icons/Buttons/Icons/ArrowLeft.svg
index 5a64cef..ef8650b 100644
--- a/public/icons/Buttons/Icons/ArrowLeft.svg
+++ b/public/icons/Buttons/Icons/ArrowLeft.svg
@@ -1,3 +1,3 @@
-
+
diff --git a/public/icons/Buttons/Icons/ArrowRight.svg b/public/icons/Buttons/Icons/ArrowRight.svg
index e0ec5e5..c609788 100644
--- a/public/icons/Buttons/Icons/ArrowRight.svg
+++ b/public/icons/Buttons/Icons/ArrowRight.svg
@@ -1,3 +1,3 @@
-
+
diff --git a/public/index.html b/public/index.html
index 7311733..d2de9a0 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,19 +1,19 @@
-
-
-
-
-
-
-
-
-
-
- Nice Gadgets
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ Nice Gadgets
+
+
+
+
+
+
diff --git a/src/Root.tsx b/src/Root.tsx
index 0e8c4fc..335c982 100644
--- a/src/Root.tsx
+++ b/src/Root.tsx
@@ -6,15 +6,22 @@ import {
} from 'react-router-dom';
import { App } from './App';
import { HomePage } from './modules/HomePage';
-import { PhonesPage } from './modules/PhonesPage';
+import { ProductsPage } from './modules/PhonesPage';
import { ProductDetailsPage } from './modules/ProductDetailsPage';
import { CartPage } from './modules/CartPage';
import { NotFoundPage } from './modules/NotFoundPage';
-import { TabletsPage } from './modules/TabletsPage';
import { PageInProgress } from './modules/PageInProgress';
-import { AccessoriesPage } from './modules/AccessoriesPage';
import { FavoritesPage } from './modules/FavoritesPage';
-import { getProductDetail } from './api/service';
+import {
+ getProductDetail,
+ getProductsWithSearchParams as loadPhones,
+ getProductAmount as loadPhonesAmount,
+} from './api/service';
+import { EndPoints } from './types/Enums';
+
+const MOBILE_TITLE = 'Mobile phones';
+// const TABLETS_TITLE = 'Tablet';
+// const ACCESSOTIES_TITLE = 'Accessories';
export const Root = () => (
@@ -24,14 +31,44 @@ export const Root = () => (
} />
} />
- } />
+
+ )}
+ />
}
+ element={(
+
+ )}
/>
- } />
- } />
+ {/* }
+ /> */}
+ {/* }
+ /> */}
} />
} />
} />
diff --git a/src/modules/AccessoriesPage/AccessoriesPage.tsx b/src/modules/AccessoriesPage/AccessoriesPage.tsx
index f3d43d0..1e0692a 100644
--- a/src/modules/AccessoriesPage/AccessoriesPage.tsx
+++ b/src/modules/AccessoriesPage/AccessoriesPage.tsx
@@ -1,7 +1,7 @@
-import './AccessoriesPage.module.scss';
-
-import React from 'react';
-
-export const AccessoriesPage: React.FC = () => {
- return Accessories Page
;
-};
+import './AccessoriesPage.module.scss';
+
+import React from 'react';
+
+export const AccessoriesPage: React.FC = () => {
+ return Accessories Page
;
+};
diff --git a/src/modules/AccessoriesPage/index.ts b/src/modules/AccessoriesPage/index.ts
index 486474a..0cc97ca 100644
--- a/src/modules/AccessoriesPage/index.ts
+++ b/src/modules/AccessoriesPage/index.ts
@@ -1 +1 @@
-export * from './AccessoriesPage';
+export * from './AccessoriesPage';
diff --git a/src/modules/CartPage/CartPage.module.scss b/src/modules/CartPage/CartPage.module.scss
index 2d9354b..6bb528d 100644
--- a/src/modules/CartPage/CartPage.module.scss
+++ b/src/modules/CartPage/CartPage.module.scss
@@ -107,11 +107,21 @@
color: $color__white;
@include buttons-typography;
background-color: $color__accent;
+ cursor: pointer;
+ transition: all 0.3s ease;
+
+ &:hover {
+ box-shadow: 0px 3px 13px 0px rgba(23, 32, 49, 0.40);
+ }
&__DARK {
border-radius: 0;
color: $color__dark-theme__white;
background-color: $color__dark-theme__accent;
+
+ &:hover {
+ background-color: $color__dark-theme__accent__hover;
+ }
}
}
diff --git a/src/modules/CartPage/components/CartItem/index.ts b/src/modules/CartPage/components/CartItem/index.ts
index 37a0553..7f07517 100644
--- a/src/modules/CartPage/components/CartItem/index.ts
+++ b/src/modules/CartPage/components/CartItem/index.ts
@@ -1 +1 @@
-export * from './CartItem';
+export * from './CartItem';
diff --git a/src/modules/FavoritesPage/HomeIcon.tsx b/src/modules/FavoritesPage/HomeIcon.tsx
index 9a89871..be6c45d 100644
--- a/src/modules/FavoritesPage/HomeIcon.tsx
+++ b/src/modules/FavoritesPage/HomeIcon.tsx
@@ -1,46 +1,46 @@
-import React, { FC, SVGProps } from 'react';
-
-interface IconProps extends SVGProps {
- color: string;
-}
-
-export const HomeIcon: FC = ({ color, ...props }) => {
- return (
-
- );
-};
+import React, { FC, SVGProps } from 'react';
+
+interface IconProps extends SVGProps {
+ color: string;
+}
+
+export const HomeIcon: FC = ({ color, ...props }) => {
+ return (
+
+ );
+};
diff --git a/src/modules/HomePage/HomePage.module.scss b/src/modules/HomePage/HomePage.module.scss
index 4d35aab..69a1a50 100644
--- a/src/modules/HomePage/HomePage.module.scss
+++ b/src/modules/HomePage/HomePage.module.scss
@@ -1,19 +1,19 @@
-@import '../../styles/utils/mixins/mixin-media';
-@import '../../styles/utils/mixins/mixin-typography';
-
-.title {
- margin-bottom: 24px;
- @include h1-typography;
-
- @include onTablet {
- margin-bottom: 32px;
- }
-
- @include onDesktop {
- margin-bottom: 56px;
- }
-
- &__DARK {
- @include typography-dark;
- }
-}
+@import '../../styles/utils/mixins/mixin-media';
+@import '../../styles/utils/mixins/mixin-typography';
+
+.title {
+ margin-bottom: 24px;
+ @include h1-typography;
+
+ @include onTablet {
+ margin-bottom: 32px;
+ }
+
+ @include onDesktop {
+ margin-bottom: 56px;
+ }
+
+ &__DARK {
+ @include typography-dark;
+ }
+}
diff --git a/src/modules/HomePage/HomePage.tsx b/src/modules/HomePage/HomePage.tsx
index 298b15f..6b2d645 100644
--- a/src/modules/HomePage/HomePage.tsx
+++ b/src/modules/HomePage/HomePage.tsx
@@ -1,52 +1,63 @@
-import React, { useEffect, useState } from 'react';
-import cn from 'classnames';
-
-import styles from './HomePage.module.scss';
-
-import { ShopByCategory } from './componets/ShopByCategory';
-import { MainTitle } from './componets/MainTitle';
-import { MainSlider } from './componets/MainSlider';
-import { ProductSlider } from '../shared/ProductSlider';
-import { useAppSelector } from '../../store/hooks';
-import { getNewestProducts, getProductsWithDiscount } from '../../api/service';
-import { Product } from '../../types/Product';
-
-export const HomePage: React.FC = () => {
- const [newPhones, setNewPhones] = useState([]);
- const [phonesWithDiscount, setPhonesWithDiscount] = useState([]);
- const { isDarkTheme } = useAppSelector((state) => state.theme);
-
- useEffect(() => {
- getNewestProducts().then(setNewPhones);
-
- getProductsWithDiscount().then(setPhonesWithDiscount);
- }, []);
-
- return (
- <>
-
-
-
- Welcome to Nice Gadgets store!
-
-
-
-
-
-
-
-
-
- >
- );
-};
+import React, { useEffect, useState } from 'react';
+import cn from 'classnames';
+
+import styles from './HomePage.module.scss';
+
+import { ShopByCategory } from './componets/ShopByCategory';
+import { MainTitle } from './componets/MainTitle';
+import { MainSlider } from './componets/MainSlider';
+import { ProductSlider } from '../shared/ProductSlider';
+import { useAppSelector } from '../../store/hooks';
+import { getNewestProducts, getProductsWithDiscount } from '../../api/service';
+import { Product } from '../../types/Product';
+import { Loader } from '../shared/Loader';
+
+export const HomePage: React.FC = () => {
+ const [newPhones, setNewPhones] = useState([]);
+ const [phonesWithDiscount, setPhonesWithDiscount] = useState([]);
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+
+ useEffect(() => {
+ getNewestProducts().then(setNewPhones);
+
+ getProductsWithDiscount().then(setPhonesWithDiscount);
+ }, []);
+
+ return (
+ <>
+
+
+
+ Welcome to Nice Gadgets store!
+
+
+
+
+ {!newPhones.length
+ ? (
+
+ ) : (
+
+ )}
+
+
+
+ {!phonesWithDiscount.length ? (
+
+ ) : (
+
+ )}
+
+ >
+ );
+};
diff --git a/src/modules/HomePage/componets/MainSlider/MainSlider.module.scss b/src/modules/HomePage/componets/MainSlider/MainSlider.module.scss
index beceb1b..c0afdba 100644
--- a/src/modules/HomePage/componets/MainSlider/MainSlider.module.scss
+++ b/src/modules/HomePage/componets/MainSlider/MainSlider.module.scss
@@ -1,44 +1,44 @@
-@import '../../../../styles/blocks/grid';
-@import './slick.scss';
-
-.container {
- @extend .grid;
-}
-
-.slider {
- position: relative;
- width: 100%;
- height: 432px;
- border: none;
- box-sizing: border-box;
-
- @include onMobile {
- grid-column: 1 / -1;
- }
-
- @include onTablet {
- grid-column: 2 / 12;
- }
-
- @include onDesktop {
- grid-column: 2 / 24;
- }
-}
-
-.sliderPhoto {
- position: relative;
- overflow: hidden;
- width: 100%;
- height: 320px;
-
- object-fit: cover;
- object-position: center center;
-
- @include onTablet {
- height: 400px;
- }
-
- @include onDesktop {
- height: 400px;
- }
-}
+@import '../../../../styles/blocks/grid';
+@import './slick.scss';
+
+.container {
+ @extend .grid;
+}
+
+.slider {
+ position: relative;
+ width: 100%;
+ height: 432px;
+ border: none;
+ box-sizing: border-box;
+
+ @include onMobile {
+ grid-column: 1 / -1;
+ }
+
+ @include onTablet {
+ grid-column: 2 / 12;
+ }
+
+ @include onDesktop {
+ grid-column: 2 / 24;
+ }
+}
+
+.sliderPhoto {
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+ height: 320px;
+
+ object-fit: cover;
+ object-position: center center;
+
+ @include onTablet {
+ height: 400px;
+ }
+
+ @include onDesktop {
+ height: 400px;
+ }
+}
diff --git a/src/modules/HomePage/componets/MainSlider/MainSlider.tsx b/src/modules/HomePage/componets/MainSlider/MainSlider.tsx
index d98d3d6..30787a2 100644
--- a/src/modules/HomePage/componets/MainSlider/MainSlider.tsx
+++ b/src/modules/HomePage/componets/MainSlider/MainSlider.tsx
@@ -1,74 +1,74 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import React, { createRef, useEffect } from 'react';
-import Slider from 'react-slick';
-import cn from 'classnames';
-
-import './slick.scss';
-import './slick-theme.scss';
-
-import { bannersData } from '../../../../static/banners/bannersData';
-import style from './MainSlider.module.scss';
-import { useAppSelector } from '../../../../store/hooks';
-import { SampleNextArrow } from './SampleNextArrow';
-import { SamplePrevArrow } from './SamplePrevArrow';
-
-export const MainSlider: React.FC = () => {
- const ref = createRef();
-
- const { isDarkTheme } = useAppSelector((state) => state.theme);
- // const isDarkTheme = true;
- const settings = {
- dots: true,
- infinite: true,
- speed: 500,
- slidesToShow: 1,
- slidesToScroll: 1,
- autoplay: true,
- autoplaySpeed: 5000,
- pauseOnHover: true,
- swipeToSlide: true,
- nextArrow: ,
- prevArrow: ,
- adaptiveHeight: true,
- appendDots: (dots: any) => (
-
- ),
- };
-
- useEffect(() => {
- if (ref.current && isDarkTheme) {
- ref.current.className = 'slick-dots slick-dots__dark';
- }
-
- if (ref.current && !isDarkTheme) {
- ref.current.className = 'slick-dots';
- }
- }, [ref, isDarkTheme]);
-
- return (
-
-
- {bannersData.map(banner => (
-
-
-
- ))}
-
-
- );
-};
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import React, { createRef, useEffect } from 'react';
+import Slider from 'react-slick';
+import cn from 'classnames';
+
+import './slick.scss';
+import './slick-theme.scss';
+
+import { bannersData } from '../../../../static/banners/bannersData';
+import style from './MainSlider.module.scss';
+import { useAppSelector } from '../../../../store/hooks';
+import { SampleNextArrow } from './SampleNextArrow';
+import { SamplePrevArrow } from './SamplePrevArrow';
+
+export const MainSlider: React.FC = () => {
+ const ref = createRef();
+
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ // const isDarkTheme = true;
+ const settings = {
+ dots: true,
+ infinite: true,
+ speed: 500,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ autoplay: true,
+ autoplaySpeed: 5000,
+ pauseOnHover: true,
+ swipeToSlide: true,
+ nextArrow: ,
+ prevArrow: ,
+ adaptiveHeight: true,
+ appendDots: (dots: any) => (
+
+ ),
+ };
+
+ useEffect(() => {
+ if (ref.current && isDarkTheme) {
+ ref.current.className = 'slick-dots slick-dots__dark';
+ }
+
+ if (ref.current && !isDarkTheme) {
+ ref.current.className = 'slick-dots';
+ }
+ }, [ref, isDarkTheme]);
+
+ return (
+
+
+ {bannersData.map(banner => (
+
+
+
+ ))}
+
+
+ );
+};
diff --git a/src/modules/HomePage/componets/MainSlider/SampleNextArrow.tsx b/src/modules/HomePage/componets/MainSlider/SampleNextArrow.tsx
index f15f784..e46c63c 100644
--- a/src/modules/HomePage/componets/MainSlider/SampleNextArrow.tsx
+++ b/src/modules/HomePage/componets/MainSlider/SampleNextArrow.tsx
@@ -1,35 +1,35 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import React, { useState } from 'react';
-import {
- ReactComponent as NextIcon,
-} from '../../../../static/icons/arrow-right_icon.svg';
-import { useAppSelector } from '../../../../store/hooks';
-
-export const SampleNextArrow: React.FC = (props: any) => {
- const [isHover, setIsHover] = useState(false);
-
- const { className, style, onClick } = props;
- const { isDarkTheme } = useAppSelector((state) => state.theme);
-
- return (
- <>
-
- >
- );
-};
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import React, { useState } from 'react';
+import {
+ ReactComponent as NextIcon,
+} from '../../../../static/icons/arrow-right_icon.svg';
+import { useAppSelector } from '../../../../store/hooks';
+
+export const SampleNextArrow: React.FC = (props: any) => {
+ const [isHover, setIsHover] = useState(false);
+
+ const { className, style, onClick } = props;
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src/modules/HomePage/componets/MainSlider/SamplePrevArrow.tsx b/src/modules/HomePage/componets/MainSlider/SamplePrevArrow.tsx
index fd27a23..b2e4ddf 100644
--- a/src/modules/HomePage/componets/MainSlider/SamplePrevArrow.tsx
+++ b/src/modules/HomePage/componets/MainSlider/SamplePrevArrow.tsx
@@ -1,35 +1,35 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import React, { useState } from 'react';
-import {
- ReactComponent as PrevIcon,
-} from '../../../../static/icons/arrow-left_icon.svg';
-import { useAppSelector } from '../../../../store/hooks';
-
-export const SamplePrevArrow: React.FC = (props: any) => {
- const [isHover, setIsHover] = useState(false);
-
- const { className, style, onClick } = props;
- const { isDarkTheme } = useAppSelector((state) => state.theme);
-
- return (
- <>
-
- >
- );
-};
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import React, { useState } from 'react';
+import {
+ ReactComponent as PrevIcon,
+} from '../../../../static/icons/arrow-left_icon.svg';
+import { useAppSelector } from '../../../../store/hooks';
+
+export const SamplePrevArrow: React.FC = (props: any) => {
+ const [isHover, setIsHover] = useState(false);
+
+ const { className, style, onClick } = props;
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src/modules/HomePage/componets/MainSlider/index.ts b/src/modules/HomePage/componets/MainSlider/index.ts
index c00b339..df0fb29 100644
--- a/src/modules/HomePage/componets/MainSlider/index.ts
+++ b/src/modules/HomePage/componets/MainSlider/index.ts
@@ -1 +1 @@
-export * from './MainSlider';
+export * from './MainSlider';
diff --git a/src/modules/HomePage/componets/MainSlider/slick-theme.scss b/src/modules/HomePage/componets/MainSlider/slick-theme.scss
index b9b6baa..28f5c05 100644
--- a/src/modules/HomePage/componets/MainSlider/slick-theme.scss
+++ b/src/modules/HomePage/componets/MainSlider/slick-theme.scss
@@ -1,126 +1,126 @@
-@charset "UTF-8";
-@import '../../../../styles/utils/mixins/_mixin-media.scss';
-@import '../../../../styles/utils/variables/colors';
-
-/* Arrows */
-@include onMobile {
- .slick-prev,
- .slick-next,
- .slick-arrow {
- display: none;
- visibility: hidden;
- }
-}
-
-@include onTablet {
- .slick-arrow {
- position: absolute;
- height: 400px;
- width: 32px;
- cursor: pointer;
- border: 1px solid $color__secondary;
- border-radius: 48px;
- background-color: $color__white;
- top: 46.5% ;
- -webkit-transform: translate(0, -50%);
- -ms-transform: translate(0, -50%);
- transform: translate(0, -50%);
- padding: 0;
-
- &:hover {
- border-color: $color__primary;
- }
- }
-
- .slick-prev {
- left: -49px;
- }
-
- .slick-next {
- right: -49px;
- }
-}
-
-@include onDesktop {
- .slick-arrow {
- position: absolute;
- height: 400px;
- width: 32px;
- cursor: pointer;
- border: 1px solid $color__secondary;
- border-radius: 48px;
- background-color: $color__white;
- top: 46.5% ;
- -webkit-transform: translate(0, -50%);
- -ms-transform: translate(0, -50%);
- transform: translate(0, -50%);
- padding: 0;
-
- &:hover {
- border-color: $color__primary;
- }
- }
-
- .slick-prev {
- left: -49px;
- }
-
- .slick-next {
- right: -49px;
- }
-}
-
-/* Dots */
-.slick-dots {
- margin-top: 8px;
- list-style: none;
- text-align: center;
- width: 100%;
-
- li {
- position: relative;
- display: inline-block;
-
- button {
- border: 0;
- background: transparent;
- width: 24px;
- height: 24px;
- margin: 0 4px;
- padding: 0;
- cursor: pointer;
- color: transparent;
-
- &:before {
- display: block;
- position: absolute;
- content: '';
- width: 14px;
- height: 4px;
- margin-top: 7px;
- margin-left: 4px;
- background-color: $color__elements;
- opacity: 1;
- }
- }
-
- &.slick-active button:before {
- background-color: $color__primary;
- opacity: 1;
- }
- }
-
- &__dark {
- li {
- button {
- &:before {
- background-color: #3b3e4a;
- }
- }
-
- &.slick-active button:before {
- background-color: #f1f2f9;
- }
- }
- }
-}
+@charset "UTF-8";
+@import '../../../../styles/utils/mixins/_mixin-media.scss';
+@import '../../../../styles/utils/variables/colors';
+
+/* Arrows */
+@include onMobile {
+ .slick-prev,
+ .slick-next,
+ .slick-arrow {
+ display: none;
+ visibility: hidden;
+ }
+}
+
+@include onTablet {
+ .slick-arrow {
+ position: absolute;
+ height: 400px;
+ width: 32px;
+ cursor: pointer;
+ border: 1px solid $color__secondary;
+ border-radius: 48px;
+ background-color: $color__white;
+ top: 46.5% ;
+ -webkit-transform: translate(0, -50%);
+ -ms-transform: translate(0, -50%);
+ transform: translate(0, -50%);
+ padding: 0;
+
+ &:hover {
+ border-color: $color__primary;
+ }
+ }
+
+ .slick-prev {
+ left: -49px;
+ }
+
+ .slick-next {
+ right: -49px;
+ }
+}
+
+@include onDesktop {
+ .slick-arrow {
+ position: absolute;
+ height: 400px;
+ width: 32px;
+ cursor: pointer;
+ border: 1px solid $color__secondary;
+ border-radius: 48px;
+ background-color: $color__white;
+ top: 46.5% ;
+ -webkit-transform: translate(0, -50%);
+ -ms-transform: translate(0, -50%);
+ transform: translate(0, -50%);
+ padding: 0;
+
+ &:hover {
+ border-color: $color__primary;
+ }
+ }
+
+ .slick-prev {
+ left: -49px;
+ }
+
+ .slick-next {
+ right: -49px;
+ }
+}
+
+/* Dots */
+.slick-dots {
+ margin-top: 8px;
+ list-style: none;
+ text-align: center;
+ width: 100%;
+
+ li {
+ position: relative;
+ display: inline-block;
+
+ button {
+ border: 0;
+ background: transparent;
+ width: 24px;
+ height: 24px;
+ margin: 0 4px;
+ padding: 0;
+ cursor: pointer;
+ color: transparent;
+
+ &:before {
+ display: block;
+ position: absolute;
+ content: '';
+ width: 14px;
+ height: 4px;
+ margin-top: 7px;
+ margin-left: 4px;
+ background-color: $color__elements;
+ opacity: 1;
+ }
+ }
+
+ &.slick-active button:before {
+ background-color: $color__primary;
+ opacity: 1;
+ }
+ }
+
+ &__dark {
+ li {
+ button {
+ &:before {
+ background-color: #3b3e4a;
+ }
+ }
+
+ &.slick-active button:before {
+ background-color: #f1f2f9;
+ }
+ }
+ }
+}
diff --git a/src/modules/HomePage/componets/MainSlider/slick.scss b/src/modules/HomePage/componets/MainSlider/slick.scss
index c229b98..8e6a0bb 100644
--- a/src/modules/HomePage/componets/MainSlider/slick.scss
+++ b/src/modules/HomePage/componets/MainSlider/slick.scss
@@ -1,100 +1,100 @@
-/* Slider */
-
-.slick-slider {
- position: relative;
- display: block;
- box-sizing: border-box;
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- -ms-touch-action: pan-y;
- touch-action: pan-y;
- -webkit-tap-highlight-color: transparent;
-}
-.slick-list {
- position: relative;
- overflow: hidden;
- display: block;
- margin: 0;
- padding: 0;
-
- &:focus {
- outline: none;
- }
-
- &.dragging {
- cursor: pointer;
- cursor: hand;
- }
-}
-.slick-slider .slick-track,
-.slick-slider .slick-list {
- -webkit-transform: translate3d(0, 0, 0);
- -moz-transform: translate3d(0, 0, 0);
- -ms-transform: translate3d(0, 0, 0);
- -o-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
-}
-
-.slick-track {
- position: relative;
- left: 0;
- top: 0;
- display: block;
- margin-left: auto;
- margin-right: auto;
-
- &:before,
- &:after {
- content: "";
- display: table;
- }
-
- &:after {
- clear: both;
- }
-
- .slick-loading & {
- visibility: hidden;
- }
-}
-.slick-slide {
- float: left;
- height: 100%;
- min-height: 1px;
- [dir="rtl"] & {
- float: right;
- }
- img {
- display: block;
- }
- &.slick-loading img {
- display: none;
- }
-
- display: none;
-
- &.dragging img {
- pointer-events: none;
- }
-
- .slick-initialized & {
- display: block;
- }
-
- .slick-loading & {
- visibility: hidden;
- }
-
- .slick-vertical & {
- display: block;
- height: auto;
- border: 1px solid transparent;
- }
-}
-.slick-arrow.slick-hidden {
- display: none;
-}
+/* Slider */
+
+.slick-slider {
+ position: relative;
+ display: block;
+ box-sizing: border-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -ms-touch-action: pan-y;
+ touch-action: pan-y;
+ -webkit-tap-highlight-color: transparent;
+}
+.slick-list {
+ position: relative;
+ overflow: hidden;
+ display: block;
+ margin: 0;
+ padding: 0;
+
+ &:focus {
+ outline: none;
+ }
+
+ &.dragging {
+ cursor: pointer;
+ cursor: hand;
+ }
+}
+.slick-slider .slick-track,
+.slick-slider .slick-list {
+ -webkit-transform: translate3d(0, 0, 0);
+ -moz-transform: translate3d(0, 0, 0);
+ -ms-transform: translate3d(0, 0, 0);
+ -o-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+
+.slick-track {
+ position: relative;
+ left: 0;
+ top: 0;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+
+ &:before,
+ &:after {
+ content: "";
+ display: table;
+ }
+
+ &:after {
+ clear: both;
+ }
+
+ .slick-loading & {
+ visibility: hidden;
+ }
+}
+.slick-slide {
+ float: left;
+ height: 100%;
+ min-height: 1px;
+ [dir="rtl"] & {
+ float: right;
+ }
+ img {
+ display: block;
+ }
+ &.slick-loading img {
+ display: none;
+ }
+
+ display: none;
+
+ &.dragging img {
+ pointer-events: none;
+ }
+
+ .slick-initialized & {
+ display: block;
+ }
+
+ .slick-loading & {
+ visibility: hidden;
+ }
+
+ .slick-vertical & {
+ display: block;
+ height: auto;
+ border: 1px solid transparent;
+ }
+}
+.slick-arrow.slick-hidden {
+ display: none;
+}
diff --git a/src/modules/HomePage/componets/MainTitle/MainTitle.module.scss b/src/modules/HomePage/componets/MainTitle/MainTitle.module.scss
index 32650f4..dda2ac1 100644
--- a/src/modules/HomePage/componets/MainTitle/MainTitle.module.scss
+++ b/src/modules/HomePage/componets/MainTitle/MainTitle.module.scss
@@ -1,7 +1,7 @@
-@import '../../../../styles/utils/mixins/mixin-media';
-
-.mainTitle {
- width: 0px;
- height: 0px;
- overflow: hidden;
-}
+@import '../../../../styles/utils/mixins/mixin-media';
+
+.mainTitle {
+ width: 0px;
+ height: 0px;
+ overflow: hidden;
+}
diff --git a/src/modules/HomePage/componets/MainTitle/MainTitle.tsx b/src/modules/HomePage/componets/MainTitle/MainTitle.tsx
index 6306b65..f7612fc 100644
--- a/src/modules/HomePage/componets/MainTitle/MainTitle.tsx
+++ b/src/modules/HomePage/componets/MainTitle/MainTitle.tsx
@@ -1,6 +1,6 @@
-import React from 'react';
-import styles from './MainTitle.module.scss';
-
-export const MainTitle: React.FC = () => (
- Product Catalog
-);
+import React from 'react';
+import styles from './MainTitle.module.scss';
+
+export const MainTitle: React.FC = () => (
+ Product Catalog
+);
diff --git a/src/modules/HomePage/componets/MainTitle/index.ts b/src/modules/HomePage/componets/MainTitle/index.ts
index 854ba7c..d762f96 100644
--- a/src/modules/HomePage/componets/MainTitle/index.ts
+++ b/src/modules/HomePage/componets/MainTitle/index.ts
@@ -1 +1 @@
-export * from './MainTitle';
+export * from './MainTitle';
diff --git a/src/modules/HomePage/componets/ShopByCategory/ShopByCategory.module.scss b/src/modules/HomePage/componets/ShopByCategory/ShopByCategory.module.scss
index 95af21b..80f807e 100644
--- a/src/modules/HomePage/componets/ShopByCategory/ShopByCategory.module.scss
+++ b/src/modules/HomePage/componets/ShopByCategory/ShopByCategory.module.scss
@@ -1,104 +1,104 @@
-@import '../../../../styles/blocks/grid';
-@import '../../../../styles/utils/variables/colors';
-@import '../../../../styles/utils/mixins/mixin-media';
-@import '../../../../styles/utils/mixins/mixin-typography';
-
-.shopByCategory {
- &__title {
- margin-bottom: 1.5rem;
- @include h2-typography;
- }
-
- &__titleDark {
- @include typography-dark;
- }
-
- &__container {
- @extend .grid;
- }
-
- &__article {
- margin-bottom: 32px;
- grid-column: span 4;
- color: $color__primary;
- @include onTablet {
- margin-bottom: 0;
- }
-
- @include onDesktop {
- grid-column: span 8;
- }
- }
-
- &__subtitle {
- @include h4-typography;
- }
-
- &__subtitleDark {
- @include typography-dark;
- }
-
- &__content {
- color: $color__secondary;
- @include bodyText-typography;
- }
-
- &__contentDark {
- color: $color__dark-theme__secondary;
- }
-
- &__imgContainer {
- position: relative;
- height: 0;
- padding-bottom: 100%;
- border-radius: 8px;
- margin-bottom: 1.5rem;
- overflow: hidden;
- }
-
- &__imgPhones {
- background-color: #6D6474;
- }
-
- &__imgDark {
- border-radius: 0px;
- }
-
- &__imgTablets {
- background-color: #D3D3D3;
- }
-
- &__imgAccessories {
- background-color: #D53C51;
- }
-
- &__picture {
- position: absolute;
- display: block;
- width: 100%;
- height: 100%;
- left: 10%;
- top: 10%;
- transition: transform 0.3s ease;
- }
-
- &__pictureTablet {
- left: 7%;
- top: 5%;
- }
-
- &__pictureAccessories {
- left: 3%;
- top: 0%;
- }
-
- &__imgContainer:hover &__picture {
- transform: scale(1.2);
- }
-}
-
-.shopByCategoryDark {
- background-color: $color__dark-theme__black;
-}
-
-
+@import '../../../../styles/blocks/grid';
+@import '../../../../styles/utils/variables/colors';
+@import '../../../../styles/utils/mixins/mixin-media';
+@import '../../../../styles/utils/mixins/mixin-typography';
+
+.shopByCategory {
+ &__title {
+ margin-bottom: 1.5rem;
+ @include h2-typography;
+ }
+
+ &__titleDark {
+ @include typography-dark;
+ }
+
+ &__container {
+ @extend .grid;
+ }
+
+ &__article {
+ margin-bottom: 32px;
+ grid-column: span 4;
+ color: $color__primary;
+ @include onTablet {
+ margin-bottom: 0;
+ }
+
+ @include onDesktop {
+ grid-column: span 8;
+ }
+ }
+
+ &__subtitle {
+ @include h4-typography;
+ }
+
+ &__subtitleDark {
+ @include typography-dark;
+ }
+
+ &__content {
+ color: $color__secondary;
+ @include bodyText-typography;
+ }
+
+ &__contentDark {
+ color: $color__dark-theme__secondary;
+ }
+
+ &__imgContainer {
+ position: relative;
+ height: 0;
+ padding-bottom: 100%;
+ border-radius: 8px;
+ margin-bottom: 1.5rem;
+ overflow: hidden;
+ }
+
+ &__imgPhones {
+ background-color: #6D6474;
+ }
+
+ &__imgDark {
+ border-radius: 0px;
+ }
+
+ &__imgTablets {
+ background-color: #D3D3D3;
+ }
+
+ &__imgAccessories {
+ background-color: #D53C51;
+ }
+
+ &__picture {
+ position: absolute;
+ display: block;
+ width: 100%;
+ height: 100%;
+ left: 10%;
+ top: 10%;
+ transition: transform 0.3s ease;
+ }
+
+ &__pictureTablet {
+ left: 7%;
+ top: 5%;
+ }
+
+ &__pictureAccessories {
+ left: 3%;
+ top: 0%;
+ }
+
+ &__imgContainer:hover &__picture {
+ transform: scale(1.2);
+ }
+}
+
+.shopByCategoryDark {
+ background-color: $color__dark-theme__black;
+}
+
+
diff --git a/src/modules/HomePage/componets/ShopByCategory/index.ts b/src/modules/HomePage/componets/ShopByCategory/index.ts
index 8081526..2996221 100644
--- a/src/modules/HomePage/componets/ShopByCategory/index.ts
+++ b/src/modules/HomePage/componets/ShopByCategory/index.ts
@@ -1 +1 @@
-export * from './ShopByCategory';
+export * from './ShopByCategory';
diff --git a/src/modules/PhonesPage/PhonesPage.module.scss b/src/modules/PhonesPage/PhonesPage.module.scss
index e69de29..ac74948 100644
--- a/src/modules/PhonesPage/PhonesPage.module.scss
+++ b/src/modules/PhonesPage/PhonesPage.module.scss
@@ -0,0 +1,88 @@
+@import '../../styles/utils/variables/colors';
+@import '../../styles/blocks/grid';
+
+.productsPage {
+ // @include grid;
+
+ &__DARK {
+ background-color: $color__dark-theme__black;
+ }
+
+ &__breadCrumbs {
+ margin-bottom: 24px;
+ margin-top: 25px;
+ }
+
+ &__title {
+ margin-bottom: 8px;
+ color: $color__primary;
+ font-size: 32px;
+ font-style: normal;
+ font-weight: 800;
+ line-height: 41px;
+ letter-spacing: -0.32px;
+
+ &__DARK {
+ color: $color__dark-theme__white;
+ }
+ }
+
+ &__errorButton {
+ display: flex;
+ height: 40px;
+ justify-content: center;
+ align-items: center;
+ flex: 1 0 0;
+
+ border-radius: 8px;
+ border: none;
+ background: $color__accent;
+
+ color: $color__white;
+ text-align: center;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: 21px;
+
+ &:hover {
+ box-shadow: 0px 3px 13px 0px rgba(23, 32, 49, 0.4);
+ }
+
+ &__DARK {
+ background: #905bff;
+ border-radius: 0px;
+ color: $color__dark-theme__white;
+ border: none;
+
+ &:hover {
+ background: #a378ff;
+ }
+ }
+ }
+
+ &__counter {
+ margin-bottom: 32px;
+ color: #89939a;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 21px;
+
+ &__DARK {
+ color: $color__dark-theme__secondary;
+ }
+ }
+
+ &__filter {
+ display: flex;
+ margin-bottom: 24px;
+ }
+
+ // &__phonesList {
+ // }
+
+ &__phoneItem {
+ margin-bottom: 40px;
+ }
+}
diff --git a/src/modules/PhonesPage/PhonesPage.tsx b/src/modules/PhonesPage/PhonesPage.tsx
index d78021c..05476f1 100644
--- a/src/modules/PhonesPage/PhonesPage.tsx
+++ b/src/modules/PhonesPage/PhonesPage.tsx
@@ -1,43 +1,185 @@
-import React, { useEffect, useState } from 'react';
-
-// import styles from './PhonesPage.module.scss';
-
-import { Breadcrumbs } from '../shared/Breadcrumbs';
-import { ProductList } from '../shared/ProductList';
-import { getProductsWithSearchParams } from '../../api/service';
-import { Loader } from '../shared/Loader';
-import { Pagination } from '../shared/Pagination';
-import { Filtration } from '../shared/Filtration';
-import { EndPoints } from '../../types/Enums';
-import { Product } from '../../types/Product';
-
-export const PhonesPage: React.FC = () => {
- const [phones, setPhones] = useState([]);
- const [isLoading, setIsLoading] = useState(false);
-
- useEffect(() => {
- setIsLoading(true);
- getProductsWithSearchParams(EndPoints.Phones)
- .then(setPhones)
- .finally(() => setIsLoading(false));
- }, []);
-
- return (
- <>
-
-
- Mobile phones
- N models
-
-
-
- {isLoading ? (
-
- ) : (
-
- )}
-
-
- >
- );
-};
+import React, { useEffect, useState } from 'react';
+import { useSearchParams } from 'react-router-dom';
+import classNames from 'classnames';
+
+import styles from './PhonesPage.module.scss';
+
+import { Breadcrumbs } from '../shared/Breadcrumbs';
+import { ProductList } from '../shared/ProductList';
+import { getProductsWithSearchParams } from '../../api/service';
+import { Loader } from '../shared/Loader';
+import { Pagination } from '../shared/Pagination';
+import { Filtration } from '../shared/Filtration';
+import { EndPoints, ProductsAmount } from '../../types/Enums';
+import { Product, QueryParams } from '../../types/Product';
+import { SortBy } from '../../types/SortBy';
+import { useAppSelector } from '../../store/hooks';
+import { getSearchWith } from '../../utils/getSearchWith';
+
+type Props = {
+ title: string;
+ loadData: (
+ EndPoint: EndPoints,
+ params?: QueryParams
+ ) => Promise;
+ loadAmount: () => Promise;
+};
+
+export const ProductsPage: React.FC = ({
+ title,
+ loadData,
+ loadAmount,
+}) => {
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ const [products, setProducts] = useState([]);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState('');
+ const [totalAmount, setTotalAmount] = useState(0);
+ const [searchParams] = useSearchParams();
+
+ const defaultPerPage = 'all';
+ const defaultSortBy = SortBy.Newest;
+ const defaultPage = 1;
+
+ const sort = searchParams.get('sort');
+ const page = searchParams.get('page');
+ const perPage = searchParams.get('perPage');
+
+ useEffect(() => {
+ if (searchParams.toString() === '') {
+ getSearchWith(searchParams,
+ { sort: defaultSortBy, page: defaultPage, perPage: defaultPerPage });
+ }
+ });
+
+ const perPageString: string = perPage || defaultPerPage;
+ const currentPageNumber: number = page !== null
+ ? parseInt(page, 10)
+ : defaultPage;
+ const sortByEnum: SortBy = sort ? (sort as SortBy) : defaultSortBy;
+
+ useEffect(() => {
+ loadAmount().then((amount) => setTotalAmount(amount.phones));
+ }, [loadAmount]);
+
+ const getTotalPages = () => {
+ if (perPageString === 'All') {
+ return 1;
+ }
+
+ return totalAmount / Number(perPage);
+ };
+
+ const totalPages = getTotalPages();
+
+ const showPagination = () => {
+ if (perPage === 'All') {
+ return false;
+ }
+
+ if (totalAmount < Number(perPage)) {
+ return false;
+ }
+
+ return (
+
+ );
+ };
+
+ useEffect(() => {
+ setIsLoading(true);
+ getProductsWithSearchParams(EndPoints.Phones)
+ .then(setProducts)
+ .finally(() => setIsLoading(false));
+ }, [sortByEnum, perPageString, currentPageNumber, error, loadData]);
+
+ // useEffect(() => {
+ // setIsLoading(true);
+ // loadData(
+ // perPageString,
+ // currentPageNumber,
+ // sortByEnum,
+ // )
+ // .then(setProducts)
+ // .catch(setError)
+ // .finally(() => setIsLoading(false));
+ // }, [sortByEnum, perPageString, currentPageNumber, error, loadData]);
+
+ return (
+
+
+
+
+
+
+ {title}
+
+
+ {isLoading && (
+
+ )}
+
+ {!isLoading && error && (
+ <>
+
+ {error}
+
+
+
+ >
+ )}
+
+ {!isLoading && !error && (
+ <>
+ {totalAmount
+ ? (
+
+ {`${totalAmount} modeles`}
+
+ ) : (
+
+ {`There are no ${title.toLowerCase()} yet`}
+
+ )}
+
+
+
+
+
+
+
+ {showPagination()}
+ >
+ )}
+
+ );
+};
diff --git a/src/modules/ProductDetailsPage/ProductDetailsPage.tsx b/src/modules/ProductDetailsPage/ProductDetailsPage.tsx
index c9766cf..af39797 100644
--- a/src/modules/ProductDetailsPage/ProductDetailsPage.tsx
+++ b/src/modules/ProductDetailsPage/ProductDetailsPage.tsx
@@ -8,21 +8,23 @@ import styles from './ProductDetailsPage.module.scss';
import { Breadcrumbs } from '../shared/Breadcrumbs';
import { BackButton } from '../shared/BackButton';
// import { ProductDetailsSlider } from './components/ProductDetailsSlider';
+import { EndPoints } from '../../types/Enums';
import { ProductAbout }
from './components/ProductDetailsSlider/ProductAbout/ProductAbout';
import { ProductTechspec }
from './components/ProductDetailsSlider/ProductTechspec/ProductTechspec';
-import { EndPoints } from '../../types/Enums';
import { Detail } from '../../types/Product';
import { useAppSelector } from '../../store/hooks';
// import { ProductSlider } from '../shared/ProductSlider';
type Props = {
loadData: (endPoint: EndPoints, itemId: string) => Promise,
+ endPoint: EndPoints
};
export const ProductDetailsPage: React.FC = ({
loadData,
+ endPoint,
}) => {
const { itemId } = useParams();
const [itemDetails, setItemDetails] = useState();
@@ -30,10 +32,10 @@ export const ProductDetailsPage: React.FC = ({
useEffect(() => {
if (itemId) {
- loadData(EndPoints.Phones, itemId)
+ loadData(endPoint, itemId)
.then(setItemDetails);
}
- }, [loadData, itemId]);
+ }, [loadData, itemId, endPoint]);
return (
= ({
{/*
-
- */}
+
+ */}
{itemDetails.current.description && (
{
+ return (
+ <>
+
+ >
+ );
+};
+
+export const PrevArrow: React.FC = () => {
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src/modules/ProductDetailsPage/components/ProductDetailsSlider/BorderColorHandler.ts b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/BorderColorHandler.ts
new file mode 100644
index 0000000..f4f67cf
--- /dev/null
+++ b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/BorderColorHandler.ts
@@ -0,0 +1,30 @@
+import styles from './ProductDetailsSlider.module.scss';
+
+export const getBorderColor = (
+ i: number, currentSlide: number, isDarkTheme: boolean,
+) => {
+ let borderColor;
+
+ switch (true) {
+ case currentSlide === i && isDarkTheme:
+ borderColor = styles['dots-border-dark-cur'];
+ break;
+
+ case currentSlide !== i && isDarkTheme:
+ borderColor = styles['dots-border-dark'];
+ break;
+
+ case currentSlide === i && !isDarkTheme:
+ borderColor = styles['dots-border-light-cur'];
+ break;
+
+ case currentSlide !== i && !isDarkTheme:
+ borderColor = styles['dots-border-light'];
+ break;
+
+ default:
+ break;
+ }
+
+ return borderColor;
+};
diff --git a/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.module.scss b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.module.scss
index e69de29..2bf1073 100644
--- a/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.module.scss
+++ b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.module.scss
@@ -0,0 +1,191 @@
+@import '../../../../styles/utils/mixins/mixin-media';
+
+.slick-prev-phone,
+.slick-next-phone {
+ display: none;
+ visibility: hidden;
+}
+
+#phoneImagesSlider {
+ .slick-track {
+ display: flex;
+ height: 464px !important;
+ }
+}
+
+.phonePhoto {
+ @include onMobile {
+ width: 288px;
+ height: 288px;
+ object-fit: contain;
+ margin-inline: auto;
+ }
+
+ @include onTablet {
+ width: 288px;
+ height: 288px;
+ object-fit: contain;
+ }
+
+ @include onDesktop {
+ width: 464px;
+ height: 464px;
+ object-fit: contain;
+ }
+};
+
+.slick-dots,
+.slick-thumb {
+ cursor: pointer;
+ width: auto !important;
+
+ @include onMobile {
+ height: 40px;
+ width: 51px;
+ object-fit: contain;
+ padding-block: 4px;
+ }
+
+ @include onTablet {
+ height: 28px;
+ width: 28px;
+ object-fit: contain;
+ padding-block: 4px;
+ }
+
+ @include onDesktop {
+ height: 67px;
+ width: 67px;
+ object-fit: contain;
+ padding: 4px;
+ }
+}
+
+#phone-photo {
+ width: auto !important;
+ height: 464px !important;
+ img {
+ width: auto !important;
+ }
+}
+
+.vertical-dots {
+ ul {
+ display: flex !important;
+ flex-direction: column;
+ margin-right: 16px;
+ width: auto !important;
+ margin-top: 0 !important;
+
+ @include onMobile {
+ flex-direction: row;
+ margin-right: 0px;
+ justify-content: center;
+ margin-top: 16px !important;
+ }
+
+ @include onTablet {
+ :last-child {
+ margin-bottom: 0px;
+ }
+ }
+
+ @include onDesktop {
+ :last-child {
+ margin-bottom: 0px;
+ }
+ }
+
+ li {
+ width: 79px;
+ height: 79px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ @include onTablet {
+ width: 34px;
+ height: 34px;
+ }
+
+ @include onDesktop {
+ width: 79px;
+ height: 79px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ @include onMobile {
+ width: 48px;
+ height: 48px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+ }
+ }
+
+ li {
+
+ @include onMobile {
+ width: 51px !important;
+ margin-right: 8px;
+ }
+
+ @include onTablet {
+ margin-bottom: 8px;
+ }
+
+ @include onDesktop {
+ margin-bottom: 16px;
+ }
+ }
+
+ @include onTablet {
+ display: flex;
+ flex-direction: row-reverse;
+ margin-right: 16px;
+ cursor: pointer;
+ }
+
+ @include onDesktop {
+ display: flex;
+ flex-direction: row-reverse;
+ cursor: pointer;
+ margin-right: 16px;
+ }
+}
+
+.dots-container {
+ display: flex;
+ flex-direction: column;
+}
+
+.dots-border-light-cur {
+ border: 1px solid #0F0F11;
+ border-radius: 4px;
+}
+
+.dots-border-light {
+ border: 1px solid #E2E6E9;
+ border-radius: 4px;
+}
+
+.dots-border-dark {
+ border: 1px solid #3b3e4a;
+ border-radius: 4px;
+}
+
+.dots-border-dark-cur {
+ border: 1px solid #f1f2f9;
+ border-radius: 4px;
+}
diff --git a/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.tsx b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.tsx
index b304713..a482af1 100644
--- a/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.tsx
+++ b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/ProductDetailsSlider.tsx
@@ -1,7 +1,105 @@
-import React from 'react';
+/* eslint-disable jsx-a11y/anchor-is-valid */
+import React, { useState } from 'react';
+import Slider from 'react-slick';
-// import styles from './ProductDetailsSlider.module.scss';
+import styles from './ProductDetailsSlider.module.scss';
+import { NextArrow, PrevArrow } from './Arrows';
+import { useAppSelector } from '../../../../store/hooks';
+import { getBorderColor } from './BorderColorHandler';
-export const ProductDetailsSlider: React.FC = () => {
- return Product Detail Slider
;
+type Props = {
+ images: string[] | undefined;
+};
+
+export const ProductDetailsSlider: React.FC = ({ images }) => {
+ const [currentSlide, setCurrentSlide] = useState(0);
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+
+ const settings = {
+ customPaging: (i: number) => {
+ return (
+
+ setCurrentSlide(i)}
+ onKeyDown={() => setCurrentSlide(i)}
+ role="presentation"
+ />
+
+ );
+ },
+ dots: true,
+ infinite: true,
+ speed: 500,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ nextArrow: (
+
+ ),
+ prevArrow: (
+
+ ),
+ vertical: true,
+ verticalSwiping: true,
+ responsive: [
+ {
+ breakpoint: 320,
+ settings: {
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ vertical: false,
+ verticalSwiping: false,
+ },
+ },
+ {
+ breakpoint: 640,
+ settings: {
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ vertical: false,
+ verticalSwiping: false,
+ },
+ },
+ {
+ breakpoint: 1200,
+ settings: {
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ vertical: true,
+ verticalSwiping: true,
+ },
+ },
+ ],
+ };
+
+ return (
+
+
+ {images?.map(image => (
+
+
+
+
+ ))}
+
+
+ );
};
diff --git a/src/modules/ProductDetailsPage/components/ProductDetailsSlider/index.ts b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/index.ts
index a393ea6..e800eaa 100644
--- a/src/modules/ProductDetailsPage/components/ProductDetailsSlider/index.ts
+++ b/src/modules/ProductDetailsPage/components/ProductDetailsSlider/index.ts
@@ -1 +1 @@
-export * from './ProductDetailsSlider';
+export * from './ProductDetailsSlider';
diff --git a/src/modules/ProductDetailsPage/index.ts b/src/modules/ProductDetailsPage/index.ts
index 6615089..db22256 100644
--- a/src/modules/ProductDetailsPage/index.ts
+++ b/src/modules/ProductDetailsPage/index.ts
@@ -1 +1 @@
-export * from './ProductDetailsPage';
+export * from './ProductDetailsPage';
diff --git a/src/modules/TabletsPage/TabletsPage.tsx b/src/modules/TabletsPage/TabletsPage.tsx
index d589a30..65858a9 100644
--- a/src/modules/TabletsPage/TabletsPage.tsx
+++ b/src/modules/TabletsPage/TabletsPage.tsx
@@ -1,7 +1,7 @@
-import './TabletsPage.module.scss';
-
-import React from 'react';
-
-export const TabletsPage: React.FC = () => {
- return Tablets Page
;
-};
+import './TabletsPage.module.scss';
+
+import React from 'react';
+
+export const TabletsPage: React.FC = () => {
+ return Tablets Page
;
+};
diff --git a/src/modules/TabletsPage/index.ts b/src/modules/TabletsPage/index.ts
index 6988826..33c7713 100644
--- a/src/modules/TabletsPage/index.ts
+++ b/src/modules/TabletsPage/index.ts
@@ -1 +1 @@
-export * from './TabletsPage';
+export * from './TabletsPage';
diff --git a/src/modules/shared/AddToCart/index.ts b/src/modules/shared/AddToCart/index.ts
index ca621b6..2baad75 100644
--- a/src/modules/shared/AddToCart/index.ts
+++ b/src/modules/shared/AddToCart/index.ts
@@ -1 +1 @@
-export * from './AddToCart';
+export * from './AddToCart';
diff --git a/src/modules/shared/AddToFavourites/index.ts b/src/modules/shared/AddToFavourites/index.ts
index 96d230a..36e379f 100644
--- a/src/modules/shared/AddToFavourites/index.ts
+++ b/src/modules/shared/AddToFavourites/index.ts
@@ -1 +1 @@
-export * from './AddToFavourites';
+export * from './AddToFavourites';
diff --git a/src/modules/shared/BackButton/index.ts b/src/modules/shared/BackButton/index.ts
index b68e24e..a51d86d 100644
--- a/src/modules/shared/BackButton/index.ts
+++ b/src/modules/shared/BackButton/index.ts
@@ -1 +1 @@
-export * from './BackButton';
+export * from './BackButton';
diff --git a/src/modules/shared/Breadcrumbs/Breadcrumbs.module.scss b/src/modules/shared/Breadcrumbs/Breadcrumbs.module.scss
index 67ca29d..e226bd8 100644
--- a/src/modules/shared/Breadcrumbs/Breadcrumbs.module.scss
+++ b/src/modules/shared/Breadcrumbs/Breadcrumbs.module.scss
@@ -1,13 +1,34 @@
-@import '../../../styles/utils/mixins/mixin-media';
+@import '../../../styles/utils/variables/colors';
-.breadcrumbs {
- grid-column: span 4;
+.breadcrumbContainer {
+ display: flex;
+ gap: 8px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.link {
+ display: flex;
+ gap: 8px;
+ align-items: flex-end;
+}
+
+.content {
+ color: $color__secondary;
+ font-size: 12px;
+ font-weight: 600;
- @include onTablet {
- grid-column: span 12;
+ &__prev {
+ color: $color__primary;
}
- @include onDesktop {
- grid-column: span 24;
+ &__prev__DARK {
+ color: $color__dark-theme__white;
+ }
+
+ &__DARK {
+ color: $color__dark-theme__secondary;
}
}
+
diff --git a/src/modules/shared/Breadcrumbs/Breadcrumbs.tsx b/src/modules/shared/Breadcrumbs/Breadcrumbs.tsx
index 9d93f71..6420bea 100644
--- a/src/modules/shared/Breadcrumbs/Breadcrumbs.tsx
+++ b/src/modules/shared/Breadcrumbs/Breadcrumbs.tsx
@@ -1,7 +1,61 @@
import React from 'react';
+import cn from 'classnames';
+import { Link, useLocation } from 'react-router-dom';
+import { useAppSelector } from '../../../store/hooks';
+import { ReactComponent as HomeIcon }
+ from '../../../static/icons/home_icon.svg';
+import { ReactComponent as ArrowRightIcon }
+ from '../../../static/icons/arrow-right_icon.svg';
import styles from './Breadcrumbs.module.scss';
export const Breadcrumbs: React.FC = () => {
- return Breadcrumbs
;
+ const location = useLocation();
+ const { pathname } = location;
+ const segments = pathname.split('/');
+ const currentPage = (segments[segments.length - 1]);
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ const { origin } = window.location;
+
+ let url = '';
+ const breadcrumbLinks = segments.map((segment) => {
+ url += `${segment}`;
+
+ return (
+
+
+ {segment === ''
+ ? (
+
+ )
+ : (
+
+
+
+ {segment.charAt(0).toUpperCase() + segment.slice(1)}
+
+
+ )}
+
+
+ );
+ });
+
+ return (
+
+ {breadcrumbLinks}
+
+ );
};
diff --git a/src/modules/shared/Breadcrumbs/index.ts b/src/modules/shared/Breadcrumbs/index.ts
index ce97754..1a699f6 100644
--- a/src/modules/shared/Breadcrumbs/index.ts
+++ b/src/modules/shared/Breadcrumbs/index.ts
@@ -1 +1 @@
-export * from './Breadcrumbs';
+export * from './Breadcrumbs';
diff --git a/src/modules/shared/BurgerMenu/index.ts b/src/modules/shared/BurgerMenu/index.ts
index cc518a4..0a9f211 100644
--- a/src/modules/shared/BurgerMenu/index.ts
+++ b/src/modules/shared/BurgerMenu/index.ts
@@ -1 +1 @@
-export * from './BurgerMenu';
+export * from './BurgerMenu';
diff --git a/src/modules/shared/EmptyCart/EmptyCart.module.scss b/src/modules/shared/EmptyCart/EmptyCart.module.scss
new file mode 100644
index 0000000..a3d940e
--- /dev/null
+++ b/src/modules/shared/EmptyCart/EmptyCart.module.scss
@@ -0,0 +1,130 @@
+@import '../../../styles/utils/mixins/mixin-media';
+@import '../../../styles/utils/mixins/mixin-typography';
+@import '../../../styles/utils/variables/colors';
+
+.container {
+ height: 420px;
+ overflow-y: hidden;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 10px;
+
+ @include onMobile {
+ gap: 5px;
+ }
+}
+
+.cart_icon {
+ height: 170px;
+
+ &_dark {
+ height: 170px;
+ filter: invert(89%);
+
+ @include onMobile {
+ height: 90px;
+ }
+ }
+
+ @include onMobile {
+ height: 90px;
+ }
+}
+
+.headline {
+ @include h2-typography;
+ text-align: center;
+
+ &_dark {
+ @include h2-typography;
+ color: $color__dark-theme__white;
+
+ @include onMobile {
+ font-size: 24px;
+ }
+ }
+
+ @include onMobile {
+ font-size: 24px;
+ }
+}
+
+
+.subtitle {
+ text-align: center;
+ color: $color__secondary;
+ @include bodyText-typography;
+
+ &_dark {
+ @include bodyText-typography;
+ color: $color__dark-theme__white;
+ }
+}
+
+.button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 15px;
+ min-width: 130px;
+
+ border-radius: 8px;
+ border: none;
+ background: $color__accent;
+ margin-top: 12px;
+
+ color: $color__white;
+ @include buttons-typography;
+ text-decoration: none;
+
+ transition: scale 0.05s ease;
+
+ &:hover {
+ box-shadow: 0px 3px 13px 0px rgba(23, 32, 49, 0.4);
+ scale: 1.1;
+ }
+
+ &_dark {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 15px;
+ min-width: 130px;
+
+ border-radius: 0px;
+ border: none;
+ background: $color__dark-theme__accent;
+ margin-top: 12px;
+
+ color: $color__dark-theme__white;
+ @include buttons-typography;
+ text-decoration: none;
+
+ transition: scale 0.05s ease;
+
+ &:hover {
+ box-shadow: 0px 3px 13px 0px rgba(23, 32, 49, 0.4);
+ scale: 1.1;
+ background: #a378ff;
+ }
+
+ @include onMobile {
+ scale: 0.8;
+ &:hover {
+ scale: 0.9;
+ }
+ margin-top: 5px;
+ }
+ }
+
+ @include onMobile {
+ scale: 0.8;
+ &:hover {
+ scale: 0.9;
+ }
+ margin-top: 5px;
+ }
+}
+
diff --git a/src/modules/shared/EmptyCart/EmptyCart.tsx b/src/modules/shared/EmptyCart/EmptyCart.tsx
new file mode 100644
index 0000000..2f27b15
--- /dev/null
+++ b/src/modules/shared/EmptyCart/EmptyCart.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import cn from 'classnames';
+import { Link } from 'react-router-dom';
+import styles from './EmptyCart.module.scss';
+import { useAppSelector } from '../../../store/hooks';
+import cart_icon from '../../../static/icons/cart_icon.svg';
+
+export const EmptyCart: React.FC = () => {
+ const { isDarkTheme } = useAppSelector(state => state.theme);
+
+ return (
+
+
+
+ Your cart is empty
+
+
+ You can add an item to your cart by clicking Add to cart button
+
+
+ Explore the catalog
+
+
+ );
+};
diff --git a/src/modules/shared/EmptyCart/index.ts b/src/modules/shared/EmptyCart/index.ts
new file mode 100644
index 0000000..1ba3911
--- /dev/null
+++ b/src/modules/shared/EmptyCart/index.ts
@@ -0,0 +1 @@
+export * from './EmptyCart';
diff --git a/src/modules/shared/EmptyFavourites/EmptyFavourites.module.scss b/src/modules/shared/EmptyFavourites/EmptyFavourites.module.scss
new file mode 100644
index 0000000..0a34a0e
--- /dev/null
+++ b/src/modules/shared/EmptyFavourites/EmptyFavourites.module.scss
@@ -0,0 +1,130 @@
+@import '../../../styles/utils/mixins/mixin-media';
+@import '../../../styles/utils/mixins/mixin-typography';
+@import '../../../styles/utils/variables/colors';
+
+.container {
+ height: 420px;
+ overflow-y: hidden;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 10px;
+
+ @include onMobile {
+ gap: 5px;
+ }
+}
+
+.fav_icon {
+ height: 170px;
+
+ &_dark {
+ height: 170px;
+ filter: invert(89%);
+
+ @include onMobile {
+ height: 90px;
+ }
+ }
+
+ @include onMobile {
+ height: 90px;
+ }
+}
+
+.headline {
+ @include h2-typography;
+ text-align: center;
+
+ &_dark {
+ @include h2-typography;
+ color: $color__dark-theme__white;
+
+ @include onMobile {
+ font-size: 24px;
+ }
+ }
+
+ @include onMobile {
+ font-size: 24px;
+ }
+}
+
+
+.subtitle {
+ text-align: center;
+ color: $color__secondary;
+ @include bodyText-typography;
+
+ &_dark {
+ @include bodyText-typography;
+ color: $color__dark-theme__white;
+ }
+}
+
+.button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 15px;
+ min-width: 130px;
+
+ border-radius: 8px;
+ border: none;
+ background: $color__accent;
+ margin-top: 12px;
+
+ color: $color__white;
+ @include buttons-typography;
+ text-decoration: none;
+
+ transition: scale 0.05s ease;
+
+ &:hover {
+ box-shadow: 0px 3px 13px 0px rgba(23, 32, 49, 0.4);
+ scale: 1.1;
+ }
+
+ &_dark {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 15px;
+ min-width: 130px;
+
+ border-radius: 0px;
+ border: none;
+ background: $color__dark-theme__accent;
+ margin-top: 12px;
+
+ color: $color__dark-theme__white;
+ @include buttons-typography;
+ text-decoration: none;
+
+ transition: scale 0.05s ease;
+
+ &:hover {
+ box-shadow: 0px 3px 13px 0px rgba(23, 32, 49, 0.4);
+ scale: 1.1;
+ background: #a378ff;
+ }
+
+ @include onMobile {
+ scale: 0.8;
+ &:hover {
+ scale: 0.9;
+ }
+ margin-top: 5px;
+ }
+ }
+
+ @include onMobile {
+ scale: 0.8;
+ &:hover {
+ scale: 0.9;
+ }
+ margin-top: 5px;
+ }
+}
+
diff --git a/src/modules/shared/EmptyFavourites/EmptyFavourites.tsx b/src/modules/shared/EmptyFavourites/EmptyFavourites.tsx
new file mode 100644
index 0000000..1143de1
--- /dev/null
+++ b/src/modules/shared/EmptyFavourites/EmptyFavourites.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import cn from 'classnames';
+import { Link } from 'react-router-dom';
+import styles from './EmptyFavourites.module.scss';
+import { useAppSelector } from '../../../store/hooks';
+import fav_icon from '../../../static/icons/favourites_icon.svg';
+
+export const EmptyFavourites: React.FC = () => {
+ const { isDarkTheme } = useAppSelector(state => state.theme);
+
+ return (
+
+
+
+ No favourites yet!
+
+
+ You can add an item to your favourites by clicking heart icon
+
+
+ Bring me back
+
+
+ );
+};
diff --git a/src/modules/shared/EmptyFavourites/index.ts b/src/modules/shared/EmptyFavourites/index.ts
new file mode 100644
index 0000000..0bbd6b4
--- /dev/null
+++ b/src/modules/shared/EmptyFavourites/index.ts
@@ -0,0 +1 @@
+export * from './EmptyFavourites';
diff --git a/src/modules/shared/Filtration/Filtration.module.scss b/src/modules/shared/Filtration/Filtration.module.scss
index e69de29..8d2aaa4 100644
--- a/src/modules/shared/Filtration/Filtration.module.scss
+++ b/src/modules/shared/Filtration/Filtration.module.scss
@@ -0,0 +1,110 @@
+@import '../../../styles/utils/variables/colors';
+
+.filtration {
+ display: flex;
+
+ &__block {
+ display: flex;
+ flex-direction: column;
+
+ &:first-child {
+ margin-right: 16px;
+ }
+ }
+
+ &__label {
+ color: $color__secondary;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+ }
+
+
+ &__dropdown {
+ display: flex;
+ position: relative;
+ justify-content: space-between;
+ align-items: center;
+ color: $color__primary;
+ font-size: 14px;
+ font-weight: 700;
+ line-height: 21px;
+
+ width: 176px;
+ height: 40px;
+ flex-shrink: 0;
+ border-radius: 8px;
+ border: 1px solid $color__icons;
+ background-color: $color__white;
+ transition: border 0.3s ease;
+
+ &:hover {
+ border: 1px solid $color__secondary;
+ }
+
+ &__DARK {
+ background: $color__dark-theme__surface-2;
+ border-radius: 0px;
+ border: 1px solid $color__dark-theme__surface-2;
+ color: #F1F2F9;
+
+ &:hover {
+ border: 1px solid $color__dark-theme__icons;
+ }
+ }
+ }
+
+ &__list {
+ position: absolute;
+ width: 176px;
+ margin-top: 8px;
+ z-index: 1;
+ display: flex;
+ flex-direction: column;
+
+ border-radius: 8px;
+ border: 1px solid $color__elements;
+ box-shadow: 0px 2px 15px 0px rgba(0, 0, 0, 0.05);
+
+ &__DARK {
+ border-radius: 0px;
+ border: 1px solid $color__dark-theme__elements;
+ background-color: $color__dark-theme__black;
+ }
+ }
+
+ &__option {
+ color: $color__secondary;
+ font-size: 14px;
+ font-weight: 500;
+ line-height: 21px;
+ background-color: $color__white;
+ margin-left: 1px;
+ margin-right: 1px;
+ transition: border 0.3s ease, background-color 0.3s ease;
+
+ &:first-child {
+ margin-top: 8px;
+ }
+
+ &:last-child {
+ margin-bottom: 8px;
+ }
+
+ &:hover {
+ color: $color__primary;
+ background: $color__white;
+ }
+
+ &__DARK {
+ color: $color__dark-theme__secondary;
+ background-color: $color__dark-theme__black;
+
+ &:hover {
+ background-color: $color__dark-theme__surface-2;
+ color: $color__dark-theme__white;
+ }
+ }
+ }
+}
diff --git a/src/modules/shared/Filtration/Filtration.tsx b/src/modules/shared/Filtration/Filtration.tsx
index 1947c30..e346d0a 100644
--- a/src/modules/shared/Filtration/Filtration.tsx
+++ b/src/modules/shared/Filtration/Filtration.tsx
@@ -1,7 +1,141 @@
-import React from 'react';
-
-// import styles from './Filtration.module.scss';
-
-export const Filtration: React.FC = () => {
- return Filtration
;
-};
+import { useState } from 'react';
+import { Link, useSearchParams } from 'react-router-dom';
+import classNames from 'classnames';
+import { useAppSelector } from '../../../store/hooks';
+import styles from './Filtration.module.scss';
+import { SortBy } from '../../../types/SortBy';
+import { getSearchWith } from '../../../utils/getSearchWith';
+import {
+ ReactComponent as ArrowDown,
+} from '../../../static/buttons/Icons_ArrowDown.svg';
+
+const PER_PAGE = ['All', '4', '8', '16'];
+
+type Props = {
+ sort: SortBy;
+ perPage: string;
+};
+
+export const Filtration: React.FC = ({ sort, perPage }) => {
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ const [isSortOpen, setIsSortOpen] = useState(false);
+ const [isPerPageOpen, setIsPerPageOpen] = useState(false);
+ const [searchParams] = useSearchParams();
+
+ const getPerPageParams = (newPerPage: string) => {
+ if (perPage === 'All') {
+ const search = getSearchWith(searchParams, { perPage: 'all' });
+
+ return search;
+ }
+
+ const search = getSearchWith(searchParams, { perPage: newPerPage });
+
+ return search;
+ };
+
+ return (
+
+
+
+
+
+
+ {isSortOpen && (
+
+ {Object.entries(SortBy).map(([key, value]) => (
+
+ {key}
+
+ ))}
+
+ )}
+
+
+
+
+
+
+
+
+
+ {isPerPageOpen && (
+
+ {PER_PAGE.map(amount => (
+
+ {amount}
+
+ ))}
+
+ )}
+
+
+
+ );
+};
diff --git a/src/modules/shared/Footer/Footer.module.scss b/src/modules/shared/Footer/Footer.module.scss
index d7e213e..f9455c7 100644
--- a/src/modules/shared/Footer/Footer.module.scss
+++ b/src/modules/shared/Footer/Footer.module.scss
@@ -1,133 +1,133 @@
-@import '../../../../src/styles/utils/variables/colors';
-@import '../../../styles/utils/mixins/mixin-media';
-@import '../../../styles/utils/mixins/mixin-typography';
-
-.footer {
- display: flex;
- justify-content: center;
- padding: 32px 0;
- width: 100%;
- background: $color__white;
- box-shadow: 0px -1px 0px 0px $color__elements;
-
- &__dark {
- display: flex;
- justify-content: center;
- padding: 32px 0;
- width: 100%;
- box-shadow: 0px -1px 0px 0px $color__dark-theme__elements;
- background: $color__dark-theme__black;
-
- @include onMobile {
- justify-content: flex-start;
- flex-direction: column;
- }
- }
-
- @include onMobile {
- justify-content: flex-start;
- flex-direction: column;
- }
-}
-
-.container {
- display: flex;
-
- @include onMobile {
- width: auto;
- margin: 0 16px;
- gap: 32px;
- flex-direction: column;
- align-items: flex-start;
- }
-
- @include onTablet {
- display: flex;
- width: 100%;
- justify-content: space-between;
- margin: 0 32px;
- align-items: center;
- height: 32px;
- }
-
- @include onDesktop {
- max-width: 1200px;
- }
-}
-
-.return_button,
-.return_button__dark {
- display: flex;
- align-items: center;
- gap: 16px;
-
- @include onMobile {
- align-self: center;
- justify-content: center;
- }
-}
-
-.nav_center {
- display: flex;
- width: 33%;
- justify-content: space-between;
-
- @include onMobile {
- flex-direction: column;
- gap: 16px;
- }
-}
-
-.nav_text {
- text-decoration: none;
- display: flex;
- color: $color__secondary;
- font-family: 'Mont', sans-serif;
- justify-content: space-between;
- @include upperCase-typography;
- padding: 18px 12px;
-
- &__dark {
- text-decoration: none;
- display: flex;
- color: $color__dark-theme__white;
- font-family: 'Mont', sans-serif;
- justify-content: space-between;
- @include upperCase-typography;
- padding: 18px 12px;
-
- @include onMobile {
- padding: 0;
- }
- }
-
- @include onMobile {
- padding: 0;
- }
-}
-
-.nav_logo {
- height: 32px;
- display: flex;
- justify-content: flex-start;
-
- &__dark {
- height: 32px;
- display: flex;
- justify-content: flex-start;
- }
-}
-
-.button_top {
- display: flex;
- color: $color__secondary;
- font-family: 'Mont', sans-serif;
- text-decoration: none;
- @include smallText-typography;
-}
-
-.button_logo {
- height: 32px;
- width: 32px;
- display: flex;
-}
+@import '../../../../src/styles/utils/variables/colors';
+@import '../../../styles/utils/mixins/mixin-media';
+@import '../../../styles/utils/mixins/mixin-typography';
+
+.footer {
+ display: flex;
+ justify-content: center;
+ padding: 32px 0;
+ width: 100%;
+ background: $color__white;
+ box-shadow: 0px -1px 0px 0px $color__elements;
+
+ &__dark {
+ display: flex;
+ justify-content: center;
+ padding: 32px 0;
+ width: 100%;
+ box-shadow: 0px -1px 0px 0px $color__dark-theme__elements;
+ background: $color__dark-theme__black;
+
+ @include onMobile {
+ justify-content: flex-start;
+ flex-direction: column;
+ }
+ }
+
+ @include onMobile {
+ justify-content: flex-start;
+ flex-direction: column;
+ }
+}
+
+.container {
+ display: flex;
+
+ @include onMobile {
+ width: auto;
+ margin: 0 16px;
+ gap: 32px;
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ @include onTablet {
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+ margin: 0 32px;
+ align-items: center;
+ height: 32px;
+ }
+
+ @include onDesktop {
+ max-width: 1200px;
+ }
+}
+
+.return_button,
+.return_button__dark {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+
+ @include onMobile {
+ align-self: center;
+ justify-content: center;
+ }
+}
+
+.nav_center {
+ display: flex;
+ width: 33%;
+ justify-content: space-between;
+
+ @include onMobile {
+ flex-direction: column;
+ gap: 16px;
+ }
+}
+
+.nav_text {
+ text-decoration: none;
+ display: flex;
+ color: $color__secondary;
+ font-family: 'Mont', sans-serif;
+ justify-content: space-between;
+ @include upperCase-typography;
+ padding: 18px 12px;
+
+ &__dark {
+ text-decoration: none;
+ display: flex;
+ color: $color__dark-theme__white;
+ font-family: 'Mont', sans-serif;
+ justify-content: space-between;
+ @include upperCase-typography;
+ padding: 18px 12px;
+
+ @include onMobile {
+ padding: 0;
+ }
+ }
+
+ @include onMobile {
+ padding: 0;
+ }
+}
+
+.nav_logo {
+ height: 32px;
+ display: flex;
+ justify-content: flex-start;
+
+ &__dark {
+ height: 32px;
+ display: flex;
+ justify-content: flex-start;
+ }
+}
+
+.button_top {
+ display: flex;
+ color: $color__secondary;
+ font-family: 'Mont', sans-serif;
+ text-decoration: none;
+ @include smallText-typography;
+}
+
+.button_logo {
+ height: 32px;
+ width: 32px;
+ display: flex;
+}
diff --git a/src/modules/shared/Footer/index.ts b/src/modules/shared/Footer/index.ts
index ddcc5a9..df19f26 100644
--- a/src/modules/shared/Footer/index.ts
+++ b/src/modules/shared/Footer/index.ts
@@ -1 +1 @@
-export * from './Footer';
+export * from './Footer';
diff --git a/src/modules/shared/Header/index.ts b/src/modules/shared/Header/index.ts
index 266dec8..8cc2fe3 100644
--- a/src/modules/shared/Header/index.ts
+++ b/src/modules/shared/Header/index.ts
@@ -1 +1 @@
-export * from './Header';
+export * from './Header';
diff --git a/src/modules/shared/Images/Icons/Favourites-icon_Default.svg b/src/modules/shared/Images/Icons/Favourites-icon_Default.svg
new file mode 100644
index 0000000..7c61ff6
--- /dev/null
+++ b/src/modules/shared/Images/Icons/Favourites-icon_Default.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/modules/shared/Images/Icons/Favourites-icon_Selected.svg b/src/modules/shared/Images/Icons/Favourites-icon_Selected.svg
new file mode 100644
index 0000000..c236532
--- /dev/null
+++ b/src/modules/shared/Images/Icons/Favourites-icon_Selected.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/modules/shared/Images/Icons/Favourites-icon_darkDefault.svg b/src/modules/shared/Images/Icons/Favourites-icon_darkDefault.svg
new file mode 100644
index 0000000..465d16b
--- /dev/null
+++ b/src/modules/shared/Images/Icons/Favourites-icon_darkDefault.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/modules/shared/Images/Icons/Favourites-icon_darkSelected.svg b/src/modules/shared/Images/Icons/Favourites-icon_darkSelected.svg
new file mode 100644
index 0000000..5721b4e
--- /dev/null
+++ b/src/modules/shared/Images/Icons/Favourites-icon_darkSelected.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/modules/shared/Loader/Loader.module.scss b/src/modules/shared/Loader/Loader.module.scss
index 232a8f5..b8b4381 100644
--- a/src/modules/shared/Loader/Loader.module.scss
+++ b/src/modules/shared/Loader/Loader.module.scss
@@ -1,6 +1,6 @@
@import '../../../styles/utils/variables/colors';
-.Loader {
+.loader {
display: flex;
width: 100%;
justify-content: center;
@@ -11,9 +11,14 @@
width: 4em;
height: 4em;
margin: 7em auto;
- border: 0.5em solid #ddd;
+ border: 0.5em solid $color__icons;
border-left-color: $color__accent;
animation: load8 1.2s infinite linear;
+
+ &__DARK {
+ border-color: $color__dark-theme__icons;
+ border-left-color: $color__dark-theme__accent;
+ }
}
}
diff --git a/src/modules/shared/Loader/Loader.tsx b/src/modules/shared/Loader/Loader.tsx
index ac7609d..605a8c3 100644
--- a/src/modules/shared/Loader/Loader.tsx
+++ b/src/modules/shared/Loader/Loader.tsx
@@ -1,9 +1,18 @@
import React from 'react';
+import cn from 'classnames';
import styles from './Loader.module.scss';
+import { useAppSelector } from '../../../store/hooks';
-export const Loader: React.FC = () => (
+export const Loader: React.FC = () => {
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
-
-);
+ return (
+
+ );
+};
diff --git a/src/modules/shared/Loader/index.tsx b/src/modules/shared/Loader/index.tsx
index d5ce981..8f8364e 100644
--- a/src/modules/shared/Loader/index.tsx
+++ b/src/modules/shared/Loader/index.tsx
@@ -1 +1 @@
-export * from './Loader';
+export * from './Loader';
diff --git a/src/modules/shared/Pagination/Pagination.module.scss b/src/modules/shared/Pagination/Pagination.module.scss
index e69de29..a05d2fd 100644
--- a/src/modules/shared/Pagination/Pagination.module.scss
+++ b/src/modules/shared/Pagination/Pagination.module.scss
@@ -0,0 +1,101 @@
+@import '../../../styles/utils/variables/colors';
+
+.pagination {
+ display: flex;
+ align-items: center;
+ flex-direction: row;
+ justify-content: center;
+
+ &__numbers {
+ margin-left: 16px;
+ margin-right: 16px;
+ display: flex;
+ flex-direction: row;
+ }
+
+ &__item {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ color: #000;
+ border-radius: 48px;
+ border: 1px solid $color__elements;
+ transition: border 0.3s ease, background-color 0.3s ease;
+
+ &:hover {
+ border: 1px solid $color__primary;
+ }
+
+ &__active {
+ background-color: $color__primary;
+ }
+
+ &__DARK {
+ border-radius: 0px;
+ border: none;
+ background-color: $color__dark-theme__surface-1;
+
+ &:hover {
+ background-color: $color__dark-theme__elements;
+ }
+
+ &__active {
+ background-color: $color__dark-theme__accent;
+ }
+ }
+ }
+
+ &__number {
+ color: #000;
+
+ &__SELECTED {
+ color: $color__white;
+ }
+
+ &__DARK {
+ color: $color__dark-theme__white;
+
+ &__SELECTED {
+ color: $color__dark-theme__white;
+ }
+ }
+ }
+
+ &__arrow {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border-radius: 48px;
+ border: 1px solid $color__elements;
+ transition: border 0.3s ease, background-color 0.3s ease;
+ border: 1px solid $color__icons;
+ background-repeat: no-repeat;
+
+ &:hover {
+ border: 1px solid $color__primary;
+ }
+
+ &__DISABLED {
+ border: 1px solid $color__elements;
+ }
+
+ &__DARK {
+ border-radius: 0px;
+ background-color: $color__dark-theme__surface-2;
+ border: none;
+
+ &:hover {
+ background-color: $color__dark-theme__icons;
+ }
+
+ &__DISABLED {
+ border: 1px solid $color__dark-theme__elements;
+ background-color: none;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/modules/shared/Pagination/Pagination.tsx b/src/modules/shared/Pagination/Pagination.tsx
index 9fec297..07c87f2 100644
--- a/src/modules/shared/Pagination/Pagination.tsx
+++ b/src/modules/shared/Pagination/Pagination.tsx
@@ -1,7 +1,126 @@
-import React from 'react';
-
-// import styles from './Pagination.module.scss';
-
-export const Pagination: React.FC = () => {
- return Pagination
;
-};
+import cn from 'classnames';
+import { Link, useSearchParams } from 'react-router-dom';
+import styles from './Pagination.module.scss';
+import { useAppSelector } from '../../../store/hooks';
+import { getPages } from '../../../utils/getPages';
+import { getSearchWith } from '../../../utils/getSearchWith';
+
+import {
+ ReactComponent as NextIcon,
+} from '../../../static/buttons/Button_DefaultArrowLeft.svg';
+
+import {
+ ReactComponent as PrevIcon,
+} from '../../../static/buttons/Button_DefaultArrowRight.svg';
+
+type Props = {
+ totalPages: number;
+ currentPage: number;
+};
+
+export const Pagination: React.FC = ({
+ totalPages,
+ currentPage,
+}) => {
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ const [searchParams] = useSearchParams();
+ const isFirstPage = currentPage === 1;
+ const isLastPage = currentPage === totalPages;
+
+ const pages = getPages(totalPages, currentPage);
+
+ const findColorForArrow = (isDisabled: boolean) => {
+ if (isDarkTheme && isDisabled) {
+ return '#4A4D58';
+ }
+
+ if (isDarkTheme) {
+ return '#F1F2F9';
+ }
+
+ if (isDisabled) {
+ return '#B4BDC3';
+ }
+
+ return '#0F0F11';
+ };
+
+ return (
+
+ );
+};
diff --git a/src/modules/shared/Pagination/index.ts b/src/modules/shared/Pagination/index.ts
index e016c96..7f74af1 100644
--- a/src/modules/shared/Pagination/index.ts
+++ b/src/modules/shared/Pagination/index.ts
@@ -1 +1 @@
-export * from './Pagination';
+export * from './Pagination';
diff --git a/src/modules/shared/PhoneCard/PhoneCard.tsx b/src/modules/shared/PhoneCard/PhoneCard.tsx
new file mode 100644
index 0000000..1cb2bbb
--- /dev/null
+++ b/src/modules/shared/PhoneCard/PhoneCard.tsx
@@ -0,0 +1,123 @@
+import cn from 'classnames';
+import style from './PhoneCard.module.scss';
+import { useAppSelector } from '../../../store/hooks';
+import { Phone } from '../../../types/Phone';
+
+type Props = {
+ phone: Phone;
+};
+
+export const PhoneCard: React.FC = ({ phone }) => {
+ const {
+ name,
+ fullPrice,
+ price,
+ screen,
+ capacity,
+ ram,
+ image,
+ } = phone;
+
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ const isItemSelected = false;
+
+ const characteristicsArray = [
+ { label: 'Screen', state: screen },
+ { label: 'Capacity', state: capacity },
+ { label: 'RAM', state: ram },
+ ];
+
+ return (
+
+
+
+
+
+
+ {name}
+
+
+
+
+ {`$${price}`}
+
+
+ {price !== fullPrice && (
+
+ {`$${fullPrice}`}
+
+ )}
+
+
+
+ {characteristicsArray.map((characteristic) => (
+
+
+ {characteristic.label}
+
+
+
+ {characteristic.state}
+
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/modules/shared/ProductCard/ProductCard.module.scss b/src/modules/shared/ProductCard/ProductCard.module.scss
index 6c6b195..5fee706 100644
--- a/src/modules/shared/ProductCard/ProductCard.module.scss
+++ b/src/modules/shared/ProductCard/ProductCard.module.scss
@@ -1,179 +1,179 @@
-@import '../../../styles/utils/variables/colors';
-@import '../../../styles/utils/typography';
-@import '../../../styles/utils/mixins/mixin-media';
-
-.productCard {
- display: flex;
- width: 287px;
- padding: 32px;
- flex-direction: column;
- align-items: flex-start;
- flex-shrink: 0;
- flex-wrap: wrap;
- align-content: flex-start;
- box-sizing: border-box;
- // margin: 0 auto;
- grid-column: span 4;
-
- border-radius: 8px;
- border: 1px solid $color__elements;
-
- @include onTablet {
- grid-column: span 6;
- width: 288px;
- }
-
- @media (min-width: 768px) {
- grid-column: span 4;
- }
-
- @include onDesktop {
- grid-column: span 6;
- width: 272px;
-
- }
-
- transition: transform 0.3s ease, box-shadow 0.3s ease;
-
-
- &:hover {
- overflow: hidden;
- transform: scale(1.01);
- box-shadow: 0px 3px 13px 0px $color__secondary;
- }
-
- &__DARK {
- background: #161827;
- border-radius: 0px;
- border: none;
- }
-
- &__image__container {
- display: flex;
- width: 100%;
- height: 196px;
- justify-content: center;
- }
-
- &__image {
- display: block;
- height: 196px;
- }
-
- &__name {
- height: 58px;
- margin-top: 8px;
- padding-top: 16px;
- color: $color__primary;
-
- font-size: 14px;
- font-weight: 600;
- line-height: 21px;
-
- &__DARK {
- color: $color__dark-theme__white;
- }
- }
-
- &__price {
- display: flex;
- margin-top: 8px;
- position: relative;
- padding-bottom: 8px;
-
- &::after {
- content: '';
- position: absolute;
- bottom: 0;
- display: block;
- width: 208px;
- height: 1px;
- background: $color__elements;
- }
-
- &__DARK {
- &::after {
- background: $color__dark-theme__elements;
- }
- }
- }
-
- &__realPrice {
- color: $color__primary;
-
- font-size: 22px;
- font-weight: 800;
- line-height: 140%;
-
- &__DARK {
- color: $color__dark-theme__white;
- }
- }
-
- &__fullPrice {
- margin-left: 8px;
- color: $color__secondary;
-
- font-size: 22px;
- font-weight: 500;
- line-height: normal;
- text-decoration-line: line-through;
-
- &__DARK {
- color: #75767f;
- }
- }
-
- &__characteristics {
- display: flex;
- padding: 8px 0px;
- flex-direction: column;
- align-items: center;
- gap: 8px;
- align-self: stretch;
-
- &__item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- align-self: stretch;
- }
-
- &__label {
- display: block;
- color: $color__secondary;
-
- font-size: 12px;
- font-weight: 600;
- line-height: normal;
-
- &__DARK {
- color: #75767f;
- }
- }
-
- &__state {
- display: block;
- color: $color__primary;
-
- text-align: right;
- font-size: 12px;
- font-weight: 700;
- line-height: normal;
-
- &__DARK {
- color: $color__dark-theme__white;
- }
- }
- }
-
- &__buttons {
- display: flex;
- margin-top: 8px;
- justify-content: space-between;
- align-items: center;
- align-self: stretch;
- padding-bottom: 0px;
- margin-bottom: 0px;
- }
-}
+@import '../../../styles/utils/variables/colors';
+@import '../../../styles/utils/typography';
+@import '../../../styles/utils/mixins/mixin-media';
+
+.productCard {
+ display: flex;
+ width: 287px;
+ padding: 32px;
+ flex-direction: column;
+ align-items: flex-start;
+ flex-shrink: 0;
+ flex-wrap: wrap;
+ align-content: flex-start;
+ box-sizing: border-box;
+ // margin: 0 auto;
+ grid-column: span 4;
+
+ border-radius: 8px;
+ border: 1px solid $color__elements;
+
+ @include onTablet {
+ grid-column: span 6;
+ width: 288px;
+ }
+
+ @media (min-width: 768px) {
+ grid-column: span 4;
+ }
+
+ @include onDesktop {
+ grid-column: span 6;
+ width: 272px;
+
+ }
+
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+
+
+ &:hover {
+ overflow: hidden;
+ transform: scale(1.01);
+ box-shadow: 0px 3px 13px 0px $color__secondary;
+ }
+
+ &__DARK {
+ background: #161827;
+ border-radius: 0px;
+ border: none;
+ }
+
+ &__image__container {
+ display: flex;
+ width: 100%;
+ height: 196px;
+ justify-content: center;
+ }
+
+ &__image {
+ display: block;
+ height: 196px;
+ }
+
+ &__name {
+ height: 58px;
+ margin-top: 8px;
+ padding-top: 16px;
+ color: $color__primary;
+
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+
+ &__DARK {
+ color: $color__dark-theme__white;
+ }
+ }
+
+ &__price {
+ display: flex;
+ margin-top: 8px;
+ position: relative;
+ padding-bottom: 8px;
+
+ &::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ display: block;
+ width: 208px;
+ height: 1px;
+ background: $color__elements;
+ }
+
+ &__DARK {
+ &::after {
+ background: $color__dark-theme__elements;
+ }
+ }
+ }
+
+ &__realPrice {
+ color: $color__primary;
+
+ font-size: 22px;
+ font-weight: 800;
+ line-height: 140%;
+
+ &__DARK {
+ color: $color__dark-theme__white;
+ }
+ }
+
+ &__fullPrice {
+ margin-left: 8px;
+ color: $color__secondary;
+
+ font-size: 22px;
+ font-weight: 500;
+ line-height: normal;
+ text-decoration-line: line-through;
+
+ &__DARK {
+ color: #75767f;
+ }
+ }
+
+ &__characteristics {
+ display: flex;
+ padding: 8px 0px;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+ align-self: stretch;
+
+ &__item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ align-self: stretch;
+ }
+
+ &__label {
+ display: block;
+ color: $color__secondary;
+
+ font-size: 12px;
+ font-weight: 600;
+ line-height: normal;
+
+ &__DARK {
+ color: #75767f;
+ }
+ }
+
+ &__state {
+ display: block;
+ color: $color__primary;
+
+ text-align: right;
+ font-size: 12px;
+ font-weight: 700;
+ line-height: normal;
+
+ &__DARK {
+ color: $color__dark-theme__white;
+ }
+ }
+ }
+
+ &__buttons {
+ display: flex;
+ margin-top: 8px;
+ justify-content: space-between;
+ align-items: center;
+ align-self: stretch;
+ padding-bottom: 0px;
+ margin-bottom: 0px;
+ }
+}
diff --git a/src/modules/shared/ProductList/ProductList.module.scss b/src/modules/shared/ProductList/ProductList.module.scss
index 99233f9..6667e2b 100644
--- a/src/modules/shared/ProductList/ProductList.module.scss
+++ b/src/modules/shared/ProductList/ProductList.module.scss
@@ -1,7 +1,7 @@
-@import '../../../styles/blocks/grid';
-
- .gridContainer {
- @extend .grid;
- grid-row-gap: 40px;
- }
-
+@import '../../../styles/blocks/grid';
+
+ .gridContainer {
+ @extend .grid;
+ grid-row-gap: 40px;
+ }
+
diff --git a/src/modules/shared/ProductList/index.ts b/src/modules/shared/ProductList/index.ts
index c71910a..6c99401 100644
--- a/src/modules/shared/ProductList/index.ts
+++ b/src/modules/shared/ProductList/index.ts
@@ -1 +1 @@
-export * from './ProductList';
+export * from './ProductList';
diff --git a/src/modules/shared/ProductSlider/ProductSlider.module.scss b/src/modules/shared/ProductSlider/ProductSlider.module.scss
index e0f9e26..3626ef9 100644
--- a/src/modules/shared/ProductSlider/ProductSlider.module.scss
+++ b/src/modules/shared/ProductSlider/ProductSlider.module.scss
@@ -1,72 +1,72 @@
-@import '../../../styles/blocks/_grid';
-@import '../../../styles/utils/mixins/mixin-typography';
-
-.header {
- @include h2-typography;
-
- @include onMobile {
- width: 215px;
- }
-
- &__DARK {
- @include typography-dark;
- }
-}
-
-.slick-slide-card,
-.slick-clone-card,
-.slide-card {
- width: 272px !important;
-}
-
-.slick-next-small,
-.slick-prev-small {
- position: absolute;
- height: 32px;
- width: 32px;
- cursor: pointer;
- border: 1px solid $color__secondary;
- border-radius: 48px;
- background-color: $color__white;
- top: -8.6% ;
- -webkit-transform: translate(0, -50%);
- -ms-transform: translate(0, -50%);
- transform: translate(0, -50%);
- padding: 0;
-
- @include onMobile {
- top:-7.7%;
- }
-}
-
-.slick-prev-small {
- right: 48px;
-}
-
-.slick-next-small {
- right: 0px;
-}
-
-.icon {
- display: block;
- margin: auto auto;
-}
-
-.slick-list-card {
- height: 505px;
- width: 100%;
-}
-
-.slider-card {
- margin-top: 24px;
- position: relative;
- width: 100%;
- height: 100%;
- border: none;
- box-sizing: border-box;
-}
-
-.slick-dots-product {
- display: none;
- visibility: hidden;
-}
+@import '../../../styles/blocks/_grid';
+@import '../../../styles/utils/mixins/mixin-typography';
+
+.header {
+ @include h2-typography;
+
+ @include onMobile {
+ width: 215px;
+ }
+
+ &__DARK {
+ @include typography-dark;
+ }
+}
+
+.slick-slide-card,
+.slick-clone-card,
+.slide-card {
+ width: 272px !important;
+}
+
+.slick-next-small,
+.slick-prev-small {
+ position: absolute;
+ height: 32px;
+ width: 32px;
+ cursor: pointer;
+ border: 1px solid $color__secondary;
+ border-radius: 48px;
+ background-color: $color__white;
+ top: -8.6% ;
+ -webkit-transform: translate(0, -50%);
+ -ms-transform: translate(0, -50%);
+ transform: translate(0, -50%);
+ padding: 0;
+
+ @include onMobile {
+ top:-7.7%;
+ }
+}
+
+.slick-prev-small {
+ right: 48px;
+}
+
+.slick-next-small {
+ right: 0px;
+}
+
+.icon {
+ display: block;
+ margin: auto auto;
+}
+
+.slick-list-card {
+ height: 505px;
+ width: 100%;
+}
+
+.slider-card {
+ margin-top: 24px;
+ position: relative;
+ width: 100%;
+ height: 100%;
+ border: none;
+ box-sizing: border-box;
+}
+
+.slick-dots-product {
+ display: none;
+ visibility: hidden;
+}
diff --git a/src/modules/shared/ProductSlider/SampleNextArrow.tsx b/src/modules/shared/ProductSlider/SampleNextArrow.tsx
index 27ff0c3..beb8682 100644
--- a/src/modules/shared/ProductSlider/SampleNextArrow.tsx
+++ b/src/modules/shared/ProductSlider/SampleNextArrow.tsx
@@ -1,61 +1,61 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import React, { useState } from 'react';
-import {
- ReactComponent as NextIcon,
-} from '../../../static/icons/arrow-right_icon.svg';
-import styles from './ProductSlider.module.scss';
-import {
- chooseArrowColor, chooseBackgroundColor, chooseIconColor,
-} from './colorHandlers';
-import { useAppSelector } from '../../../store/hooks';
-
-type Props = {
- handleClick: () => void;
- style?: Record
- currentSlide: number;
- maxSlides: number;
-};
-
-export const SampleNextArrow: React.FC = (props: any) => {
- const [isHover, setIsHover] = useState(false);
-
- const {
- style, onClick, handleClick, currentSlide, maxSlides,
- } = props;
- const { isDarkTheme } = useAppSelector((state) => state.theme);
- // const isDarkTheme = true;
- const isNotDisabled = currentSlide < maxSlides;
-
- return (
- <>
-
- >
- );
-};
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import React, { useState } from 'react';
+import {
+ ReactComponent as NextIcon,
+} from '../../../static/icons/arrow-right_icon.svg';
+import styles from './ProductSlider.module.scss';
+import {
+ chooseArrowColor, chooseBackgroundColor, chooseIconColor,
+} from './colorHandlers';
+import { useAppSelector } from '../../../store/hooks';
+
+type Props = {
+ handleClick: () => void;
+ style?: Record
+ currentSlide: number;
+ maxSlides: number;
+};
+
+export const SampleNextArrow: React.FC = (props: any) => {
+ const [isHover, setIsHover] = useState(false);
+
+ const {
+ style, onClick, handleClick, currentSlide, maxSlides,
+ } = props;
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ // const isDarkTheme = true;
+ const isNotDisabled = currentSlide < maxSlides;
+
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src/modules/shared/ProductSlider/SamplePrevArrow.tsx b/src/modules/shared/ProductSlider/SamplePrevArrow.tsx
index 177a356..58932b1 100644
--- a/src/modules/shared/ProductSlider/SamplePrevArrow.tsx
+++ b/src/modules/shared/ProductSlider/SamplePrevArrow.tsx
@@ -1,58 +1,58 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import React, { useState } from 'react';
-import {
- ReactComponent as PrevIcon,
-} from '../../../static/icons/arrow-left_icon.svg';
-import styles from './ProductSlider.module.scss';
-import {
- chooseArrowColor, chooseBackgroundColor, chooseIconColor,
-} from './colorHandlers';
-import { useAppSelector } from '../../../store/hooks';
-
-type Props = {
- handleClick: () => void;
- currentSlide: number;
-};
-
-export const SamplePrevArrow: React.FC = (props: any) => {
- const [isHover, setIsHover] = useState(false);
-
- const {
- style, onClick, handleClick, currentSlide,
- } = props;
- const { isDarkTheme } = useAppSelector((state) => state.theme);
- // const isDarkTheme = true;
- const isNotDisabled = currentSlide > 0;
-
- return (
- <>
-
- >
- );
-};
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import React, { useState } from 'react';
+import {
+ ReactComponent as PrevIcon,
+} from '../../../static/icons/arrow-left_icon.svg';
+import styles from './ProductSlider.module.scss';
+import {
+ chooseArrowColor, chooseBackgroundColor, chooseIconColor,
+} from './colorHandlers';
+import { useAppSelector } from '../../../store/hooks';
+
+type Props = {
+ handleClick: () => void;
+ currentSlide: number;
+};
+
+export const SamplePrevArrow: React.FC = (props: any) => {
+ const [isHover, setIsHover] = useState(false);
+
+ const {
+ style, onClick, handleClick, currentSlide,
+ } = props;
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ // const isDarkTheme = true;
+ const isNotDisabled = currentSlide > 0;
+
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src/modules/shared/ProductSlider/colorHandlers.ts b/src/modules/shared/ProductSlider/colorHandlers.ts
index 29d43df..1e66791 100644
--- a/src/modules/shared/ProductSlider/colorHandlers.ts
+++ b/src/modules/shared/ProductSlider/colorHandlers.ts
@@ -1,100 +1,100 @@
-export const chooseIconColor = (
- isDarkTheme: boolean, isNotDisabled:boolean,
-) => {
- let iconColor;
-
- switch (true) {
- case isDarkTheme && !isNotDisabled:
- iconColor = '#3b3e4a';
- break;
-
- case isDarkTheme:
- iconColor = '#f1f2f9';
- break;
-
- case !isNotDisabled:
- iconColor = '#b4bdc3';
- break;
-
- default:
- iconColor = '#0f0f11';
- }
-
- return iconColor;
-};
-
-export const chooseArrowColor = (
- isHover: boolean,
- isNotDisabled:boolean,
- isDarkTheme: boolean,
-) => {
- let arrowBorder;
-
- switch (true) {
- case isDarkTheme && !isNotDisabled && isHover:
- arrowBorder = '#3b3e4a';
- break;
-
- case isDarkTheme && !isNotDisabled && !isHover:
- arrowBorder = '#3b3e4a';
- break;
-
- case isDarkTheme && isNotDisabled && isHover:
- arrowBorder = '#4a4d58';
- break;
-
- case isDarkTheme && isNotDisabled && !isHover:
- arrowBorder = '#323542';
- break;
-
- case !isNotDisabled:
- arrowBorder = '#e2e6e9';
- break;
-
- case !isNotDisabled && isHover:
- arrowBorder = '#e2e6e9';
- break;
-
- case isHover:
- arrowBorder = '#0f0f11';
- break;
-
- default:
- arrowBorder = '#b4bdc3';
- break;
- }
-
- return arrowBorder;
-};
-
-export const chooseBackgroundColor = (
- isHover: boolean,
- isNotDisabled:boolean,
- isDarkTheme: boolean,
-) => {
- let backgroundColor;
-
- switch (true) {
- case !isNotDisabled && isDarkTheme && isHover:
- backgroundColor = '#0f1121';
- break;
-
- case !isNotDisabled && isDarkTheme && !isHover:
- backgroundColor = '#0f1121';
- break;
-
- case isNotDisabled && isDarkTheme && isHover:
- backgroundColor = '#4a4d58';
- break;
-
- case isNotDisabled && isDarkTheme && !isHover:
- backgroundColor = '#323542';
- break;
-
- default:
- backgroundColor = '#fff';
- break;
- }
-
- return backgroundColor;
-};
+export const chooseIconColor = (
+ isDarkTheme: boolean, isNotDisabled:boolean,
+) => {
+ let iconColor;
+
+ switch (true) {
+ case isDarkTheme && !isNotDisabled:
+ iconColor = '#3b3e4a';
+ break;
+
+ case isDarkTheme:
+ iconColor = '#f1f2f9';
+ break;
+
+ case !isNotDisabled:
+ iconColor = '#b4bdc3';
+ break;
+
+ default:
+ iconColor = '#0f0f11';
+ }
+
+ return iconColor;
+};
+
+export const chooseArrowColor = (
+ isHover: boolean,
+ isNotDisabled:boolean,
+ isDarkTheme: boolean,
+) => {
+ let arrowBorder;
+
+ switch (true) {
+ case isDarkTheme && !isNotDisabled && isHover:
+ arrowBorder = '#3b3e4a';
+ break;
+
+ case isDarkTheme && !isNotDisabled && !isHover:
+ arrowBorder = '#3b3e4a';
+ break;
+
+ case isDarkTheme && isNotDisabled && isHover:
+ arrowBorder = '#4a4d58';
+ break;
+
+ case isDarkTheme && isNotDisabled && !isHover:
+ arrowBorder = '#323542';
+ break;
+
+ case !isNotDisabled:
+ arrowBorder = '#e2e6e9';
+ break;
+
+ case !isNotDisabled && isHover:
+ arrowBorder = '#e2e6e9';
+ break;
+
+ case isHover:
+ arrowBorder = '#0f0f11';
+ break;
+
+ default:
+ arrowBorder = '#b4bdc3';
+ break;
+ }
+
+ return arrowBorder;
+};
+
+export const chooseBackgroundColor = (
+ isHover: boolean,
+ isNotDisabled:boolean,
+ isDarkTheme: boolean,
+) => {
+ let backgroundColor;
+
+ switch (true) {
+ case !isNotDisabled && isDarkTheme && isHover:
+ backgroundColor = '#0f1121';
+ break;
+
+ case !isNotDisabled && isDarkTheme && !isHover:
+ backgroundColor = '#0f1121';
+ break;
+
+ case isNotDisabled && isDarkTheme && isHover:
+ backgroundColor = '#4a4d58';
+ break;
+
+ case isNotDisabled && isDarkTheme && !isHover:
+ backgroundColor = '#323542';
+ break;
+
+ default:
+ backgroundColor = '#fff';
+ break;
+ }
+
+ return backgroundColor;
+};
diff --git a/src/modules/shared/ProductSlider/index.ts b/src/modules/shared/ProductSlider/index.ts
index 5349238..252db7d 100644
--- a/src/modules/shared/ProductSlider/index.ts
+++ b/src/modules/shared/ProductSlider/index.ts
@@ -1 +1 @@
-export * from './ProductSlider';
+export * from './ProductSlider';
diff --git a/src/modules/shared/ProductSlider/slick-theme.scss b/src/modules/shared/ProductSlider/slick-theme.scss
new file mode 100644
index 0000000..ee0c05b
--- /dev/null
+++ b/src/modules/shared/ProductSlider/slick-theme.scss
@@ -0,0 +1,132 @@
+@charset "UTF-8";
+@import '../../../styles/blocks/grid';
+@import '../../../styles/utils/variables/colors';
+
+/* Arrows */
+// @include onMobile {
+// .slick-prev,
+// .slick-next,
+// .slick-arrow {
+// display: none;
+// visibility: hidden;
+// }
+// }
+
+// @include onTablet {
+// .slick-arrow {
+// position: absolute;
+// height: 400px;
+// width: 32px;
+// cursor: pointer;
+// border: 1px solid $color__secondary;
+// border-radius: 48px;
+// background-color: $color__white;
+// top: 46.5% ;
+// -webkit-transform: translate(0, -50%);
+// -ms-transform: translate(0, -50%);
+// transform: translate(0, -50%);
+// padding: 0;
+
+// &:hover {
+// border-color: $color__primary;
+// }
+// }
+
+// .slick-prev {
+// left: -49px;
+// }
+
+// .slick-next {
+// right: -49px;
+// }
+// }
+
+ // @include onDesktop {
+ // .slick-arrow {
+ // position: absolute;
+ // height: 400px;
+ // width: 32px;
+ // cursor: pointer;
+ // border: 1px solid $color__secondary;
+ // border-radius: 48px;
+ // background-color: $color__white;
+ // top: 46.5% ;
+ // -webkit-transform: translate(0, -50%);
+ // -ms-transform: translate(0, -50%);
+ // transform: translate(0, -50%);
+ // padding: 0;
+
+ // &:hover {
+ // border-color: $color__primary;
+ // }
+ // }
+
+ // .slick-prev {
+ // left: -49px;
+ // }
+
+ // .slick-next {
+ // right: -49px;
+ // }
+ // }
+
+/* Dots */
+
+// .slick-dots-product {
+// display: none;
+// visibility: hidden;
+// }
+
+// .slick-dots {
+// margin-top: 8px;
+// list-style: none;
+// text-align: center;
+// width: 100%;
+
+// li {
+// position: relative;
+// display: inline-block;
+
+// button {
+// border: 0;
+// background: transparent;
+// width: 24px;
+// height: 24px;
+// margin: 0 4px;
+// padding: 0;
+// cursor: pointer;
+// color: transparent;
+
+// &:before {
+// display: block;
+// position: absolute;
+// content: '';
+// width: 14px;
+// height: 4px;
+// margin-top: 7px;
+// margin-left: 4px;
+// background-color: $color__elements;
+// opacity: 1;
+// }
+// }
+
+// &.slick-active button:before {
+// background-color: $color__primary;
+// opacity: 1;
+// }
+// }
+
+// &__dark {
+// li {
+// button {
+// &:before {
+// background-color: #3b3e4a;
+// }
+// }
+
+// &.slick-active button:before {
+// background-color: #f1f2f9;
+// }
+// }
+// }
+// }
diff --git a/src/modules/shared/ProductSlider/slick.scss b/src/modules/shared/ProductSlider/slick.scss
index 4c37447..649646d 100644
--- a/src/modules/shared/ProductSlider/slick.scss
+++ b/src/modules/shared/ProductSlider/slick.scss
@@ -1,118 +1,118 @@
-@import '../../../styles/utils/mixins/mixin-media';
-
-/* Slider */
-
-.slick-slider {
- position: relative;
- display: block;
- box-sizing: border-box;
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- -ms-touch-action: pan-y;
- touch-action: pan-y;
- -webkit-tap-highlight-color: transparent;
-}
-
-.slick-slider .slick-track,
-.slick-slider .slick-list {
- -webkit-transform: translate3d(0, 0, 0);
- -moz-transform: translate3d(0, 0, 0);
- -ms-transform: translate3d(0, 0, 0);
- -o-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
-}
-
-.slick-list-product {
- position: relative;
- overflow: hidden;
- display: block;
- height: 505px !important;
- margin: 0;
- padding:0 !important;
-
- &:focus {
- outline: none;
- }
-
- &.dragging {
- cursor: pointer;
- cursor: hand;
- }
-}
-
-.slick-track-product {
- position: relative;
- left: 0;
- top: 0;
- display: flex !important;
- margin-left: auto;
- margin-right: auto;
- height: 505px !important;
- justify-content: space-between;
-
- &:before,
- &:after {
- content: "";
- display: table;
- }
-
- &:after {
- clear: both;
- }
-
- .slick-loading & {
- visibility: hidden;
- }
-}
-
-.slick-slide {
- float: left;
- height: 100%;
- min-height: 1px;
- [dir="rtl"] & {
- float: right;
- }
- img {
- display: block;
- }
- &.slick-loading img {
- display: none;
- }
-
- display: none;
-
- &.dragging img {
- pointer-events: none;
- }
-
- .slick-initialized & {
- display: block;
- }
-
- .slick-loading & {
- visibility: hidden;
- }
-
- .slick-vertical & {
- display: block;
- height: auto;
- border: 1px solid transparent;
- }
-}
-.slick-arrow.slick-hidden {
- display: none;
-}
-
-#phonesSlider {
- .slick-track {
- display: flex;
- }
- .slick-slide {
- width: 272px !important;
- margin: 0px auto 0px 0px;
- }
-}
+@import '../../../styles/utils/mixins/mixin-media';
+
+/* Slider */
+
+.slick-slider {
+ position: relative;
+ display: block;
+ box-sizing: border-box;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -ms-touch-action: pan-y;
+ touch-action: pan-y;
+ -webkit-tap-highlight-color: transparent;
+}
+
+.slick-slider .slick-track,
+.slick-slider .slick-list {
+ -webkit-transform: translate3d(0, 0, 0);
+ -moz-transform: translate3d(0, 0, 0);
+ -ms-transform: translate3d(0, 0, 0);
+ -o-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+
+.slick-list-product {
+ position: relative;
+ overflow: hidden;
+ display: block;
+ height: 505px !important;
+ margin: 0;
+ padding:0 !important;
+
+ &:focus {
+ outline: none;
+ }
+
+ &.dragging {
+ cursor: pointer;
+ cursor: hand;
+ }
+}
+
+.slick-track-product {
+ position: relative;
+ left: 0;
+ top: 0;
+ display: flex !important;
+ margin-left: auto;
+ margin-right: auto;
+ height: 505px !important;
+ justify-content: space-between;
+
+ &:before,
+ &:after {
+ content: "";
+ display: table;
+ }
+
+ &:after {
+ clear: both;
+ }
+
+ .slick-loading & {
+ visibility: hidden;
+ }
+}
+
+.slick-slide {
+ float: left;
+ height: 100%;
+ min-height: 1px;
+ [dir="rtl"] & {
+ float: right;
+ }
+ img {
+ display: block;
+ }
+ &.slick-loading img {
+ display: none;
+ }
+
+ display: none;
+
+ &.dragging img {
+ pointer-events: none;
+ }
+
+ .slick-initialized & {
+ display: block;
+ }
+
+ .slick-loading & {
+ visibility: hidden;
+ }
+
+ .slick-vertical & {
+ display: block;
+ height: auto;
+ border: 1px solid transparent;
+ }
+}
+.slick-arrow.slick-hidden {
+ display: none;
+}
+
+#phonesSlider {
+ .slick-track {
+ display: flex;
+ }
+ .slick-slide {
+ width: 272px !important;
+ margin: 0px auto 0px 0px;
+ }
+}
diff --git a/src/modules/shared/components/PhoneCard/PhoneCard.module.scss b/src/modules/shared/components/PhoneCard/PhoneCard.module.scss
new file mode 100644
index 0000000..5001234
--- /dev/null
+++ b/src/modules/shared/components/PhoneCard/PhoneCard.module.scss
@@ -0,0 +1,246 @@
+@import '../../../../styles/utils/variables/colors';
+
+.productCard {
+ display: flex;
+ width: 272px;
+ padding: 32px;
+ flex-direction: column;
+ align-items: flex-start;
+ flex-shrink: 0;
+ flex-wrap: wrap;
+ align-content: flex-start;
+ box-sizing: border-box;
+
+ border-radius: 8px;
+ border: 1px solid $color__elements;
+
+ &__DARK {
+ background: #161827;
+ border-radius: 0px;
+ }
+
+ &__image__container {
+ display: flex;
+ width: 208px;
+ height: 196px;
+ justify-content: center;
+ }
+
+ &__image {
+ display: block;
+ height: 196px;
+ }
+
+ &__name {
+ margin-top: 8px;
+ padding-top: 16px;
+ color: $color__primary;
+
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 21px;
+
+ &__DARK {
+ color: $color__dark-theme-white;
+ }
+ }
+
+ &__price {
+ display: flex;
+ margin-top: 8px;
+ position: relative;
+ padding-bottom: 8px;
+
+ &::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ display: block;
+ width: 208px;
+ height: 1px;
+ background: $color__elements;
+ }
+
+ &__DARK {
+ &::after {
+ background: $color__dark-theme-elements;
+ }
+ }
+ }
+
+ &__realPrice {
+ color: $color__primary;
+
+ font-size: 22px;
+ font-style: normal;
+ font-weight: 800;
+ line-height: 140%;
+
+ &__DARK {
+ color: $color__dark-theme-white;
+ }
+ }
+
+ &__fullPrice {
+ margin-left: 8px;
+ color: $color__secondary;
+
+ font-size: 22px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: normal;
+ text-decoration-line: line-through;
+
+ &__DARK {
+ color: #75767f;
+ }
+ }
+
+ &__characteristics {
+ display: flex;
+ padding: 8px 0px;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+ align-self: stretch;
+
+ &__item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ align-self: stretch;
+ }
+
+ &__label {
+ display: block;
+ color: $color__secondary;
+
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: normal;
+
+ &__DARK {
+ color: #75767f;
+ }
+ }
+
+ &__state {
+ display: block;
+ color: $color__primary;
+
+ text-align: right;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: normal;
+
+ &__DARK {
+ color: $color__dark-theme-white;
+ }
+ }
+ }
+
+ &__buttons {
+ display: flex;
+ margin-top: 8px;
+ justify-content: space-between;
+ align-items: center;
+ align-self: stretch;
+ padding-bottom: 0px;
+ margin-bottom: 0px;
+ }
+
+ &__addToCart {
+ display: flex;
+ height: 40px;
+ justify-content: center;
+ align-items: center;
+ flex: 1 0 0;
+
+ border-radius: 8px;
+ border: none;
+ background: $color__accent;
+
+ color: $color__white;
+ text-align: center;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: 21px;
+
+ &:hover {
+ box-shadow: 0px 3px 13px 0px rgba(23, 32, 49, 0.4);
+ }
+
+ &__SELECTED {
+ border-radius: 8px;
+ border: 1px solid $color__elements;
+ background: $color__white;
+ color: $color__accent;
+ }
+
+ &__DARK {
+ background: #905bff;
+ border-radius: 0px;
+ color: $color__dark-theme-white;
+ border: none;
+
+ &:hover {
+ background: #a378ff;
+ }
+
+ &__SELECTED {
+ background: $color__dark-theme-secondary;
+ color: $color__dark-theme-white;
+ }
+ }
+ }
+
+ &__addToFavourite {
+ background-image: url('../../Images/Icons/Favourites-icon_Default.svg');
+
+ margin-left: 8px;
+ width: 40px;
+ height: 40px;
+ flex-shrink: 0;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-color: $color__white;
+
+ border-radius: 48px;
+ border: 1px solid $color__icons;
+
+ &:hover {
+ border: 1px solid $color__primary;
+ }
+
+ &__SELECTED {
+ background-image: url('../../Images/Icons/Favourites-icon_Selected.svg');
+
+ border: 1px solid $color__elements;
+ }
+
+ &__DARK {
+ background-image: url('../../Images/Icons/Favourites-icon_darkDefault.svg');
+
+ background-color: $color__dark-theme-secondary;
+ border-radius: 0px;
+ border: none;
+ color: $color__dark-theme-white;
+
+ &:hover {
+ background-color: #4a4d58;
+ }
+
+ &__SELECTED {
+ background-image: url('../../Images/Icons/Favourites-icon_darkSelected.svg');
+
+ border: 1px solid $color__dark-theme-elements;
+ border-radius: 0px;
+ background-color: $color__dark-theme-secondary;
+ }
+ }
+ }
+}
diff --git a/src/modules/shared/components/PhoneCard/PhoneCard.tsx b/src/modules/shared/components/PhoneCard/PhoneCard.tsx
new file mode 100644
index 0000000..d98cc3d
--- /dev/null
+++ b/src/modules/shared/components/PhoneCard/PhoneCard.tsx
@@ -0,0 +1,149 @@
+/* eslint-disable jsx-a11y/anchor-has-content */
+/* eslint-disable jsx-a11y/control-has-associated-label */
+import cn from 'classnames';
+import style from './PhoneCard.module.scss';
+import { useAppSelector } from '../../../../store/hooks';
+import { Phone } from '../../../../types/Phone';
+
+type Props = {
+ phoneItem: Phone;
+};
+
+export const PhoneCard: React.FC = ({ phoneItem }) => {
+ const {
+ name,
+ fullPrice,
+ price,
+ screen,
+ capacity,
+ ram,
+ image,
+ } = phoneItem;
+
+ const { isDarkTheme } = useAppSelector((state) => state.theme);
+ const isItemSelected = true;
+
+ const showDiscountPrice = () => {
+ if (price !== fullPrice) {
+ return (
+
+ {`$${fullPrice}`}
+
+ );
+ }
+
+ return false;
+ };
+
+ const characteristicsArray = [
+ { label: 'Screen', state: screen },
+ { label: 'Capacity', state: capacity },
+ { label: 'RAM', state: ram },
+ ];
+
+ return (
+
+
+
+
+
+
+ {name}
+
+
+
+
+ {`$${price}`}
+
+
+ {showDiscountPrice()}
+
+
+
+ {characteristicsArray.map((characteristic) => (
+
+
+ {characteristic.label}
+
+
+
+ {characteristic.state}
+
+
+ ))}
+
+
+
+
+
+
+ {/* */}
+
+
+ );
+};
diff --git a/src/modules/shared/components/PhoneCard/index.ts b/src/modules/shared/components/PhoneCard/index.ts
new file mode 100644
index 0000000..53e9b01
--- /dev/null
+++ b/src/modules/shared/components/PhoneCard/index.ts
@@ -0,0 +1 @@
+export * from './PhoneCard';
diff --git a/src/static/api/phones/apple-iphone-7-32gb-black.json b/src/static/api/phones/apple-iphone-7-32gb-black.json
new file mode 100644
index 0000000..e661783
--- /dev/null
+++ b/src/static/api/phones/apple-iphone-7-32gb-black.json
@@ -0,0 +1,48 @@
+
+{
+ "id": "apple-iphone-7-32gb-black",
+ "namespaceId": "apple-iphone-7",
+ "name": "Apple iPhone 7 32GB Black",
+ "capacityAvailable": ["32GB"],
+ "capacity": "32GB",
+ "priceRegular": 400,
+ "priceDiscount": 375,
+ "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "color": "black",
+ "images": [
+ "img/phones/apple-iphone-7/black/00.jpg",
+ "img/phones/apple-iphone-7/black/01.jpg",
+ "img/phones/apple-iphone-7/black/02.jpg",
+ "img/phones/apple-iphone-7/black/03.jpg",
+ "img/phones/apple-iphone-7/black/04.jpg"
+ ],
+ "description": [
+ {
+ "title": "And then there was Pro",
+ "text": [
+ "A transformative triple-camera system that adds tons of capability without complexity.",
+ "An unprecedented leap in battery life. And a mind-blowing chip that doubles down on machine learning and pushes the boundaries of what a smartphone can do. Welcome to the first iPhone powerful enough to be called Pro."
+ ]
+ },
+ {
+ "title": "Camera",
+ "text": [
+ "Meet the first triple-camera system to combine cutting-edge technology with the legendary simplicity of iPhone. Capture up to four times more scene. Get beautiful images in drastically lower light. Shoot the highest-quality video in a smartphone โ then edit with the same tools you love for photos. Youโve never shot with anything like it."
+ ]
+ },
+ {
+ "title": "Shoot it. Flip it. Zoom it. Crop it. Cut it. Light it. Tweak it. Love it.",
+ "text": [
+ "iPhone 11 Pro lets you capture videos that are beautifully true to life, with greater detail and smoother motion. Epic processing power means it can shoot 4K video with extended dynamic range and cinematic video stabilization โ all at 60 fps. You get more creative control, too, with four times more scene and powerful new editing tools to play with."
+ ]
+ }
+ ],
+ "screen": "4.7' IPS",
+ "resolution": "1334x750",
+ "processor": "Apple A10",
+ "ram": "2GB",
+ "camera": "12 Mp + 7 Mp",
+ "zoom": "Digital, 5x",
+ "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+}
+
diff --git a/src/static/api/phones/apple-iphone-7-32gb-rosegold.json b/src/static/api/phones/apple-iphone-7-32gb-rosegold.json
new file mode 100644
index 0000000..e69de29
diff --git a/src/static/api/phones/apple-iphone-7-plus-32gb-black.json b/src/static/api/phones/apple-iphone-7-plus-32gb-black.json
new file mode 100644
index 0000000..19caecb
--- /dev/null
+++ b/src/static/api/phones/apple-iphone-7-plus-32gb-black.json
@@ -0,0 +1,48 @@
+
+{
+ "id": "apple-iphone-7-plus-32gb-black",
+ "namespaceId": "apple-iphone-7-plus",
+ "name": "Apple iPhone 7 Plus 32GB Black",
+ "capacityAvailable": ["32GB"],
+ "capacity": "32GB",
+ "priceRegular": 540,
+ "priceDiscount": 500,
+ "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "color": "black",
+ "images": [
+ "img/phones/apple-iphone-7-plus/black/00.jpg",
+ "img/phones/apple-iphone-7-plus/black/01.jpg",
+ "img/phones/apple-iphone-7-plus/black/02.jpg",
+ "img/phones/apple-iphone-7-plus/black/03.jpg",
+ "img/phones/apple-iphone-7-plus/black/04.jpg"
+ ],
+ "description": [
+ {
+ "title": "And then there was Pro",
+ "text": [
+ "A transformative triple-camera system that adds tons of capability without complexity.",
+ "An unprecedented leap in battery life. And a mind-blowing chip that doubles down on machine learning and pushes the boundaries of what a smartphone can do. Welcome to the first iPhone powerful enough to be called Pro."
+ ]
+ },
+ {
+ "title": "Camera",
+ "text": [
+ "Meet the first triple-camera system to combine cutting-edge technology with the legendary simplicity of iPhone. Capture up to four times more scene. Get beautiful images in drastically lower light. Shoot the highest-quality video in a smartphone โ then edit with the same tools you love for photos. Youโve never shot with anything like it."
+ ]
+ },
+ {
+ "title": "Shoot it. Flip it. Zoom it. Crop it. Cut it. Light it. Tweak it. Love it.",
+ "text": [
+ "iPhone 11 Pro lets you capture videos that are beautifully true to life, with greater detail and smoother motion. Epic processing power means it can shoot 4K video with extended dynamic range and cinematic video stabilization โ all at 60 fps. You get more creative control, too, with four times more scene and powerful new editing tools to play with."
+ ]
+ }
+ ],
+ "screen": "5.5' IPS",
+ "resolution": "1920x1080",
+ "processor": "Apple A10",
+ "ram": "3GB",
+ "camera": "12 Mp + 7 Mp",
+ "zoom": "Digital, 10x / Optical, 2x",
+ "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+}
+
diff --git a/src/static/api/phones/apple-iphone-7-plus-32gb-gold.json b/src/static/api/phones/apple-iphone-7-plus-32gb-gold.json
new file mode 100644
index 0000000..dea5c38
--- /dev/null
+++ b/src/static/api/phones/apple-iphone-7-plus-32gb-gold.json
@@ -0,0 +1,48 @@
+
+{
+ "id": "apple-iphone-7-plus-32gb-gold",
+ "namespaceId": "apple-iphone-7-plus",
+ "name": "Apple iPhone 7 Plus 32GB Gold",
+ "capacityAvailable": ["32GB"],
+ "capacity": "32GB",
+ "priceRegular": 540,
+ "priceDiscount": 500,
+ "colorsAvailable": ["black", "rosegold", "gold", "silver"],
+ "color": "gold",
+ "images": [
+ "img/phones/apple-iphone-7-plus/gold/00.jpg",
+ "img/phones/apple-iphone-7-plus/gold/01.jpg",
+ "img/phones/apple-iphone-7-plus/gold/02.jpg",
+ "img/phones/apple-iphone-7-plus/gold/03.jpg",
+ "img/phones/apple-iphone-7-plus/gold/04.jpg"
+ ],
+ "description": [
+ {
+ "title": "And then there was Pro",
+ "text": [
+ "A transformative triple-camera system that adds tons of capability without complexity.",
+ "An unprecedented leap in battery life. And a mind-blowing chip that doubles down on machine learning and pushes the boundaries of what a smartphone can do. Welcome to the first iPhone powerful enough to be called Pro."
+ ]
+ },
+ {
+ "title": "Camera",
+ "text": [
+ "Meet the first triple-camera system to combine cutting-edge technology with the legendary simplicity of iPhone. Capture up to four times more scene. Get beautiful images in drastically lower light. Shoot the highest-quality video in a smartphone โ then edit with the same tools you love for photos. Youโve never shot with anything like it."
+ ]
+ },
+ {
+ "title": "Shoot it. Flip it. Zoom it. Crop it. Cut it. Light it. Tweak it. Love it.",
+ "text": [
+ "iPhone 11 Pro lets you capture videos that are beautifully true to life, with greater detail and smoother motion. Epic processing power means it can shoot 4K video with extended dynamic range and cinematic video stabilization โ all at 60 fps. You get more creative control, too, with four times more scene and powerful new editing tools to play with."
+ ]
+ }
+ ],
+ "screen": "5.5' IPS",
+ "resolution": "1920x1080",
+ "processor": "Apple A10",
+ "ram": "3GB",
+ "camera": "12 Mp + 7 Mp",
+ "zoom": "Digital, 10x / Optical, 2x",
+ "cell": ["GPRS", "EDGE", "WCDMA", "UMTS", "HSPA", "LTE"]
+}
+
diff --git a/src/static/api/phones/apple-iphone-7-plus-32gb-rosegold.json b/src/static/api/phones/apple-iphone-7-plus-32gb-rosegold.json
new file mode 100644
index 0000000..e69de29
diff --git a/src/static/api/phones/apple-iphone-7-plus-32gb-silver.json b/src/static/api/phones/apple-iphone-7-plus-32gb-silver.json
new file mode 100644
index 0000000..e69de29
diff --git a/src/static/banners/bannersData.js b/src/static/banners/bannersData.js
index 1bb5d1b..8f7b99d 100644
--- a/src/static/banners/bannersData.js
+++ b/src/static/banners/bannersData.js
@@ -2,16 +2,16 @@ export const bannersData = [
{
id: 1,
title: 'banner-phones',
- photo: '/banner-phones.png',
+ photo: '/banners/banner-phones.webp',
},
{
id: 2,
title: 'banner-tablets',
- photo: '/banner-tablets.png',
+ photo: '/banners/banner-tablets.webp',
},
{
id: 3,
title: 'banner-accessories',
- photo: '/banner-accessories.png',
+ photo: '/banners/banner-accessories.webp',
},
];
diff --git a/src/static/buttons/Button_DarkDefaultArrowLeft.svg b/src/static/buttons/Button_DarkDefaultArrowLeft.svg
new file mode 100644
index 0000000..ea1fdf9
--- /dev/null
+++ b/src/static/buttons/Button_DarkDefaultArrowLeft.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Button_DarkDefaultArrowRight.svg b/src/static/buttons/Button_DarkDefaultArrowRight.svg
new file mode 100644
index 0000000..c14adfa
--- /dev/null
+++ b/src/static/buttons/Button_DarkDefaultArrowRight.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Button_DarkDisabledArrowLeft.svg b/src/static/buttons/Button_DarkDisabledArrowLeft.svg
new file mode 100644
index 0000000..f888fc5
--- /dev/null
+++ b/src/static/buttons/Button_DarkDisabledArrowLeft.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Button_DarkDisabledArrowRight.svg b/src/static/buttons/Button_DarkDisabledArrowRight.svg
new file mode 100644
index 0000000..78ead13
--- /dev/null
+++ b/src/static/buttons/Button_DarkDisabledArrowRight.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Button_DefaultArrowLeft.svg b/src/static/buttons/Button_DefaultArrowLeft.svg
new file mode 100644
index 0000000..d2bb8d9
--- /dev/null
+++ b/src/static/buttons/Button_DefaultArrowLeft.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Button_DefaultArrowRight.svg b/src/static/buttons/Button_DefaultArrowRight.svg
new file mode 100644
index 0000000..bc43ed0
--- /dev/null
+++ b/src/static/buttons/Button_DefaultArrowRight.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Button_DisabledArrowLeft.svg b/src/static/buttons/Button_DisabledArrowLeft.svg
new file mode 100644
index 0000000..2f44f37
--- /dev/null
+++ b/src/static/buttons/Button_DisabledArrowLeft.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Button_DisabledArrowRight.svg b/src/static/buttons/Button_DisabledArrowRight.svg
new file mode 100644
index 0000000..abdbd71
--- /dev/null
+++ b/src/static/buttons/Button_DisabledArrowRight.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Icons_ArrowDown.svg b/src/static/buttons/Icons_ArrowDown.svg
new file mode 100644
index 0000000..8819d34
--- /dev/null
+++ b/src/static/buttons/Icons_ArrowDown.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Icons_ArrowUp.svg b/src/static/buttons/Icons_ArrowUp.svg
new file mode 100644
index 0000000..1579b82
--- /dev/null
+++ b/src/static/buttons/Icons_ArrowUp.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Icons_DarkArrowDown.svg b/src/static/buttons/Icons_DarkArrowDown.svg
new file mode 100644
index 0000000..4979e91
--- /dev/null
+++ b/src/static/buttons/Icons_DarkArrowDown.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/Icons_DarktArrowUp.svg b/src/static/buttons/Icons_DarktArrowUp.svg
new file mode 100644
index 0000000..cc4bfb2
--- /dev/null
+++ b/src/static/buttons/Icons_DarktArrowUp.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/static/buttons/fovourites-default_button.svg b/src/static/buttons/fovourites-default_button.svg
index 36393d5..49e569a 100644
--- a/src/static/buttons/fovourites-default_button.svg
+++ b/src/static/buttons/fovourites-default_button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/fovourites-default_button_dark.svg b/src/static/buttons/fovourites-default_button_dark.svg
index e6242ff..dba3aa4 100644
--- a/src/static/buttons/fovourites-default_button_dark.svg
+++ b/src/static/buttons/fovourites-default_button_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/fovourites-hover_button.svg b/src/static/buttons/fovourites-hover_button.svg
index 28c7b9c..7e2892b 100644
--- a/src/static/buttons/fovourites-hover_button.svg
+++ b/src/static/buttons/fovourites-hover_button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/fovourites-selected_button.svg b/src/static/buttons/fovourites-selected_button.svg
index d7c7caf..48a8c19 100644
--- a/src/static/buttons/fovourites-selected_button.svg
+++ b/src/static/buttons/fovourites-selected_button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/fovourites-selected_button_dark.svg b/src/static/buttons/fovourites-selected_button_dark.svg
index 25ac412..b529c28 100644
--- a/src/static/buttons/fovourites-selected_button_dark.svg
+++ b/src/static/buttons/fovourites-selected_button_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/pagination-default__button.svg b/src/static/buttons/pagination-default__button.svg
index ce60ac0..b1cc0d4 100644
--- a/src/static/buttons/pagination-default__button.svg
+++ b/src/static/buttons/pagination-default__button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/pagination-default_button_dark.svg b/src/static/buttons/pagination-default_button_dark.svg
index 39b774b..5f12eda 100644
--- a/src/static/buttons/pagination-default_button_dark.svg
+++ b/src/static/buttons/pagination-default_button_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/pagination-hover_button.svg b/src/static/buttons/pagination-hover_button.svg
index a2e92f6..780250c 100644
--- a/src/static/buttons/pagination-hover_button.svg
+++ b/src/static/buttons/pagination-hover_button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/pagination-selected__button.svg b/src/static/buttons/pagination-selected__button.svg
index 9dcdede..54c5cc4 100644
--- a/src/static/buttons/pagination-selected__button.svg
+++ b/src/static/buttons/pagination-selected__button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/slider-right-button-default_button_dark.svg b/src/static/buttons/slider-right-button-default_button_dark.svg
index c016265..5672883 100644
--- a/src/static/buttons/slider-right-button-default_button_dark.svg
+++ b/src/static/buttons/slider-right-button-default_button_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/slider-right-button-disabled_button.svg b/src/static/buttons/slider-right-button-disabled_button.svg
index 83de078..78ce63f 100644
--- a/src/static/buttons/slider-right-button-disabled_button.svg
+++ b/src/static/buttons/slider-right-button-disabled_button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/slider-right-button-disabled_button_dark.svg b/src/static/buttons/slider-right-button-disabled_button_dark.svg
index 069b974..cbe6546 100644
--- a/src/static/buttons/slider-right-button-disabled_button_dark.svg
+++ b/src/static/buttons/slider-right-button-disabled_button_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/slider-right-button-hover_button.svg b/src/static/buttons/slider-right-button-hover_button.svg
index 037a08e..0dd46fb 100644
--- a/src/static/buttons/slider-right-button-hover_button.svg
+++ b/src/static/buttons/slider-right-button-hover_button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/slider-right-default__button.svg b/src/static/buttons/slider-right-default__button.svg
index aa7038c..4ac81f9 100644
--- a/src/static/buttons/slider-right-default__button.svg
+++ b/src/static/buttons/slider-right-default__button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/slider-up-button-default_button.svg b/src/static/buttons/slider-up-button-default_button.svg
index f04c768..1e46ee1 100644
--- a/src/static/buttons/slider-up-button-default_button.svg
+++ b/src/static/buttons/slider-up-button-default_button.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/buttons/slider-up-button-default_button_dark.svg b/src/static/buttons/slider-up-button-default_button_dark.svg
index ff85414..be4386f 100644
--- a/src/static/buttons/slider-up-button-default_button_dark.svg
+++ b/src/static/buttons/slider-up-button-default_button_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/icons/arrow-down_icon.svg b/src/static/icons/arrow-down_icon.svg
index 8819d34..0b22de4 100644
--- a/src/static/icons/arrow-down_icon.svg
+++ b/src/static/icons/arrow-down_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/arrow-left_icon.svg b/src/static/icons/arrow-left_icon.svg
index e351a43..4432259 100644
--- a/src/static/icons/arrow-left_icon.svg
+++ b/src/static/icons/arrow-left_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/arrow-right_icon.svg b/src/static/icons/arrow-right_icon.svg
index 3f0fdf6..5ff3bbd 100644
--- a/src/static/icons/arrow-right_icon.svg
+++ b/src/static/icons/arrow-right_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/arrow-up_icon.svg b/src/static/icons/arrow-up_icon.svg
index 1579b82..fa2b55d 100644
--- a/src/static/icons/arrow-up_icon.svg
+++ b/src/static/icons/arrow-up_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/cart_icon.svg b/src/static/icons/cart_icon.svg
index 0cbe9f9..b2653e2 100644
--- a/src/static/icons/cart_icon.svg
+++ b/src/static/icons/cart_icon.svg
@@ -1,7 +1,7 @@
-
+
diff --git a/src/static/icons/close_icon.svg b/src/static/icons/close_icon.svg
index 637dbd8..447f12e 100644
--- a/src/static/icons/close_icon.svg
+++ b/src/static/icons/close_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/favourites_icon.svg b/src/static/icons/favourites_icon.svg
index 4c265c2..d21ff1b 100644
--- a/src/static/icons/favourites_icon.svg
+++ b/src/static/icons/favourites_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/home_icon.svg b/src/static/icons/home_icon.svg
index 8ff4bba..7cff7c2 100644
--- a/src/static/icons/home_icon.svg
+++ b/src/static/icons/home_icon.svg
@@ -1,4 +1,4 @@
diff --git a/src/static/icons/menu_icon.svg b/src/static/icons/menu_icon.svg
index b246df7..65d4b20 100644
--- a/src/static/icons/menu_icon.svg
+++ b/src/static/icons/menu_icon.svg
@@ -1,9 +1,9 @@
-
+
diff --git a/src/static/icons/minus_icon.svg b/src/static/icons/minus_icon.svg
index 0547f12..235b2d8 100644
--- a/src/static/icons/minus_icon.svg
+++ b/src/static/icons/minus_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/plus_icon.svg b/src/static/icons/plus_icon.svg
index 3dd6377..974f7e1 100644
--- a/src/static/icons/plus_icon.svg
+++ b/src/static/icons/plus_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/icons/search_icon.svg b/src/static/icons/search_icon.svg
index 3541cda..9f9e97b 100644
--- a/src/static/icons/search_icon.svg
+++ b/src/static/icons/search_icon.svg
@@ -1,5 +1,5 @@
-
+
diff --git a/src/static/selectors/color-default_selector.svg b/src/static/selectors/color-default_selector.svg
index 251b9ac..c26376a 100644
--- a/src/static/selectors/color-default_selector.svg
+++ b/src/static/selectors/color-default_selector.svg
@@ -1,10 +1,10 @@
-
+
diff --git a/src/static/selectors/color-default_selector_dark.svg b/src/static/selectors/color-default_selector_dark.svg
index 879b80e..6379ca0 100644
--- a/src/static/selectors/color-default_selector_dark.svg
+++ b/src/static/selectors/color-default_selector_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/selectors/color-hover_selector.svg b/src/static/selectors/color-hover_selector.svg
index 72ca0f1..2cdfccf 100644
--- a/src/static/selectors/color-hover_selector.svg
+++ b/src/static/selectors/color-hover_selector.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/selectors/color-hover_selector_dark.svg b/src/static/selectors/color-hover_selector_dark.svg
index 31132ed..0aa9767 100644
--- a/src/static/selectors/color-hover_selector_dark.svg
+++ b/src/static/selectors/color-hover_selector_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/selectors/color-selected_selector.svg b/src/static/selectors/color-selected_selector.svg
index 4269a61..b03860f 100644
--- a/src/static/selectors/color-selected_selector.svg
+++ b/src/static/selectors/color-selected_selector.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/static/selectors/color-selected_selector_dark.svg b/src/static/selectors/color-selected_selector_dark.svg
index 4035997..1f9a9da 100644
--- a/src/static/selectors/color-selected_selector_dark.svg
+++ b/src/static/selectors/color-selected_selector_dark.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/store/reducers/themeSlice.ts b/src/store/reducers/themeSlice.ts
index 0e58ed1..dede34a 100644
--- a/src/store/reducers/themeSlice.ts
+++ b/src/store/reducers/themeSlice.ts
@@ -1,26 +1,26 @@
-/* eslint-disable no-param-reassign */
-import { createSlice } from '@reduxjs/toolkit';
-import { localClient } from '../../utils/localClient';
-
-export interface ThemeState {
- isDarkTheme: boolean;
-}
-
-const initialState: ThemeState = {
- isDarkTheme:
- localClient.read('isDarkTheme') || localClient.init('isDarkTheme', false),
-};
-
-const themeSlice = createSlice({
- name: 'theme',
- initialState,
- reducers: {
- change: (state) => {
- state.isDarkTheme = !state.isDarkTheme;
- localClient.write('isDarkTheme', state.isDarkTheme);
- },
- },
-});
-
-export default themeSlice.reducer;
-export const { actions } = themeSlice;
+/* eslint-disable no-param-reassign */
+import { createSlice } from '@reduxjs/toolkit';
+import { localClient } from '../../utils/localClient';
+
+export interface ThemeState {
+ isDarkTheme: boolean;
+}
+
+const initialState: ThemeState = {
+ isDarkTheme:
+ localClient.read('isDarkTheme') || localClient.init('isDarkTheme', false),
+};
+
+const themeSlice = createSlice({
+ name: 'theme',
+ initialState,
+ reducers: {
+ change: (state) => {
+ state.isDarkTheme = !state.isDarkTheme;
+ localClient.write('isDarkTheme', state.isDarkTheme);
+ },
+ },
+});
+
+export default themeSlice.reducer;
+export const { actions } = themeSlice;
diff --git a/src/store/store.ts b/src/store/store.ts
index e1eef62..8072788 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -1,25 +1,25 @@
-import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
-
-import themeReducer from './reducers/themeSlice';
-import favoritesReducer from './reducers/favoritesSlice';
-import cartReducer from './reducers/cartSlice';
-
-export const store = configureStore({
- reducer: {
- theme: themeReducer,
- favorites: favoritesReducer,
- cart: cartReducer,
- },
-});
-
-export type AppDispatch = typeof store.dispatch;
-export type RootState = ReturnType;
-
-/* eslint-disable @typescript-eslint/indent */
-export type AppThunk = ThunkAction<
- ReturnType,
- RootState,
- unknown,
- Action
->;
-/* eslint-enable @typescript-eslint/indent */
+import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
+
+import themeReducer from './reducers/themeSlice';
+import favoritesReducer from './reducers/favoritesSlice';
+import cartReducer from './reducers/cartSlice';
+
+export const store = configureStore({
+ reducer: {
+ theme: themeReducer,
+ favorites: favoritesReducer,
+ cart: cartReducer,
+ },
+});
+
+export type AppDispatch = typeof store.dispatch;
+export type RootState = ReturnType;
+
+/* eslint-disable @typescript-eslint/indent */
+export type AppThunk = ThunkAction<
+ ReturnType,
+ RootState,
+ unknown,
+ Action
+>;
+/* eslint-enable @typescript-eslint/indent */
diff --git a/src/styles/blocks/_grid.scss b/src/styles/blocks/_grid.scss
index 3f7993e..4c3ce38 100644
--- a/src/styles/blocks/_grid.scss
+++ b/src/styles/blocks/_grid.scss
@@ -1,22 +1,22 @@
-@import '../utils/mixins/mixin-media';
-
-$columns--phone: 4;
-$columns--tablet: 12;
-$columns--desktop: 24;
-
-.grid {
- display: grid;
- column-gap: 16px;
-
- @include onMobile {
- grid-template-columns: repeat($columns--phone, 1fr);
- }
-
- @include onTablet {
- grid-template-columns: repeat($columns--tablet, 1fr);
- }
-
- @include onDesktop {
- grid-template-columns: repeat($columns--desktop, 1fr);
- }
-}
+@import '../utils/mixins/mixin-media';
+
+$columns--phone: 4;
+$columns--tablet: 12;
+$columns--desktop: 24;
+
+.grid {
+ display: grid;
+ column-gap: 16px;
+
+ @include onMobile {
+ grid-template-columns: repeat($columns--phone, 1fr);
+ }
+
+ @include onTablet {
+ grid-template-columns: repeat($columns--tablet, 1fr);
+ }
+
+ @include onDesktop {
+ grid-template-columns: repeat($columns--desktop, 1fr);
+ }
+}
diff --git a/src/styles/blocks/_page.scss b/src/styles/blocks/_page.scss
index 782ae90..c86a761 100644
--- a/src/styles/blocks/_page.scss
+++ b/src/styles/blocks/_page.scss
@@ -1,56 +1,56 @@
-@import '../utils/variables/colors';
-@import '../utils/mixins/mixin-media';
-@import '../utils/mixins/mixin-typography';
-
-@mixin defaultMarginButton {
- margin-bottom: 56px;
-
- @include onTablet {
- margin-bottom: 64px;
- }
-
- @include onDesktop {
- margin-bottom: 80px;
- }
-}
-
-.page {
- &__content {
- display: flex;
- flex-direction: column;
- min-height: 100vh;
- }
-
- &__main {
- flex-grow: 1;
- }
-
- &__main-title {
- margin-bottom: 24px;
- @include h1-typography;
-
- @include onTablet {
- margin-bottom: 32px;
- }
-
- @include onDesktop {
- margin-bottom: 56px;
- }
-
- &__DARK {
- @include typography-dark;
- }
- }
-
- &__categories {
- @include defaultMarginButton;
- }
-
- &__main-slider {
- @include defaultMarginButton;
- }
-
- &__product-slider {
- @include defaultMarginButton;
- }
-}
+@import '../utils/variables/colors';
+@import '../utils/mixins/mixin-media';
+@import '../utils/mixins/mixin-typography';
+
+@mixin defaultMarginButton {
+ margin-bottom: 56px;
+
+ @include onTablet {
+ margin-bottom: 64px;
+ }
+
+ @include onDesktop {
+ margin-bottom: 80px;
+ }
+}
+
+.page {
+ &__content {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ }
+
+ &__main {
+ flex-grow: 1;
+ }
+
+ &__main-title {
+ margin-bottom: 24px;
+ @include h1-typography;
+
+ @include onTablet {
+ margin-bottom: 32px;
+ }
+
+ @include onDesktop {
+ margin-bottom: 56px;
+ }
+
+ &__DARK {
+ @include typography-dark;
+ }
+ }
+
+ &__categories {
+ @include defaultMarginButton;
+ }
+
+ &__main-slider {
+ @include defaultMarginButton;
+ }
+
+ &__product-slider {
+ @include defaultMarginButton;
+ }
+}
diff --git a/src/styles/utils/_normalise.scss b/src/styles/utils/_normalise.scss
new file mode 100644
index 0000000..b86d165
--- /dev/null
+++ b/src/styles/utils/_normalise.scss
@@ -0,0 +1,3 @@
+html {
+ box-sizing: border-box;
+}
diff --git a/src/styles/utils/_normalize.scss b/src/styles/utils/_normalize.scss
index b86d165..55f9617 100644
--- a/src/styles/utils/_normalize.scss
+++ b/src/styles/utils/_normalize.scss
@@ -1,3 +1,3 @@
-html {
- box-sizing: border-box;
-}
+html {
+ box-sizing: border-box;
+}
diff --git a/src/styles/utils/_reset.scss b/src/styles/utils/_reset.scss
index 07b9405..d9bc17c 100644
--- a/src/styles/utils/_reset.scss
+++ b/src/styles/utils/_reset.scss
@@ -1,56 +1,56 @@
-html,
-body,
-div,
-span,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-p,
-a,
-address,
-img,
-ol,
-ul,
-li,
-form,
-article,
-aside,
-footer,
-header,
-menu,
-nav,
-section,
-input {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- vertical-align: baseline;
- text-decoration: none;
-}
-
-/* HTML5 display-role reset for older browsers */
-article,
-aside,
-footer,
-header,
-nav,
-section {
- display: block;
-}
-
-body {
- line-height: 1;
-}
-
-ol,
-ul {
- list-style: none;
-}
-
-iframe {
- display: none;
-}
+html,
+body,
+div,
+span,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+a,
+address,
+img,
+ol,
+ul,
+li,
+form,
+article,
+aside,
+footer,
+header,
+menu,
+nav,
+section,
+input {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ vertical-align: baseline;
+ text-decoration: none;
+}
+
+/* HTML5 display-role reset for older browsers */
+article,
+aside,
+footer,
+header,
+nav,
+section {
+ display: block;
+}
+
+body {
+ line-height: 1;
+}
+
+ol,
+ul {
+ list-style: none;
+}
+
+iframe {
+ display: none;
+}
diff --git a/src/styles/utils/mixins/_mixin-media.scss b/src/styles/utils/mixins/_mixin-media.scss
index 66e44c7..a1fe892 100644
--- a/src/styles/utils/mixins/_mixin-media.scss
+++ b/src/styles/utils/mixins/_mixin-media.scss
@@ -1,17 +1,17 @@
-@mixin onMobile {
- @media (max-width: 639px) {
- @content;
- }
-}
-
-@mixin onTablet {
- @media (min-width: 640px) {
- @content;
- }
-}
-
-@mixin onDesktop {
- @media (min-width: 1200px) {
- @content;
- }
-}
+@mixin onMobile {
+ @media (max-width: 639px) {
+ @content;
+ }
+}
+
+@mixin onTablet {
+ @media (min-width: 640px) {
+ @content;
+ }
+}
+
+@mixin onDesktop {
+ @media (min-width: 1200px) {
+ @content;
+ }
+}
diff --git a/src/styles/utils/mixins/_mixin-typography.scss b/src/styles/utils/mixins/_mixin-typography.scss
index d5e639b..1d0fb2e 100644
--- a/src/styles/utils/mixins/_mixin-typography.scss
+++ b/src/styles/utils/mixins/_mixin-typography.scss
@@ -1,81 +1,81 @@
-@import '../variables/colors';
-@import './mixin-media';
-
-@mixin typography-dark {
- color: $color__dark-theme__white;
-}
-
-@mixin h1-typography {
- font-size: 32px;
- font-weight: 800;
- line-height: 41px;
- letter-spacing: -0.32px;
- color: $color__primary;
-
- @include onTablet {
- font-size: 48px;
- line-height: 56px;
- letter-spacing: -0.48px;
- }
-}
-
-@mixin h2-typography {
- font-size: 22px;
- font-weight: 800;
- line-height: 31px;
- letter-spacing: -0.32px;
- color: $color__primary;
-
- @include onTablet {
- font-size: 32px;
- line-height: 41px;
- letter-spacing: -0.48px;
- }
-}
-
-@mixin h3-typography {
- font-size: 20px;
- font-weight: 700;
- color: $color__primary;
-
- @include onTablet {
- font-size: 22px;
- font-weight: 800;
- line-height: 140%;
- }
-}
-
-@mixin h4-typography {
- font-size: 16px;
- font-weight: 700;
- color: $color__primary;
-
- @include onTablet {
- font-size: 20px;
- }
-}
-
-@mixin upperCase-typography {
- font-size: 12px;
- font-weight: 800;
- line-height: 11px;
- letter-spacing: 0.48px;
- text-transform: uppercase;
-}
-
-@mixin buttons-typography {
- font-size: 14px;
- font-weight: 700;
- line-height: 21px;
-}
-
-@mixin bodyText-typography {
- font-size: 14px;
- font-weight: 600;
- line-height: 21px;
-}
-
-@mixin smallText-typography {
- font-size: 12px;
- font-weight: 700;
-}
+@import '../variables/colors';
+@import './mixin-media';
+
+@mixin typography-dark {
+ color: $color__dark-theme__white;
+}
+
+@mixin h1-typography {
+ font-size: 32px;
+ font-weight: 800;
+ line-height: 41px;
+ letter-spacing: -0.32px;
+ color: $color__primary;
+
+ @include onTablet {
+ font-size: 48px;
+ line-height: 56px;
+ letter-spacing: -0.48px;
+ }
+}
+
+@mixin h2-typography {
+ font-size: 22px;
+ font-weight: 800;
+ line-height: 31px;
+ letter-spacing: -0.32px;
+ color: $color__primary;
+
+ @include onTablet {
+ font-size: 32px;
+ line-height: 41px;
+ letter-spacing: -0.48px;
+ }
+}
+
+@mixin h3-typography {
+ font-size: 20px;
+ font-weight: 700;
+ color: $color__primary;
+
+ @include onTablet {
+ font-size: 22px;
+ font-weight: 800;
+ line-height: 140%;
+ }
+}
+
+@mixin h4-typography {
+ font-size: 16px;
+ font-weight: 700;
+ color: $color__primary;
+
+ @include onTablet {
+ font-size: 20px;
+ }
+}
+
+@mixin upperCase-typography {
+ font-size: 12px;
+ font-weight: 800;
+ line-height: 11px;
+ letter-spacing: 0.48px;
+ text-transform: uppercase;
+}
+
+@mixin buttons-typography {
+ font-size: 14px;
+ font-weight: 700;
+ line-height: 21px;
+}
+
+@mixin bodyText-typography {
+ font-size: 14px;
+ font-weight: 600;
+ line-height: 21px;
+}
+
+@mixin smallText-typography {
+ font-size: 12px;
+ font-weight: 700;
+}
diff --git a/src/styles/utils/variables/_colors.scss b/src/styles/utils/variables/_colors.scss
index 6d78991..737740c 100644
--- a/src/styles/utils/variables/_colors.scss
+++ b/src/styles/utils/variables/_colors.scss
@@ -19,3 +19,4 @@ $color__dark-theme__surface-2: #323542;
$color__dark-theme__black: #0f1121;
$color__dark-theme__white: #f1f2f9;
$color__dark-theme__accent: #905bff;
+$color__dark-theme__accent__hover: #a378ff;
diff --git a/src/types/Phone.ts b/src/types/Phone.ts
index 020ce9a..7e18d39 100644
--- a/src/types/Phone.ts
+++ b/src/types/Phone.ts
@@ -1,19 +1,19 @@
-export interface Phone {
- id: number;
- category: string;
- phoneId: string;
- itemId: string;
- name: string;
- fullPrice: number;
- price: number;
- screen: string;
- capacity: string;
- color: string;
- ram: string;
- year: number;
- image: string;
-}
-
-export interface PhoneWithAmount extends Phone {
- amount: number;
-}
+export interface Phone {
+ id: number;
+ category: string;
+ phoneId: string;
+ itemId: string;
+ name: string;
+ fullPrice: number;
+ price: number;
+ screen: string;
+ capacity: string;
+ color: string;
+ ram: string;
+ year: number;
+ image: string;
+}
+
+export interface PhoneWithAmount extends Phone {
+ amount: number;
+}
diff --git a/src/types/PhoneItem.ts b/src/types/PhoneItem.ts
new file mode 100644
index 0000000..ce8a0c4
--- /dev/null
+++ b/src/types/PhoneItem.ts
@@ -0,0 +1,16 @@
+export type PhoneItem = {
+ id: string;
+ name: string;
+ image: string;
+ price: number;
+ fullPrice: number;
+ year: number;
+ screen?: string;
+ capacity?: string;
+ ram?: string;
+ color?: string;
+ description?: {
+ title: string;
+ text: string[];
+ }[];
+};
diff --git a/src/types/SearchParams.ts b/src/types/SearchParams.ts
new file mode 100644
index 0000000..94ecc10
--- /dev/null
+++ b/src/types/SearchParams.ts
@@ -0,0 +1,3 @@
+export type SearchParams = {
+ [key: string]: string | number,
+};
diff --git a/src/utils/axiosClient.ts b/src/utils/axiosClient.ts
index dbd36cf..6aeaf46 100644
--- a/src/utils/axiosClient.ts
+++ b/src/utils/axiosClient.ts
@@ -1,35 +1,35 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import axios from 'axios';
-
-const instance = axios.create({
- baseURL: 'https://fe-aug23-team4-nice-gadgets-api.onrender.com',
-});
-
-function wait(delay: number) {
- return new Promise((resolve) => setTimeout(resolve, delay));
-}
-
-export const axiosClient = {
- async get(url: string) {
- await wait(500);
- const response = await instance.get(url);
-
- return response.data;
- },
-
- async post(url: string, data: any) {
- const response = await instance.post(url, data);
-
- return response.data;
- },
-
- async patch(url: string, data: any) {
- const response = await instance.patch(url, data);
-
- return response.data;
- },
-
- async delete(url: string) {
- return instance.delete(url);
- },
-};
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import axios from 'axios';
+
+const instance = axios.create({
+ baseURL: 'https://fe-aug23-team4-nice-gadgets-api.onrender.com',
+});
+
+function wait(delay: number) {
+ return new Promise((resolve) => setTimeout(resolve, delay));
+}
+
+export const axiosClient = {
+ async get(url: string) {
+ await wait(500);
+ const response = await instance.get(url);
+
+ return response.data;
+ },
+
+ async post(url: string, data: any) {
+ const response = await instance.post(url, data);
+
+ return response.data;
+ },
+
+ async patch(url: string, data: any) {
+ const response = await instance.patch(url, data);
+
+ return response.data;
+ },
+
+ async delete(url: string) {
+ return instance.delete(url);
+ },
+};
diff --git a/src/utils/getPages.ts b/src/utils/getPages.ts
new file mode 100644
index 0000000..faafe00
--- /dev/null
+++ b/src/utils/getPages.ts
@@ -0,0 +1,18 @@
+export const getPages = (totalPages: number, currentPage: number) => {
+ const maxPagesToShow = 5;
+ const pages = [];
+
+ let startPage = currentPage;
+ let endPage = currentPage + (maxPagesToShow - 1);
+
+ if (endPage > totalPages) {
+ endPage = totalPages;
+ startPage = Math.max(totalPages - (maxPagesToShow - 1), 1);
+ }
+
+ for (let i = startPage; i <= endPage; i += 1) {
+ pages.push(i);
+ }
+
+ return pages;
+};
diff --git a/src/utils/getSearchWith.ts b/src/utils/getSearchWith.ts
new file mode 100644
index 0000000..34e3093
--- /dev/null
+++ b/src/utils/getSearchWith.ts
@@ -0,0 +1,27 @@
+import { SearchParams } from '../types/SearchParams';
+
+export function getSearchWith(
+ currentParams: URLSearchParams,
+ paramsToUpdate: SearchParams,
+): string {
+ const newParams = new URLSearchParams(
+ currentParams.toString(),
+ );
+
+ Object.entries(paramsToUpdate)
+ .forEach(([key, value]) => {
+ if (value === null) {
+ newParams.delete(key);
+ } else if (Array.isArray(value)) {
+ newParams.delete(key);
+
+ value.forEach(part => {
+ newParams.append(key, part);
+ });
+ } else {
+ newParams.set(key, value.toString());
+ }
+ });
+
+ return newParams.toString();
+}
diff --git a/src/utils/getSortedProducts.ts b/src/utils/getSortedProducts.ts
new file mode 100644
index 0000000..8cfd612
--- /dev/null
+++ b/src/utils/getSortedProducts.ts
@@ -0,0 +1,24 @@
+import { Phone } from '../types/Phone';
+
+export const getSortedProducts = (
+ recievedProducts: Phone[],
+ params: URLSearchParams,
+) => {
+ const sortBy = params.get('sort') || '';
+ const visibleProducts = [...recievedProducts];
+
+ visibleProducts.sort((product1: Phone, product2: Phone) => {
+ switch (sortBy) {
+ case 'title':
+ return product1.name.localeCompare(product2.name);
+ case 'age':
+ return product2.year - product1.year;
+ case 'price':
+ return product1.price - product2.price;
+ default:
+ return 0;
+ }
+ });
+
+ return visibleProducts;
+};
diff --git a/src/utils/localClient.ts b/src/utils/localClient.ts
index 22bfd39..0c0ad02 100644
--- a/src/utils/localClient.ts
+++ b/src/utils/localClient.ts
@@ -1,55 +1,55 @@
-import { Product } from '../types/Product';
-
-export const localClient = {
- read: (key: string) => {
- const data = window.localStorage.getItem(key);
-
- try {
- return data && JSON.parse(data);
- } catch (error) {
- return null;
- }
- },
-
- write: (key: string, data: unknown) => {
- window.localStorage.setItem(key, JSON.stringify(data, null, 2));
- },
-
- add: (key: string, data: unknown) => {
- const existingData = localClient.read(key);
-
- existingData.push(data);
- window.localStorage.setItem(key, JSON.stringify(existingData, null, 2));
- },
-
- update: (key: string, data: Product) => {
- const existingData = localClient.read(key);
- const newData = existingData.map((item: Product) => {
- return item.id === data.id ? data : item;
- });
-
- window.localStorage.setItem(key, JSON.stringify(newData, null, 2));
- },
-
- delete: (key: string, id: number) => {
- const existingData = localClient.read(key);
- const newData = existingData.filter((item: Product) => item.id !== id);
-
- window.localStorage.setItem(key, JSON.stringify(newData, null, 2));
- },
-
- find: (key: string, id: number) => {
- const existingData: Product[] = localClient.read(key);
-
- return !!existingData.find((item: Product) => item.id === id);
- },
-
- // eslint-disable-next-line consistent-return
- init: (key: string, initialData: unknown) => {
- if (!localClient.read(key)) {
- localClient.write(key, initialData);
-
- return localClient.read(key);
- }
- },
-};
+import { Product } from '../types/Product';
+
+export const localClient = {
+ read: (key: string) => {
+ const data = window.localStorage.getItem(key);
+
+ try {
+ return data && JSON.parse(data);
+ } catch (error) {
+ return null;
+ }
+ },
+
+ write: (key: string, data: unknown) => {
+ window.localStorage.setItem(key, JSON.stringify(data, null, 2));
+ },
+
+ add: (key: string, data: unknown) => {
+ const existingData = localClient.read(key);
+
+ existingData.push(data);
+ window.localStorage.setItem(key, JSON.stringify(existingData, null, 2));
+ },
+
+ update: (key: string, data: Product) => {
+ const existingData = localClient.read(key);
+ const newData = existingData.map((item: Product) => {
+ return item.id === data.id ? data : item;
+ });
+
+ window.localStorage.setItem(key, JSON.stringify(newData, null, 2));
+ },
+
+ delete: (key: string, id: number) => {
+ const existingData = localClient.read(key);
+ const newData = existingData.filter((item: Product) => item.id !== id);
+
+ window.localStorage.setItem(key, JSON.stringify(newData, null, 2));
+ },
+
+ find: (key: string, id: number) => {
+ const existingData: Product[] = localClient.read(key);
+
+ return !!existingData.find((item: Product) => item.id === id);
+ },
+
+ // eslint-disable-next-line consistent-return, @typescript-eslint/no-explicit-any
+ init: (key: string, initialData: any) => {
+ if (!localClient.read(key)) {
+ localClient.write(key, initialData);
+
+ return localClient.read(key);
+ }
+ },
+};