├── public
├── _redirects
├── mobile.png
├── webSite.png
└── index.html
├── src
├── assets
│ ├── logo.png
│ └── shopping.png
├── index.js
├── index.css
├── components
│ ├── Toasts.js
│ ├── Loader.js
│ ├── BarItems.js
│ ├── NavBar.js
│ ├── ProductItem.js
│ ├── DetailItem.js
│ └── CardItem.js
├── pages
│ ├── Contact.js
│ ├── Details.js
│ ├── Favorites.js
│ ├── Products.js
│ └── ShoppingCard.js
├── App.js
└── context
│ └── ProductContext.js
├── .idea
├── .gitignore
├── modules.xml
└── e-commerce-clothes.iml
├── .gitignore
├── README.md
└── package.json
/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
2 |
--------------------------------------------------------------------------------
/public/mobile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yusufdeepwork/react-eCommerce-clothes/HEAD/public/mobile.png
--------------------------------------------------------------------------------
/public/webSite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yusufdeepwork/react-eCommerce-clothes/HEAD/public/webSite.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yusufdeepwork/react-eCommerce-clothes/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/shopping.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yusufdeepwork/react-eCommerce-clothes/HEAD/src/assets/shopping.png
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import EcommerceProvider from './context/ProductContext';
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root'),
14 | );
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/.idea/e-commerce-clothes.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/components/Toasts.js:
--------------------------------------------------------------------------------
1 | export const getAddCardToast = (product, addToast) => {
2 | addToast(`added shopping card :${product.description}`, {
3 | appearance: 'success',
4 | autoDismiss: true,
5 | });
6 | };
7 | export const removeFavoriteToast = (product, addToast) => {
8 | addToast(`removed favorite :${product.description}`, {
9 | appearance: 'info',
10 | autoDismiss: true,
11 | });
12 | };
13 | export const addFavoriteToast = (product, addToast) => {
14 | addToast(`add favorite :${product.description}`, {
15 | appearance: 'success',
16 | autoDismiss: true,
17 | });
18 | };
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # e-Commerce - Clothes Web Site
2 | `🌟` You can see all of clothes and find your style.\
3 | `🌟` If you like a clothes, you can add to your card.\
4 | `🌟` You maybe dont want to buy immediately, you can add favorites it.\
5 | `🌟` Find your style, enjoy shopping.
6 |
7 | # Website Preview
8 | ## Desktop Preview
9 | 
10 | ## Mobile Preview
11 | 
12 |
13 |
14 |
15 | ## Contribute
16 |
17 | In the project directory, you can run:
18 |
19 | ### `yarn start`
20 |
21 | Runs the app in the development mode.\
22 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
23 |
24 |
--------------------------------------------------------------------------------
/src/components/Loader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ContentLoader from 'react-content-loader';
3 |
4 | const Loader = () => {
5 | const createContentLoader = () => (
6 |
13 |
14 |
15 | );
16 | return (
17 | <>
18 | {createContentLoader()}
19 | {createContentLoader()}
20 | {createContentLoader()}
21 | {createContentLoader()}
22 | {createContentLoader()}
23 | {createContentLoader()}
24 | >
25 | );
26 | };
27 |
28 | export default Loader;
29 |
--------------------------------------------------------------------------------
/src/pages/Contact.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 |
4 | const Favorites = () => (
5 |
6 | Dont hesitate to contact our, We work for your style.
7 | Adress: Turkey/Antalya
8 | Email: awesome@suits.com
9 |
10 | );
11 | export default Favorites;
12 | const ContactInfos = styled.div`
13 | font-family: "Fira Code Medium",monospace;
14 | display: flex;
15 | height: 80vh;
16 | font-size:50px;
17 | font-weight: bold;
18 | justify-content: space-evenly;
19 | align-items: center;
20 | text-align: center;
21 | flex-direction: column;
22 | transition: 1s;
23 | animation-name: example;
24 | animation-duration: 5s;
25 | cursor: default;
26 | color: deepskyblue;
27 | @keyframes example {
28 | from {color: black;}
29 | to {color: deepskyblue;}
30 | }
31 | @media screen and (max-width: 770px){
32 | font-size: 30px;
33 | }
34 | `;
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "e-commerce-clothes",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "axios": "^0.21.1",
7 | "react": "^17.0.2",
8 | "react-alert": "^7.0.3",
9 | "react-alert-template-basic": "^1.0.2",
10 | "react-content-loader": "^6.0.3",
11 | "react-dom": "^17.0.2",
12 | "react-icons": "^4.2.0",
13 | "react-router-dom": "^5.2.0",
14 | "react-scripts": "4.0.3",
15 | "react-toast-notifications": "^2.4.4",
16 | "styled-components": "^5.3.0",
17 | "web-vitals": "^1.0.1"
18 | },
19 | "scripts": {
20 | "start": "react-scripts start",
21 | "build": "react-scripts build",
22 | "test": "react-scripts test",
23 | "eject": "react-scripts eject"
24 | },
25 |
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/pages/Details.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useContext } from 'react';
2 | import { useParams } from 'react-router-dom';
3 | import axios from 'axios';
4 | import { CartProductsContainer } from './ShoppingCard';
5 | import DetailItem from '../components/DetailItem';
6 | import { ProductContext } from '../context/ProductContext';
7 |
8 | const Details = () => {
9 | const [detailItem, setDetailItem] = useState();
10 | const dynamicUrl = useParams();
11 | const { id } = dynamicUrl;
12 | const apiUrl = `https://60bfb0e797295a0017c4398c.mockapi.io/clothesImage/${id}`;
13 | const { favorites } = useContext(ProductContext);
14 | useEffect(() => {
15 | axios.get(apiUrl).then((response) => {
16 | setDetailItem(response.data);
17 | }).catch((err) => {
18 | console.log(err);
19 | });
20 | }, [id]);
21 | const favorite = !!favorites.find((favoriteItem) => favoriteItem.id === id);
22 | return (
23 |
24 |
25 |
26 | );
27 | };
28 | export default Details;
29 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from 'react';
2 | import { Switch, Route, Redirect } from 'react-router-dom';
3 | import { ProductContext } from './context/ProductContext';
4 | import NavBar from './components/NavBar';
5 | import BarItems from './components/BarItems';
6 | import Products from './pages/Products';
7 | import Favorites from './pages/Favorites';
8 | import ShoppingCard from './pages/ShoppingCard';
9 | import Details from './pages/Details';
10 | import Contact from './pages/Contact';
11 |
12 | function App() {
13 | const { isBarActive } = useContext(ProductContext);
14 | useEffect(() => {
15 | }, [isBarActive]);
16 |
17 | return (
18 | <>
19 |
20 | {isBarActive ? : null}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | >
31 |
32 | );
33 | }
34 |
35 | export default App;
36 |
--------------------------------------------------------------------------------
/src/pages/Favorites.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import styled from 'styled-components';
3 | import { ProductsContainer } from './Products';
4 | import { ProductContext } from '../context/ProductContext';
5 | import ProductItem from '../components/ProductItem';
6 |
7 | const Favorites = () => {
8 | const { favorites } = useContext(ProductContext);
9 | return (
10 | favorites.length === 0 ? (
11 |
12 | You Dont have favorite Product yet.
13 | You can look products. We are sure you will love.
14 |
15 | ) : (
16 |
17 | {favorites.map((favorite) => )}
18 |
19 | )
20 |
21 | );
22 | };
23 | export default Favorites;
24 | const NoFavorite = styled.div`
25 | font-family: "Fira Code Medium",monospace;
26 | display: flex;
27 | height: 80vh;
28 | font-size:50px;
29 | font-weight: bold;
30 | justify-content: space-evenly;
31 | align-items: center;
32 | color: black;
33 | text-align: center;
34 | flex-direction: column;
35 | @media screen and (max-width: 770px){
36 | font-size: 30px;
37 | }
38 | `;
39 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
15 |
24 | Clothes Shop
25 |
26 |
27 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/components/BarItems.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import styled from 'styled-components';
3 | import { NavLink as Link } from 'react-router-dom';
4 | import { ProductContext } from '../context/ProductContext';
5 |
6 | const BarItems = () => {
7 | const { isBarActive, setIsBarActive } = useContext(ProductContext);
8 | const onChangeBar = (active) => setIsBarActive(!active);
9 | return (
10 |
11 | onChangeBar(isBarActive)} to="/card" activeStyle>
12 | Shopping Card
13 |
14 | onChangeBar(isBarActive)} to="/favorites" activeStyle>
15 | Favorites
16 |
17 | onChangeBar(isBarActive)} to="/contact" activeStyle>
18 | Contact
19 |
20 |
21 | );
22 | };
23 | export default BarItems;
24 |
25 | const BarItemContainer = styled.nav`
26 | display: flex;
27 | text-align: center;
28 | justify-content: space-between;
29 | font-size: 20px;
30 | padding:0 12vw;
31 | flex-direction: column;
32 | @media screen and (max-width: 768px){
33 | padding: 0;
34 | }
35 |
36 | `;
37 |
38 | const BarItem = styled(Link)`
39 | color: white;
40 | display: flex;
41 | border-bottom: cornflowerblue solid 1px;
42 | align-items: center;
43 | justify-content: center;
44 | text-align: center;
45 | text-decoration: none;
46 | padding: 0 1rem;
47 | background: darkblue;
48 | &.active {
49 | color:white ;
50 | }
51 | transition: all 0.2s ease-in-out;
52 | :hover{
53 | background: cornflowerblue;
54 | }
55 | `;
56 |
--------------------------------------------------------------------------------
/src/pages/Products.js:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from 'react';
2 | import styled from 'styled-components';
3 | import axios from 'axios';
4 | import Loader from '../components/Loader';
5 | import ProductItem from '../components/ProductItem';
6 | import { ProductContext } from '../context/ProductContext';
7 |
8 | const Products = () => {
9 | const apiUrl = 'https://60bfb0e797295a0017c4398c.mockapi.io/clothesImage';
10 | const { data, setData, favorites } = useContext(ProductContext);
11 |
12 | useEffect(() => {
13 | axios.get(apiUrl).then((response) => {
14 | setData(response.data);
15 | }).catch((err) => {
16 | // eslint-disable-next-line no-console
17 | console.log(err);
18 | });
19 | }, []);
20 | return (
21 | <>
22 |
23 | {data.length !== 0
24 | ? data.map((product) => (
25 | favoriteItem.id === product.id)}
29 | />
30 |
31 | ))
32 | : }
33 |
34 | >
35 | );
36 | };
37 | export default Products;
38 | export const ProductsContainer = styled.div`
39 | display: grid;
40 | grid-template-columns: repeat(3, 1fr);
41 | grid-gap: 2rem;
42 | grid-auto-rows: 50rem;
43 | grid-auto-columns: 40rem;
44 | text-align: center;
45 | -ms-grid-column-align: center;
46 | -ms-grid-row-align: center;
47 | align-self: center;
48 | padding: 1rem 2rem;
49 | @media screen and (max-width: 1300px){
50 | grid-template-columns: repeat(2, 1fr);
51 | grid-auto-rows: 30rem;
52 | }
53 | @media screen and (max-width: 768px){
54 | grid-template-columns: repeat(1, 1fr);
55 | grid-auto-rows: 35rem;
56 | }
57 | @media screen and (max-width: 600px){
58 | grid-auto-rows: 30rem;
59 | }
60 | `;
61 |
--------------------------------------------------------------------------------
/src/pages/ShoppingCard.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import styled from 'styled-components';
3 | import { useAlert } from 'react-alert';
4 | import { ProductContext } from '../context/ProductContext';
5 | import CardItem from '../components/CardItem';
6 |
7 | const ShoppingCard = () => {
8 | const currency = ' TRY';
9 | const { productsInCard } = useContext(ProductContext);
10 | const alert = useAlert();
11 | const calculateTotalPayment = () => {
12 | let sum = 0;
13 | // eslint-disable-next-line no-unused-expressions
14 | productsInCard ? productsInCard.forEach((item) => {
15 | sum += parseInt(item.price, 10) * item.count;
16 | }) : null;
17 | return sum;
18 | };
19 | const totalPayment = calculateTotalPayment()
20 | return (
21 |
22 |
23 |
24 | Shopping Total Payment :
25 | {` ${totalPayment}`}
26 | {currency}
27 |
28 | {totalPayment ? alert.error('We are sorry, we are closed. Please Try again after.')}
31 | >
32 | Pay
33 | : null}
34 |
35 | {productsInCard.map((product) => )}
36 |
37 | );
38 | };
39 | export default ShoppingCard;
40 | export const CartProductsContainer = styled.div`
41 | cursor: default;
42 | display: flex;
43 | justify-content: center;
44 | flex-direction: column;
45 | text-align: center;
46 | align-items: center;
47 | padding: 1vw 5vw;
48 | `;
49 | const TotalPayment = styled.div`
50 | width: 90%;
51 | height: 10rem;
52 | color: cornflowerblue;
53 | display: flex;
54 | justify-content: space-evenly;
55 | font-size:60px;
56 | align-items:center;
57 | text-align:center;
58 | background-color: lightcyan;
59 | border-radius: 100rem;
60 | margin-top: 5px;
61 | @media screen and (max-width: 600px){
62 | border-radius: 3rem;
63 | }
64 | `;
65 | const TotalPaymentText = styled.text`
66 | font-size: 40px;
67 | font-family: "Fira Code Medium",monospace;
68 | text-align: center;
69 | @media screen and (max-width: 600px){
70 | font-size: 20px;
71 | }
72 | `;
73 | const PayButton = styled.button`
74 | text-align: center;
75 | font-size: 40px;
76 | font-family: "Helvetica Neue",monospace;
77 | margin-right: 5rem;
78 | height: 4rem;
79 | width: 10rem;
80 | border-radius: 10rem;
81 | color: white;
82 | background: darkblue;
83 | :hover{
84 | background: red;
85 | cursor: pointer;
86 | transition: 0.5s;
87 | border: red solid 1px;
88 | }
89 | @media screen and (max-width: 600px){
90 | font-size: 25px;
91 | margin: 2vw;
92 | }
93 | `;
94 |
--------------------------------------------------------------------------------
/src/context/ProductContext.js:
--------------------------------------------------------------------------------
1 | import React, { createContext, useState, useEffect } from 'react';
2 | import { ToastProvider } from 'react-toast-notifications';
3 | import { positions, Provider as AlertProvider } from 'react-alert';
4 | import AlertTemplate from 'react-alert-template-basic';
5 | import { BrowserRouter } from 'react-router-dom';
6 |
7 | export const ProductContext = createContext(undefined, undefined);
8 |
9 | const eCommerceApp = ({ children }) => {
10 | const [isBarActive, setIsBarActive] = useState(false);
11 | const [favorites, setFavorites] = useState([]);
12 | const [productsInCard, setProductsInCard] = useState([]);
13 | const [data, setData] = useState([]);
14 |
15 | useEffect(() => {
16 | }, [isBarActive]);
17 |
18 | const addFavorite = (favoriteProduct) => {
19 | const copyFavoriteArray = [...favorites];
20 | const isInProduct = copyFavoriteArray.map((copyProduct) => copyProduct.id)
21 | .includes(favoriteProduct.id);
22 | if (!isInProduct && favorites) {
23 | setFavorites((prevFavorites) => [...prevFavorites, favoriteProduct]);
24 | }
25 | };
26 |
27 | const removeFavorite = (removedfavorite) => {
28 | const copyFavoriteArray = [...favorites];
29 | const isInProduct = copyFavoriteArray.map((copyProduct) => copyProduct.id)
30 | .includes(removedfavorite.id);
31 | if (isInProduct && favorites) {
32 | setFavorites(copyFavoriteArray.filter((item) => item.id !== removedfavorite.id));
33 | }
34 | };
35 | const changeItem = (willChangeProduct, favorite) => {
36 | if (favorite) {
37 | removeFavorite(willChangeProduct);
38 | } else {
39 | addFavorite(willChangeProduct);
40 | }
41 | };
42 |
43 | const addCard = (willAddCardProduct) => {
44 | const {
45 | id, price, clothesUrl, description,
46 | } = willAddCardProduct;
47 | if (productsInCard.length === 0) {
48 | setProductsInCard([{
49 | id, count: 1, price, clothesUrl, description,
50 | }]);
51 | } else if (productsInCard.find((item) => item.id === id)) {
52 | // eslint-disable-next-line max-len
53 | const updatedCard = productsInCard.map((item) => (item.id === id ? { ...item, count: item.count + 1 } : item));
54 | setProductsInCard(updatedCard);
55 | } else {
56 | setProductsInCard((prevState) => [...prevState, {
57 | id, count: 1, price, clothesUrl, description,
58 | }]);
59 | }
60 | };
61 | return (
62 |
75 |
76 |
77 |
78 | {children}
79 |
80 |
81 |
82 |
83 | );
84 | };
85 | export default eCommerceApp;
86 |
--------------------------------------------------------------------------------
/src/components/NavBar.js:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from 'react';
2 | import styled from 'styled-components';
3 | import { NavLink as Link } from 'react-router-dom';
4 | import { FaBars } from 'react-icons/fa';
5 | import logo from '../assets/logo.png';
6 | import shoppingCart from '../assets/shopping.png';
7 | import { ProductContext } from '../context/ProductContext';
8 |
9 | const NavBar = () => {
10 | const { isBarActive, setIsBarActive, productsInCard } = useContext(ProductContext);
11 | useEffect(() => {
12 |
13 | }, [productsInCard]);
14 | const calculateTotalPayment = () => {
15 | let sum = 0;
16 | // eslint-disable-next-line no-unused-expressions
17 | productsInCard.length !== 0 ? productsInCard.forEach((item) => {
18 | sum += parseInt(item.price, 10) * item.count;
19 | }) : null;
20 | return sum;
21 | };
22 | return (
23 |
41 | );
42 | };
43 | export default NavBar;
44 |
45 | const Nav = styled.nav`
46 | background: #000;
47 | display: flex;
48 | text-align: center;
49 | justify-content: space-between;
50 | height: 6rem;
51 | font-size: 20px;
52 | padding:0 12vw;
53 |
54 | @media screen and (max-width: 768px){
55 | padding: 0;
56 | }
57 | `;
58 | const NavMenu = styled.nav`
59 | display: flex;
60 | align-items: center;
61 | `;
62 |
63 | const NavLink = styled(Link)`
64 | color: white;
65 | display: flex;
66 | align-items: center;
67 | text-decoration: none;
68 | padding: 0 1rem;
69 |
70 | &.active {
71 | color:aquamarine ;
72 | }
73 | transition: all 0.2s ease-in-out;
74 | @media screen and (max-width: 768px){
75 | display: ${(({ active }) => (active ? 'none' : null))}
76 | }
77 | `;
78 | const Bars = styled(FaBars)`
79 | justify-content: center;
80 | align-items: center;
81 | cursor: pointer;
82 | display: none;
83 | color: #fff;
84 | @media screen and (max-width: 768px) {
85 | display: flex;
86 | }
87 | width: 2.5rem;
88 | height: 100%;
89 | margin-right: 20px;
90 | `;
91 | const ProductCardText = styled.h1`
92 | font-size: 24px;
93 | color: royalblue;
94 | padding: 1rem;
95 |
96 | text-align: center;
97 | align-items: center;
98 | transition: 2s;
99 | margin-right: 10px;
100 | animation-name: example;
101 | animation-duration: 2s;
102 | cursor: default;
103 | border-radius: 10rem;
104 | background-color: lightblue;
105 | @keyframes example {
106 | from {color: red;}
107 | to {color: royalblue;}
108 | }
109 | @media screen and (max-width: 1500px){
110 | font-size: 15px;
111 | padding: 0.2rem;
112 | width: 6rem;
113 | }
114 | `;
115 |
--------------------------------------------------------------------------------
/src/components/ProductItem.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import styled from 'styled-components';
3 | import { Link } from 'react-router-dom';
4 | import { useToasts } from 'react-toast-notifications';
5 | import { ProductContext } from '../context/ProductContext';
6 | import { addFavoriteToast, getAddCardToast, removeFavoriteToast } from './Toasts';
7 |
8 | const ProductItem = ({ product, favorite }) => {
9 | const { addCard, changeItem } = useContext(ProductContext);
10 | const { addToast } = useToasts();
11 |
12 | return (
13 |
14 |
15 |
16 |
17 | {product.price} TRY
18 |
19 |
20 |
21 | {
23 | addCard(product);
24 | getAddCardToast(product, addToast);
25 | }}
26 | >
27 | Add To Cart
28 |
29 | See Details
30 | {
32 | changeItem(product, favorite);
33 | // eslint-disable-next-line no-unused-expressions
34 | favorite ? removeFavoriteToast(product, addToast)
35 | : addFavoriteToast(product, addToast);
36 | }}
37 | >
38 |
39 | {favorite ? 'Remove From Favorites ' : 'Add To Favorites'}
40 |
41 |
42 |
43 | );
44 | };
45 | export default ProductItem;
46 |
47 | const ProductCart = styled.div`
48 | display: flex;
49 | text-align: center;
50 | justify-content: center;
51 | align-items: center;
52 | flex-direction: column;
53 | border-radius: 30px;
54 | background-color: ${({favorite}) => favorite ? `lightcyan`: `#f2f2f2` };
55 | color: deepskyblue;
56 | `;
57 | const ProductImage = styled.img`
58 | padding: 1rem 0 0 0;
59 | height: 80%;
60 | width: 80%;
61 | justify-content: center;
62 | align-items: center;
63 | object-fit: contain;
64 | @media screen and (max-width: 768px) and (min-width: 500px){
65 | width: 25rem;
66 | }
67 | `;
68 | const InfoProduct = styled.text`
69 | display: flex;
70 | padding: 0.5rem;
71 | font-size: 20px;
72 | font-family: "Helvetica Neue",monospace;
73 | justify-content: space-between;
74 | background-color: snow;
75 | margin-bottom:5px;
76 | border-radius:10rem;
77 |
78 | :hover{
79 | transition: 0.1s;
80 | color: blue;
81 | cursor: pointer;
82 | background-color: #5cf0ff;
83 | }
84 | @media screen and (max-width: 1300px){
85 | font-size: 1rem;
86 | padding: 0 0.5rem;
87 | }
88 | `;
89 | const ProductBar = styled.div`
90 | display: flex;
91 | justify-content: center;
92 | align-items: center;
93 | margin: 0 10px;
94 |
95 | `;
96 |
97 | const ProductPrice = styled.text`
98 |
99 | padding: 1rem;
100 | font-size: 1.5rem;
101 | font-family: "Helvetica Neue",monospace;
102 | justify-content: space-between;
103 | color: black;
104 | @media screen and (max-width: 1300px){
105 | font-size: 1rem;
106 | padding: 0.5rem 0 0.5rem 0;
107 | }
108 | `;
109 | const ShowingDetails = styled(Link)`
110 | display: flex;
111 | padding: 0.5rem;
112 | margin: 0 10px 5px 10px;
113 | font-size: 20px;
114 | font-family: "Helvetica Neue",monospace;
115 | justify-content: space-between;
116 | background-color: snow;
117 | border-radius:10rem;
118 | color: deepskyblue;
119 |
120 | :hover{
121 | transition: 0.1s;
122 | color: blue;
123 | cursor: pointer;
124 | background-color: #5cf0ff;
125 | }
126 | text-decoration: inherit; /* no underline */
127 | @media screen and (max-width: 1300px){
128 | font-size: 1rem;
129 | padding: 0 0.5rem;
130 | }
131 | `;
132 |
--------------------------------------------------------------------------------
/src/components/DetailItem.js:
--------------------------------------------------------------------------------
1 | import React, { useContext, useEffect } from 'react';
2 | import styled from 'styled-components';
3 | import { useToasts } from 'react-toast-notifications';
4 | import { Link } from 'react-router-dom';
5 | import { addFavoriteToast, removeFavoriteToast, getAddCardToast } from './Toasts';
6 | import { ProductContext } from '../context/ProductContext';
7 |
8 | const DetailItem = ({ product, favorite }) => {
9 | // eslint-disable-next-line no-console
10 | const { addToast } = useToasts();
11 | const { changeItem, addCard } = useContext(ProductContext);
12 | useEffect(() => {
13 |
14 | }, [product, favorite]);
15 |
16 | return (
17 |
18 | {/* eslint-disable-next-line react/destructuring-assignment */}
19 | {product ? (
20 | <>
21 |
22 |
23 |
24 | {product.description}
25 | {`Price : ${product.price}`}
26 |
27 |
28 | {
31 | addCard(product);
32 | getAddCardToast(product, addToast);
33 | }}
34 | >
35 | Add to Card
36 |
37 | {
40 | changeItem(product, favorite);
41 | // eslint-disable-next-line no-unused-expressions
42 | favorite ? removeFavoriteToast(product, addToast)
43 | : addFavoriteToast(product, addToast);
44 | }}
45 | >
46 | {' '}
47 | {favorite ? 'Remove From Favorites ' : 'Add To Favorites'}
48 |
49 |
50 | Back to Products Page
51 |
52 |
53 |
54 | >
55 | ) : null}
56 |
57 |
58 | );
59 | };
60 | export default DetailItem;
61 |
62 | const DetailProductBox = styled.div`
63 | cursor: default;
64 | display: flex;
65 | width: 90%;
66 | height: 80vh;
67 | margin: 1rem 0;
68 | text-align: center;
69 | justify-content: space-evenly ;
70 | align-items: center;
71 | flex-direction: row;
72 | background-color: #f2f2f2;
73 | border-radius: 4rem;
74 |
75 |
76 | @media screen and (max-width:650px){
77 | flex-direction: column;
78 | }
79 | @media screen and (max-width:650px){
80 | height: 85vh;
81 | border-radius: 1rem;
82 | margin: 0;
83 | }
84 | `;
85 | const CartProductImage = styled.img`
86 | height: 90%;
87 | width: 40%;
88 | float: left;
89 | justify-content: center;
90 | align-items: center;
91 | padding: 2rem;
92 | object-fit: contain;
93 |
94 | @media screen and (max-width: 1350px){
95 | width: 20rem;
96 | }
97 | @media screen and (max-width: 320px){
98 | width: 15rem;
99 | }@media screen and (max-width: 500px){
100 | height: 70%;
101 | }
102 | `;
103 |
104 | const DetailInfoProduct = styled.text`
105 | cursor: default;
106 | display: flex;
107 | padding: 1rem;
108 | font-size: 2rem;
109 | font-family: "Helvetica Neue",monospace;
110 | justify-content: space-between;
111 | :hover{
112 | transition: 0.1s;
113 | color: blue;
114 | cursor: ${({ link }) => (link ? 'pointer' : 'default')};
115 | }
116 | @media screen and (max-width:1000px){
117 | font-size: 1.5rem;
118 | }
119 | @media screen and (max-width:650px) {
120 | padding: 0 1rem; font-size: 1rem;
121 | }
122 | @media screen and (max-width:400px) {
123 | font-size: 0.75rem;
124 | }
125 | `;
126 | const DetailProductBar = styled.div`
127 | display: flex;
128 | justify-content: center;
129 | align-items: center;
130 | flex-direction: row;
131 | @media screen and (max-width:1000px) and (min-width: 650px){
132 | flex-direction: column;
133 | }
134 |
135 | `;
136 | const InfoBar = styled.div`
137 | display: flex;
138 | justify-content: space-between;
139 | align-items: center;
140 | flex-direction: column;
141 |
142 |
143 | `;
144 | const BackHome = styled(Link)`
145 |
146 | color: inherit; /* blue colors for links too */
147 | text-decoration: inherit; /* no underline */
148 |
149 | `;
150 | const DetailInfoButton = styled.text`
151 | cursor: default;
152 | display: flex;
153 | padding: 1rem;
154 | margin: 10px 5px;
155 | font-size: 1.5rem;
156 | font-family: "Helvetica Neue",monospace;
157 | justify-content: space-between;
158 | background-color: snow;
159 | color: deepskyblue;
160 | border-radius:10rem;
161 | :hover{
162 | transition: 0.1s;
163 | color: blue;
164 | cursor: pointer;
165 | background-color: #5cf0ff;
166 | }
167 | @media screen and (max-width:1000px){
168 | font-size: 1.5rem;
169 | }
170 | @media screen and (max-width:650px) {
171 | padding: 0 1rem; font-size: 1rem;
172 | }
173 | @media screen and (max-width:400px) {
174 | padding: 0 1rem; font-size: 0.75rem;
175 | }
176 | `;
177 |
--------------------------------------------------------------------------------
/src/components/CardItem.js:
--------------------------------------------------------------------------------
1 | import React, { useContext } from 'react';
2 | import styled from 'styled-components';
3 | import { useToasts } from 'react-toast-notifications';
4 | import { FaPlus, FaMinus } from 'react-icons/fa';
5 | import { NavLink as Link } from 'react-router-dom';
6 | import { ProductContext } from '../context/ProductContext';
7 |
8 | const CardItem = ({ product }) => {
9 | const {
10 | productsInCard, setProductsInCard,
11 | } = useContext(ProductContext);
12 | const { addToast } = useToasts();
13 |
14 | const changeItem = (isAdd) => {
15 | if (!isAdd) {
16 | addToast(`decreased | removed from shopping card :${product.description}`, {
17 | appearance: 'error',
18 | autoDismiss: true,
19 | });
20 | } else {
21 | addToast(`add to shopping card :${product.description}`, {
22 | appearance: 'success',
23 | autoDismiss: true,
24 | });
25 | }
26 | };
27 |
28 | const increaseProductInCard = () => {
29 | const { id } = product;
30 | if (productsInCard.find((item) => item.id === id)) {
31 | // eslint-disable-next-line max-len
32 | const updatedCard = productsInCard.map((item) => (item.id === id ? { ...item, count: item.count + 1 } : item));
33 | setProductsInCard(updatedCard);
34 | }
35 | };
36 |
37 | const decreaseProductInCard = () => {
38 | const { id } = product;
39 | if (productsInCard.find((item) => item.id === id)) {
40 | // eslint-disable-next-line max-len
41 | const updatedCard = productsInCard.map((item) => (item.id === id ? { ...item, count: item.count - 1 } : item));
42 | setProductsInCard(updatedCard.filter((item) => item.count !== 0));
43 | }
44 | };
45 |
46 | const getTotalPrice = () => {
47 | const { id } = product;
48 | const searchedProduct = productsInCard.find((item) => item.id === id);
49 | return searchedProduct.price * searchedProduct.count;
50 | };
51 |
52 | return (
53 |
54 |
55 |
56 | {`Product Price : ${product.price} | Total Price: ${getTotalPrice()}`}
57 | {product.description}
58 | See Details
59 |
60 |
61 |
62 | {
63 | increaseProductInCard();
64 | changeItem(true);
65 | }}
66 | />
67 |
68 | {productsInCard.find((item) => item.id === product.id).count}
69 |
70 | {
71 | decreaseProductInCard();
72 | changeItem(false);
73 | }}
74 | />
75 |
76 |
77 |
78 |
79 | );
80 | };
81 |
82 | export default CardItem;
83 |
84 | const CardBox = styled.div`
85 | cursor: default;
86 | display: flex;
87 | width: 90%;
88 | height: 30rem;
89 | text-align: center;
90 | justify-content: space-between;
91 | align-items: center;
92 | flex-direction: row;
93 | background-color: #f2f2f2;
94 | border-radius: 4rem;
95 | margin: 20px 0px;
96 | @media screen and (max-width: 425px){
97 | height: 20rem;
98 | }
99 |
100 | `;
101 | const CartProductImage = styled.img`
102 | height: 90%;
103 | width: 20%;
104 | float: left;
105 | justify-content: center;
106 | align-items: center;
107 | padding: 2rem;
108 | object-fit: contain;
109 | @media screen and (max-width: 1350px){
110 | width: 20rem;
111 | }
112 | @media screen and (max-width: 600px){
113 | display: none;
114 | }
115 | `;
116 | const InfoProduct = styled.text`
117 | cursor: default;
118 | display: flex;
119 | padding: 1rem;
120 | font-size: 20px;
121 | font-family: "Helvetica Neue",monospace;
122 | justify-content: space-between;
123 |
124 | @media screen and (max-width: 1300px){
125 | font-size: 1rem;
126 | padding: 0 0.5rem;
127 | }
128 | `;
129 | const ProductBar = styled.div`
130 | display: flex;
131 | justify-content: center;
132 | align-items: center;
133 | flex-direction: column;
134 | `;
135 |
136 | const ProductPrice = styled.text`
137 |
138 | padding: 1rem;
139 | font-size: 1.5rem;
140 | font-family: "Helvetica Neue",monospace;
141 | justify-content: space-between;
142 |
143 | @media screen and (max-width: 1300px){
144 | font-size: 1rem;
145 | padding: 0.5rem 0 0.5rem 0;
146 | }
147 | `;
148 | const CardChanges = styled.div`
149 | display: flex;
150 | justify-content: space-evenly;
151 | align-items: center;
152 | flex-direction: column;
153 | margin: 3rem;
154 | font-size: 30px;
155 | padding: 1rem;
156 | @media screen and (max-width: 710px){
157 | font-size: 20px;
158 | padding: 0;
159 | margin: 0;
160 | }
161 | `;
162 | const ChangeItem = styled.div`
163 | display: flex;
164 | padding: 1rem;
165 | font-size: 30px;
166 | font-family: "Helvetica Neue",monospace;
167 | justify-content: space-between;
168 | :hover{
169 | transition: 0.1s;
170 | color: blue;
171 | cursor: pointer;
172 | }
173 |
174 | `;
175 | const ShowDetails = styled(Link)`
176 | display: flex;
177 | align-items: center;
178 | text-decoration: none;
179 | padding: 1rem 1rem;
180 | font-size: 20px;
181 | font-family: "Fira Code Medium",monospace;
182 | margin: 10px;
183 | background-color: lightpink;
184 |
185 | &.active {
186 | color:aquamarine ;
187 |
188 | }
189 | border-radius:10rem;
190 | color: black;
191 |
192 | :hover{
193 | transition: 0.1s;
194 | color: blue;
195 | cursor: pointer;
196 | background-color: #5cf0ff;
197 | }
198 | transition: all 0.2s ease-in-out;
199 | @media screen and (min-width: 600px){
200 | display: none;
201 | }
202 | `;
203 | const ProductCardCount = styled.text`
204 | cursor: default;
205 | font-size: 70px;
206 | color: black;
207 | margin: 1.5rem 0;
208 | font-family: "Fira Code Medium",serif;
209 | @media screen and (max-width: 700px){
210 | font-size: 50px;
211 | margin: 10px;
212 | }
213 | `
214 |
--------------------------------------------------------------------------------