Skip to content

Commit

Permalink
loaders and fetchData were improved
Browse files Browse the repository at this point in the history
  • Loading branch information
Anastasiya145 committed Jul 26, 2023
1 parent 76fdb22 commit 0bd3a62
Show file tree
Hide file tree
Showing 15 changed files with 220 additions and 128 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"homepage": "https://anastasiya145.github.io/react_phone-catalog",
"version": "0.1.0",
"keywords": [],
"author": "Mate Academy",
"author": "Anastasiya Ivanova",
"license": "GPL-3.0",
"dependencies": {
"@cypress/react": "^5.12.4",
Expand Down
10 changes: 10 additions & 0 deletions src/api/fetchData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,13 @@ export const getProducts = () => {
export const getProductById = (id: string) => {
return request<DetailedProduct>(`/products/${id}.json`);
};

export const getProductByCategory = (categoryName: string) => {
return getProducts()
.then(products => {
const productsInCategory = products
.filter(product => product.category === categoryName);

return productsInCategory;
});
};
4 changes: 2 additions & 2 deletions src/components/Carousel/carousel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
}
}

@media #{$phone-media-query} {
@media #{$tablet-media-query} {

.carousel {
height: unset;
Expand All @@ -64,7 +64,7 @@

&__image {
width: 100%;
height: 300px;
height: 100%;
margin: 0;
}

Expand Down
2 changes: 0 additions & 2 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ export const Header: React.FC = () => {
setIsMenuOpened(!isMenuOpened);
};

localStorage.clear();

return (
<>
<div
Expand Down
22 changes: 20 additions & 2 deletions src/components/ProductList/ProductList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { Pagination } from '../Pagination/Pagination';
import { ProductCard } from '../ProductCard/ProductCard';
import { NoSearchResults } from '../NoSearchResults/NoSearchResults';
import './productList.scss';
import { Loader } from '../Loader';

export type Props = {
products: Product[],
isSortDropdownShown?: boolean,
isPaginationShown?: boolean,
handleVisibleProductsNumber:(number: number) => void,
};

export const itemsOptions = ['4', '8', '16', 'All'];
Expand All @@ -21,8 +23,10 @@ export const ProductList: React.FC<Props> = ({
products,
isSortDropdownShown,
isPaginationShown,
handleVisibleProductsNumber,
}) => {
const [searchParams] = useSearchParams();
const [isLoading, setIsLoading] = useState(false);
const itemsOnPage = Number(searchParams.get('itemsOnPage'))
|| products.length;
const sortBy = searchParams.get('sort') || '';
Expand All @@ -49,7 +53,19 @@ export const ProductList: React.FC<Props> = ({
);

useEffect(() => {
setIsLoading(true);

if (handleVisibleProductsNumber) {
handleVisibleProductsNumber(sortedProducts.length);
}

setVisibleProducts(sortedProducts.slice(start, end));

const timer = setTimeout(() => {
setIsLoading(false);
}, 500);

return () => clearTimeout(timer);
}, [products, sortBy, itemsOnPage, page, query]);

const startSortValue = sortBy.length === 0 ? 'Choose an option' : sortBy;
Expand All @@ -59,7 +75,9 @@ export const ProductList: React.FC<Props> = ({

return (
<>
{visibleProducts.length > 0 && (
{isLoading && <Loader />}

{visibleProducts.length > 0 && !isLoading && (
<div className="product-list">
{(isPaginationShown || isSortDropdownShown) && (
<div className="product-list__container">
Expand Down Expand Up @@ -110,7 +128,7 @@ export const ProductList: React.FC<Props> = ({
</div>
)}

{productsByQuery(query).length === 0 && (
{productsByQuery(query).length === 0 && !isLoading && (
<NoSearchResults />
)}
</>
Expand Down
2 changes: 2 additions & 0 deletions src/components/SearchBar/searchBar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
outline: none;
border: none;
border-left: 1px solid $borders-gray-color;
border-right: 1px solid $borders-gray-color;

&::placeholder {
color: $light-gray-color;
Expand Down Expand Up @@ -67,6 +68,7 @@
&__icon {
display: block;
@include button-header;
border: none;
@include bgr-img;
background-image: url($icon-search);
background-size: 20px 20px;
Expand Down
15 changes: 8 additions & 7 deletions src/components/SlickSlider/SlickSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React, { useEffect, useState } from 'react';
import Slider from 'react-slick';
import { Product } from '../../types/Product';
import { ProductCard } from '../ProductCard/ProductCard';
import { sortProducts } from '../../helpers/sortHelper';
import { SortType } from '../../types/SortType';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import './slickSlider.scss';
import { sortProducts } from '../../helpers/sortHelper';
import { SortType } from '../../types/SortType';

export type Props = {
products: Product[],
Expand All @@ -26,22 +26,22 @@ export const SlickSlider: React.FC<Props> = ({ products, sortBy }) => {
infinite: true,
speed: 500,
slidesToShow: 4,
slidesToScroll: 4,
slidesToScroll: 2,
adaptiveHeight: true,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
arrows: false,
slidesToScroll: 2,
},
},
{
breakpoint: 800,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
initialSlide: 2,
slidesToScroll: 1,
variableWidth: true,
arrows: false,
},
},
Expand All @@ -50,6 +50,7 @@ export const SlickSlider: React.FC<Props> = ({ products, sortBy }) => {
settings: {
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true,
arrows: false,
},
},
Expand Down
30 changes: 30 additions & 0 deletions src/components/SlickSlider/slickSlider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,42 @@

.slick {

&-list {
overflow: hidden;
}

&-track {
display: flex;
align-items: flex-start;
}

&-slider {
padding: 0 10px;
position: relative;
}

&-slide {
margin-right: 16px;
}

&-arrow {
@include button-transparent;
height: 32px;
position: absolute;
top: 50%;
background-color: #fff;
z-index: 2;

&:hover,
&:active,
&:focus {
background-color: #fff;
}
}

&-prev {
margin-right: 16px;
left: 0;

&::before {
background-image: url($arrow-left);
Expand All @@ -27,6 +49,7 @@
}

&-next {
right: 0;

&::before {
background-image: url($arrow-right);
Expand All @@ -37,3 +60,10 @@
}
}
}

@media #{$tablet-media-query} {

.slick-track {
gap: 16px;
}
}
49 changes: 34 additions & 15 deletions src/pages/CategoryPage/CategoryPage.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,67 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { Product } from '../../types/Product';
import { SecondNavBar } from '../../components/SecondNavBar/SecondNavBar';
import { NotFound } from '../../components/NotFound/NotFound';
import { ModelsCounter } from '../../components/ModelsCounter/ModelsCounter';
import { ProductList } from '../../components/ProductList/ProductList';
import { Loader } from '../../components/Loader';
import { getProductByCategory } from '../../api/fetchData';
import './categoryPage.scss';

export type Props = {
products: Product[];
isLoading: boolean,
};

export const CategoryPage:React.FC<Props> = ({ products, isLoading }) => {
export const CategoryPage:React.FC = () => {
const [products, setProducts] = useState<Product[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [productCount, setProductCount] = useState(products?.length);
const { pathname } = useLocation();
const categoryName = pathname.slice(1);

async function loadProducts() {
setIsLoading(true);

try {
const productsFromServer = await getProductByCategory(categoryName);

const productName = pathname.slice(1);
setProducts(productsFromServer);
} finally {
setIsLoading(false);
}
}

useEffect(() => {
loadProducts();
}, []);

const handleVisibleProductsNumber = (number: number) => {
setProductCount(number);
};

return (
<>
{!isLoading ? (
<div className={`page__${productName}`}>
{isLoading && <Loader />}

{!isLoading && (
<div className={`page__${categoryName}`}>
<SecondNavBar />
<h1 className="main-title">{productName}</h1>
<ModelsCounter number={products.length} />
<h1 className="main-title">{categoryName}</h1>
<ModelsCounter number={productCount} />

{!products.length ? (
<NotFound
title={
`Sorry, we are temporarily not selling ${productName}.
`Sorry, we are temporarily not selling ${categoryName}.
Please come back in a month.`
}
/>
) : (
<ProductList
products={products}
handleVisibleProductsNumber={handleVisibleProductsNumber}
isSortDropdownShown
isPaginationShown
/>
)}
</div>
) : (
<Loader />
)}
</>
);
Expand Down
14 changes: 11 additions & 3 deletions src/pages/FavoritesPage/FavoritesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext } from 'react';
import React, { useContext, useState } from 'react';
import { AppContext } from '../../context/AppContextProvider';
import { SecondNavBar } from '../../components/SecondNavBar/SecondNavBar';
import { NotFound } from '../../components/NotFound/NotFound';
Expand All @@ -8,19 +8,27 @@ import './favoritesPage.scss';

export const FavoritesPage:React.FC = () => {
const { favorites } = useContext(AppContext);
const [productCount, setProductCount] = useState(favorites.length);

const handleVisibleProductsNumber = (number: number) => {
setProductCount(number);
};

return (
<div className="page__favorites">
<SecondNavBar />
<h1 className="main-title">Favorites</h1>
<ModelsCounter number={favorites.length} />
<ModelsCounter number={productCount} />

{!favorites.length ? (
<NotFound
title="Your favorites list is empty"
/>
) : (
<ProductList products={favorites} />
<ProductList
products={favorites}
handleVisibleProductsNumber={handleVisibleProductsNumber}
/>
)}
</div>
);
Expand Down
Loading

0 comments on commit 0bd3a62

Please sign in to comment.