Skip to content

Commit

Permalink
created a category parent route for the ProductsPage, moved products …
Browse files Browse the repository at this point in the history
…filtering to the ProductsPage and suggestedProducts to the ProductDetailsPage, added smooth appearance for mobile menu, changed breakpoints in media queries
  • Loading branch information
sheva10barca committed Aug 8, 2023
1 parent 36706ae commit 112b98d
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 114 deletions.
75 changes: 5 additions & 70 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Routes, Route } from 'react-router-dom';

import { FavProvider } from './providers/FavProvider/FavProvider';
Expand All @@ -10,17 +10,16 @@ import { ProductDetailsPage }
from './pages/ProductDetailsPage/ProductDetailsPage';
import { FavoritesPage } from './pages/FavoritesPage/FavoritesPage';
import { NotFoundPage } from './pages/NotFoundPage/NotFoundPage';
import { ProductsPage } from './pages/ProductsPage/ProductsPage';

import { Header } from './components/Header/Header';
import { Footer } from './components/Footer/Footer';

import { getProducts } from './api/products';

import { Product } from './types/Product';
import { ProductType } from './types/ProductType';

import './App.scss';
import { ProductsPage } from './pages/ProductsPage/ProductsPage';

const App: React.FC = () => {
const [products, setProducts] = useState<Product[]>([]);
Expand All @@ -35,28 +34,6 @@ const App: React.FC = () => {
}
};

const phones = useMemo(() => {
return products.filter(
(product) => product.type === ProductType.phone,
);
}, [products]);

const tablets = useMemo(() => {
return products.filter(
(product) => product.type === ProductType.tablet,
);
}, [products]);

const accessories = useMemo(() => {
return products.filter(
(product) => product.type === ProductType.accessory,
);
}, [products]);

const suggestedProducts = useMemo(() => {
return [...products].sort(() => Math.random() - 0.5);
}, [products]);

useEffect(() => {
loadProducts();
}, []);
Expand All @@ -72,58 +49,16 @@ const App: React.FC = () => {
<Route path="/">
<Route index element={<HomePage products={products} />} />

<Route path="phones">
<Route path=":category">
<Route
index
element={
<ProductsPage products={phones} title="Mobile phones" />
}
/>
<Route
path=":productId"
element={(
<ProductDetailsPage
products={phones}
suggestedProducts={suggestedProducts}
/>
)}
/>
</Route>

<Route path="tablets">
<Route
index
element={
<ProductsPage products={tablets} title="Tablets" />
}
/>
<Route
path=":productId"
element={(
<ProductDetailsPage
products={tablets}
suggestedProducts={suggestedProducts}
/>
)}
/>
</Route>

<Route path="accessories">
<Route
index
element={(
<ProductsPage
products={accessories}
title="Accessories"
/>
)}
element={<ProductsPage products={products} />}
/>
<Route
path=":productId"
element={(
<ProductDetailsPage
products={accessories}
suggestedProducts={suggestedProducts}
products={products}
/>
)}
/>
Expand Down
27 changes: 15 additions & 12 deletions src/components/Header/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,20 @@
}

