Skip to content

Commit

Permalink
redux is added, code is refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
Blenemy committed Aug 7, 2023
1 parent 39e6feb commit 6fcd98f
Show file tree
Hide file tree
Showing 43 changed files with 914 additions and 536 deletions.
287 changes: 278 additions & 9 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@material-ui/core": "^4.12.4",
"@mui/material": "^5.13.4",
"@reduxjs/toolkit": "^1.9.5",
"@uidotdev/usehooks": "^2.0.1",
"bulma": "^0.9.3",
"classnames": "^2.3.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^8.1.2",
"react-router-dom": "^6.10.0",
"react-scripts": "^4.0.3"
},
Expand Down
92 changes: 44 additions & 48 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
import { useState, useEffect } from 'react';
import { useEffect } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { Footer } from './components/Footer/Footer';
import { Header } from './components/Header/Header';
import { Homepage } from './components/Homepage/Homepage';
import { Homepage } from './pages/Homepage';
import {
ProductDetailsPage,
} from './components/ProductDetailsPage/ProductDetailsPage';
} from './components/ProductDetails/ProductDetailsPage';
import { API_URL, getProducts } from './helpers/helper';
import { Product } from './types/Products';
import './App.scss';
import { Favoutires } from './components/Favourites/Favourites';
import { Cart } from './components/Cart/Cart';
import {
ProductDataContext,
} from './components/ProductDataContext/ProductDataContext';
import { ScrollToTop } from './helpers/ScrollToTop';
import { PhonesPage } from './components/ProductPage/PhonesPage/PhonesPage';
import { TabletsPage } from './components/ProductPage/TabletsPage/TabletsPage';
import { PhonesPage } from './pages/PhonesPage';
import { TabletsPage } from './pages/TabletsPage';
import {
AccessoriesPage,
} from './components/ProductPage/AccessoriesPage/AccessoriesPage';
} from './pages/AccessoriesPage';
import { NotFound } from './components/NotFound/NotFound';
import { useAppDispatch } from './app/hooks';
import { set } from './features/productsSlice';