.mobile {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
display: flex;
flex-direction: column;
gap: 50px;
background-color: #fafbfc;
z-index: 9999;

transform: translateX(100%);
transition: transform 0.3s;

&__menu {
display: none;
Expand All @@ -225,17 +238,7 @@
}

&.show {
display: flex;
flex-direction: column;
gap: 50px;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #fafbfc;
z-index: 9999;
overflow: hidden;
transform: translateX(0);

.mobile__menu {
display: flex;
Expand Down
21 changes: 5 additions & 16 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const Header: React.FC = () => {

<div className={cn('header__mobile mobile', {
show: showMobileMenu,
'show-menu': showMobileMenu,
})}
>
<div className="mobile__header">
Expand Down Expand Up @@ -106,10 +107,7 @@ export const Header: React.FC = () => {
<li className="mobile__item">
<NavLink
to="/"
className={({ isActive }) => cn(
'header__link',
{ 'header__link--active': isActive },
)}
className="header__link"
onClick={handleLinkClick}
>
Home
Expand All @@ -118,10 +116,7 @@ export const Header: React.FC = () => {
<li className="mobile__item">
<NavLink
to="/phones"
className={({ isActive }) => cn(
'header__link',
{ 'header__link--active': isActive },
)}
className="header__link"
onClick={handleLinkClick}
>
Phones
Expand All @@ -130,10 +125,7 @@ export const Header: React.FC = () => {
<li className="mobile__item">
<NavLink
to="/tablets"
className={({ isActive }) => cn(
'header__link',
{ 'header__link--active': isActive },
)}
className="header__link"
onClick={handleLinkClick}
>
Tablets
Expand All @@ -142,10 +134,7 @@ export const Header: React.FC = () => {
<li className="mobile__item">
<NavLink
to="/accessories"
className={({ isActive }) => cn(
'header__link',
{ 'header__link--active': isActive },
)}
className="header__link"
onClick={handleLinkClick}
>
Accessories
Expand Down
2 changes: 1 addition & 1 deletion src/components/Search/Search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
border-bottom: #e2e6e9;

@include onTablet {
width: 200px;
width: 220px;
padding-left: 16px;
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/pages/ProductDetailsPage/ProductDetailsPage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@
color: #b4bdc3;
font-family: "MontSemiBold", Helvetica, sans-serif;
font-size: 12px;
display: flex;
justify-content: center;
gap: 8px;

&-value {
min-width: fit-content;
}

@include onTablet {
margin-top: 40px;
Expand Down
20 changes: 13 additions & 7 deletions src/pages/ProductDetailsPage/ProductDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ import { useDisableScrollOnPopup } from '../../helpers/useDisableScrollOnPopup';
import './ProductDetailsPage.scss';

type Props = {
suggestedProducts: Product[];
products: Product[];
};

export const ProductDetailsPage: React.FC<Props> = React.memo(
({ suggestedProducts, products }) => {
({ products }) => {
const location = useLocation();
const propsData: ProductDetails = location.state;

Expand Down Expand Up @@ -120,9 +119,11 @@ export const ProductDetailsPage: React.FC<Props> = React.memo(

useDisableScrollOnPopup(showPopup);

const correctedSuggestedProducts = useMemo(() => {
return suggestedProducts.filter((prod) => prod.id !== currentProduct?.id);
}, [suggestedProducts, currentProduct]);
const suggestedProducts = useMemo(() => {
const shuffledProducts = [...products].sort(() => Math.random() - 0.5);

return shuffledProducts.filter((prod) => prod.id !== currentProduct?.id);
}, [products, currentProduct]);

return (
<div className="ProductDetailsPage">
Expand Down Expand Up @@ -273,7 +274,12 @@ export const ProductDetailsPage: React.FC<Props> = React.memo(
</div>
</div>

<div className="ProductDetailsPage__id">{`ID: ${propsData?.id}`}</div>
<div className="ProductDetailsPage__id">
<div className="ProductDetailsPage__id-name">ID:</div>
<div className="ProductDetailsPage__id-value">
{propsData?.id}
</div>
</div>
</div>

<div className="ProductDetailsPage__info">
Expand Down Expand Up @@ -346,7 +352,7 @@ export const ProductDetailsPage: React.FC<Props> = React.memo(

<ProductsSlider
title="You may also like"
products={correctedSuggestedProducts}
products={suggestedProducts}
key={propsData?.id}
/>
</div>
Expand Down
43 changes: 37 additions & 6 deletions src/pages/ProductsPage/ProductsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useParams, useSearchParams } from 'react-router-dom';

import { Product } from '../../types/Product';
import { ProductType } from '../../types/ProductType';
import { getSearchWith } from '../../helpers/searchHelper';
import { sortOptions } from '../../helpers/sortOptions';

Expand All @@ -11,19 +12,18 @@ import { Breadcrumbs } from '../../components/Breadcrumbs/Breadcrumbs';
import { Pagination } from '../../components/Pagination/Pagination';
import { NoSearchResults }
from '../../components/NoSearchResults/NoSearchResults';
import { NoResults } from '../../components/NoResults/NoResults';

import './ProductsPage.scss';
import { NoResults } from '../../components/NoResults/NoResults';

type Props = {
products: Product[];
title: string;
};

const smallestPageSize = 4;

export const ProductsPage: React.FC<Props> = React.memo((
{ products, title },
{ products },
) => {
const [searchParams, setSearchParams] = useSearchParams();
const query = searchParams.get('query') || '';
Expand All @@ -32,6 +32,37 @@ export const ProductsPage: React.FC<Props> = React.memo((
const pageSize = searchParams.get('pageSize') || smallestPageSize;
const currentPage = searchParams.get('currentPage') || 1;

const { category } = useParams();

let title = '' || 'Page';

const categoryProducts = useMemo(() => {
const validCategories = ['phones', 'tablets', 'accessories'];

if (category && validCategories.includes(category)) {
return products.filter((product) => {
switch (category) {
case 'phones':
title = 'Mobile phones';

return product.type === ProductType.phone;
case 'tablets':
title = 'Tablets';

return product.type === ProductType.tablet;
case 'accessories':
title = 'Accessories';

return product.type === ProductType.accessory;
default:
return false;
}
});
}

return [];
}, [products, category]);

const handleSortChange = (newValue: string) => {
setSearchParams(
getSearchWith(
Expand Down Expand Up @@ -59,13 +90,13 @@ export const ProductsPage: React.FC<Props> = React.memo((
};

const filteredProducts = useMemo(() => {
return products.filter(product => {
return categoryProducts.filter(product => {
const normalizedQuery = query.toLowerCase().trim();
const normalizedName = product.name.toLowerCase().trim();

return normalizedName.includes(normalizedQuery);
});
}, [products, query]);
}, [categoryProducts, query]);

const sortedProducts = useMemo(() => {
const productsCopy = [...filteredProducts];
Expand Down
4 changes: 2 additions & 2 deletions src/styles/mixins.scss
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
@mixin onTablet {
@media (max-width: 1023px) {
@media (max-width: 1194px) {
@content;
}
}

@mixin onMobile {
@media (max-width: 743px) {
@media (max-width: 744px) {
@content;
}
}

0 comments on commit 112b98d

Please sign in to comment.