const App = () => {
const [products, setProducts] = useState<Product[]>([]);
const dispatch = useAppDispatch();

useEffect(() => {
async function fetchData() {
try {
const response = await getProducts(API_URL);

setProducts(response);
dispatch(set(response));
} catch (fetchError) {
throw new Error('Data could not be fetched');
}
Expand All @@ -44,48 +42,46 @@ const App = () => {
<ScrollToTop />
<div className="wrapper">
<Header />
<ProductDataContext.Provider value={products}>
<Routes>
<Route
path="/"
element={<Homepage products={products} />}
/>
<Route path="phones">
<Route index element={<PhonesPage />} />
<Route
path=":productId"
element={<ProductDetailsPage products={products} />}
/>
</Route>
<Route path="tablets">
<Route index element={<TabletsPage />} />
<Route
path=":productId"
element={<ProductDetailsPage products={products} />}
/>
</Route>
<Route path="accessories">
<Route index element={<AccessoriesPage />} />
<Route
path=":productId"
element={<ProductDetailsPage products={products} />}
/>
</Route>
<Routes>
<Route
path="/"
element={<Homepage />}
/>
<Route path="phones">
<Route index element={<PhonesPage />} />
<Route
path="favourites"
element={<Favoutires />}
path=":productId"
element={<ProductDetailsPage />}
/>
</Route>
<Route path="tablets">
<Route index element={<TabletsPage />} />
<Route
path="cart"
element={<Cart />}
path=":productId"
element={<ProductDetailsPage />}
/>
<Route path="*" element={<NotFound />} />
</Route>
<Route path="accessories">
<Route index element={<AccessoriesPage />} />
<Route
path="home"
element={<Navigate to="/" replace />}
path=":productId"
element={<ProductDetailsPage />}
/>
</Routes>
</ProductDataContext.Provider>
</Route>
<Route
path="favourites"
element={<Favoutires />}
/>
<Route
path="cart"
element={<Cart />}
/>
<Route path="*" element={<NotFound />} />
<Route
path="home"
element={<Navigate to="/" replace />}
/>
</Routes>
<Footer />
</div>
</div>
Expand Down
6 changes: 6 additions & 0 deletions src/app/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';

// Use these hooks everywhere instead of useDispatch and useSelector
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
22 changes: 22 additions & 0 deletions src/app/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
import productsSlice from '../features/productsSlice';
import productInfoSlice from '../features/productInfoSlice';

export const store = configureStore({
reducer: {
products: productsSlice,
productInfo: productInfoSlice,
},
});

export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;

/* eslint-disable @typescript-eslint/indent */
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;
/* eslint-enable @typescript-eslint/indent */
14 changes: 6 additions & 8 deletions src/components/Cart/Cart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export const Cart: React.FC = () => {
const cartFromStorage = retrievedData ? JSON.parse(retrievedData) : [];

setCartPhones(cartFromStorage);

return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
};
}, []);

const calculateTotal = (cartArray: Product[]) => {
Expand Down Expand Up @@ -55,14 +61,6 @@ export const Cart: React.FC = () => {
}, 3000);
};

useEffect(() => {
return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
};
}, []);

return (
<main className="cart-page">
<div className="cart-page__container">
Expand Down
15 changes: 9 additions & 6 deletions src/components/Favourites/Favourites.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useMemo, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { ProductCard } from '../ProductCard/ProductCard';
import { PageIndicator } from '../PageIndicator/Phonespage/PageIndicator';
import { PageIndicator } from '../PageIndicator/PageIndicator';
import { Product } from '../../types/Products';
import { NoResults } from '../NoResults/NoResults';

Expand All @@ -12,10 +12,13 @@ export const Favoutires: React.FC = () => {
const [searchParams] = useSearchParams();
const query = searchParams.get('query');

const filteredByQueryPhones = favouritePhones.filter((product) => (
query === null
|| query === ''
|| product.name.toLowerCase().includes(query.toLowerCase())));
const filteredByQueryPhones = useMemo(() => {
return favouritePhones.filter((product) => (
query === null
|| query === ''
|| product.name.toLowerCase().includes(query.toLowerCase())
));
}, [favouritePhones, query]);

return (
<main className="phones-page">
Expand Down
16 changes: 0 additions & 16 deletions src/components/Homepage/Homepage.tsx

This file was deleted.

33 changes: 0 additions & 33 deletions src/components/HotPrices/HotPrices.tsx

This file was deleted.

14 changes: 5 additions & 9 deletions src/components/NoResults/NoResults.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import './NoResults.scss';

export const NoResults: React.FC<{ category: string }> = ({ category }) => {
if (category === 'cart') {
return (
<div className="results-not-found">Your cart is empty</div>
);
}

return (
<div className="results-not-found">
{category}
{' '}
not found
{category === 'cart' ? (
'Your cart is empty'
) : (
`${category} not found`
)}
</div>
);
};
6 changes: 6 additions & 0 deletions src/components/PageIndicator/PageIndicator.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.indicator-name {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 40px;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Link } from 'react-router-dom';
import home from '../../../images/Home.svg';
import arrow from '../../../images/Vector (Stroke).svg';
import home from '../../images/Home.svg';
import './PageIndicator.scss';

type Props = {
Expand All @@ -21,24 +20,11 @@ export const PageIndicator: React.FC<Props> = ({
<img src={home} alt="home" className="indicator-name__img" />
</Link>
</div>
<img
src={arrow}
alt="arrowBack"
className="indicator-name__arrow"
/>
<Link
to={`/${productType.toLowerCase()}`}
className="indicator-name__title"
>
{productType}
</Link>
<div className="indicator-name__arrow">&lt;</div>
<Link to={`/${productType.toLowerCase()}`} className="indicator-name__title">{productType}</Link>
{productName && (
<>
<img
src={arrow}
alt="arrowBack"
className="indicator-name__arrow"
/>
<div className="indicator-name__arrow">&lt;</div>
<div className="indicator-name__title">{productName}</div>
</>
)}
Expand Down
13 changes: 0 additions & 13 deletions src/components/PageIndicator/Phonespage/PageIndicator.scss

This file was deleted.

8 changes: 5 additions & 3 deletions src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,13 @@ export const Pagination: React.FC<Props> = ({
&lt;
</button>

{pages.map((page) => (
{pages.map((page, index) => (
typeof page === 'number'
? (
<button
type="button"
key={page}
// eslint-disable-next-line react/no-array-index-key
key={`${page}_${index}`}
onClick={() => handlePageChange(page)}
className={classNames('pagination__button', {
active: currentPage === page,
Expand All @@ -74,7 +75,8 @@ export const Pagination: React.FC<Props> = ({
)
: (
<div
key={page}
// eslint-disable-next-line react/no-array-index-key
key={`${page}_${index}`}
className="dots"
>
...
Expand Down
4 changes: 0 additions & 4 deletions src/components/ProductDataContext/ProductDataContext.tsx

This file was deleted.

Loading

0 comments on commit 6fcd98f

Please sign in to comment.