Commit 63ecdad7 authored by Pavel Mishakov's avatar Pavel Mishakov

finished lesson 68

parent d0dadb30
......@@ -8,12 +8,14 @@
"name": "burger-builder",
"version": "0.1.0",
"dependencies": {
"@reduxjs/toolkit": "^1.9.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.2.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.4.4",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
......@@ -2907,6 +2909,29 @@
}
}
},
"node_modules/@reduxjs/toolkit": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.1.tgz",
"integrity": "sha512-HikrdY+IDgRfRYlCTGUQaiCxxDDgM1mQrRbZ6S1HFZX5ZYuJ4o8EstNmhTwHdPl2rTmLxzwSu0b3AyeyTlR+RA==",
"dependencies": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.0.2"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@remix-run/router": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz",
......@@ -3589,6 +3614,15 @@
"@types/node": "*"
}
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
......@@ -3761,6 +3795,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/ws": {
"version": "8.5.3",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
......@@ -8108,6 +8147,19 @@
"he": "bin/he"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
......@@ -8371,9 +8423,9 @@
}
},
"node_modules/immer": {
"version": "9.0.14",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz",
"integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw==",
"version": "9.0.16",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz",
"integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
......@@ -13507,6 +13559,49 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
......@@ -13675,6 +13770,22 @@
"node": ">=8"
}
},
"node_modules/redux": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"peerDependencies": {
"redux": "^4"
}
},
"node_modules/regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
......@@ -13817,6 +13928,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
},
"node_modules/reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"node_modules/resolve": {
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
......@@ -15367,6 +15483,14 @@
"punycode": "^2.1.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
......@@ -18300,6 +18424,17 @@
"source-map": "^0.7.3"
}
},
"@reduxjs/toolkit": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.1.tgz",
"integrity": "sha512-HikrdY+IDgRfRYlCTGUQaiCxxDDgM1mQrRbZ6S1HFZX5ZYuJ4o8EstNmhTwHdPl2rTmLxzwSu0b3AyeyTlR+RA==",
"requires": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
}
},
"@remix-run/router": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.4.tgz",
......@@ -18786,6 +18921,15 @@
"@types/node": "*"
}
},
"@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
......@@ -18958,6 +19102,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
},
"@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@types/ws": {
"version": "8.5.3",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
......@@ -22110,6 +22259,21 @@
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"requires": {
"react-is": "^16.7.0"
},
"dependencies": {
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}
}
},
"hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
......@@ -22306,9 +22470,9 @@
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ=="
},
"immer": {
"version": "9.0.14",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz",
"integrity": "sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw=="
"version": "9.0.16",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.16.tgz",
"integrity": "sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ=="
},
"import-fresh": {
"version": "3.3.0",
......@@ -25875,6 +26039,26 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"requires": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"dependencies": {
"react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}
}
},
"react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
......@@ -25997,6 +26181,20 @@
"strip-indent": "^3.0.0"
}
},
"redux": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
"requires": {
"@babel/runtime": "^7.9.2"
}
},
"redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"requires": {}
},
"regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
......@@ -26108,6 +26306,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
},
"reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"resolve": {
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
......@@ -27253,6 +27456,12 @@
"punycode": "^2.1.0"
}
},
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"requires": {}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
......@@ -3,12 +3,14 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.9.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.2.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.4.4",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
......
......@@ -4,8 +4,15 @@ import Checkout from "./containers/Checkout/Checkout";
import ContactData from "./containers/Checkout/ContactData/ContactData";
import Layout from "./components/Layout/Layout";
import Orders from "./containers/Orders/Orders";
import { getIngredients } from "./store/ingredients.slice";
import { useDispatch } from "react-redux";
import { useEffect } from "react";
function App() {
const dispatch = useDispatch()
useEffect(() => {
dispatch(getIngredients())
}, [])
return (
<BrowserRouter>
<Routes>
......
......@@ -16,6 +16,14 @@ class ApiBurger {
console.log(err)
}
}
getIngredients = async() => {
try {
const response = await burgerInstance.get('/ingredients.json')
return response?.data
} catch (err) {
console.log(err)
}
}
}
export const apiBurger = new ApiBurger()
\ No newline at end of file
import React from 'react';
import './BuildControls.css';
import BuildControl from './BuildControl/BuildControl'
import { useSelector } from 'react-redux';
const BuildControls = props => {
const ingredients = useSelector(state => state.ingredients.basket)
return (
<div className='BuildControls'>
<p>Current Price: <strong>{props.price} KZT</strong></p>
{Object.keys(props.ingredients).map(ingType => {
{Object.keys(ingredients).map(ingType => {
return <BuildControl
key={ingType}
type={ingType}
......
import React from 'react';
import { useSelector } from 'react-redux';
import './Burger.css';
import Ingredient from './Ingredient/Ingredient'
// const Burger = (props) => {
//const ingredientKeys = Object.keys(props.ingredients) // ['salad', 'bacon'...]
// props = {ingredients} {ingredients}
const Burger = ({ingredients}) => {
const Burger = () => {
const ingredients = useSelector(state => state.ingredients.basket)
const ingredientKeys = Object.keys(ingredients) // ['salad', 'bacon'...]
let ingList = []
ingredientKeys.forEach(igKey => {
......
......@@ -110,3 +110,10 @@
background: linear-gradient(#bf3813, #c45e38);
margin: 2% auto;
}
.Tomato {
width: 70%;
height: 8%;
background: linear-gradient(to right, red 50%, white 20%, orange 30%);
margin: 2% auto;
}
......@@ -12,16 +12,8 @@ const Ingredient = ({type}) => {
<div className='Seeds2' />
</div>
)
case 'meat':
return <div className='Meat' />
case 'bacon':
return <div className='Bacon' />
case 'cheese':
return <div className='Cheese' />
case 'salad':
return <div className='Salad' />
default:
return null
return <div className={type} />
}
}
......
import React from "react";
import { useSelector } from "react-redux";
import Button from "../../UI/Button/Button";
import './OrderSummary.css'
const OrderSummary = (props) => {
const ingredients = useSelector(state => state.ingredients.basket)
const totalPrice = useSelector(state => state.ingredients.totalPrice)
const ingredientSummary = Object.keys(props.ingredients)
const ingredientSummary = Object.keys(ingredients)
.map(igKey => {
return (
<li key={igKey}>
<span style={{textTransform: 'capitalize'}}>
{igKey}
</span> : {props.ingredients[igKey]}
</span> : {ingredients[igKey]}
</li>
)
})
......@@ -22,7 +25,7 @@ const OrderSummary = (props) => {
<ul>
{ingredientSummary}
</ul>
<p><strong>Total price: </strong>{props.price} KZT</p>
<p><strong>Total price: </strong>{totalPrice} KZT</p>
<p>Continue to checkout</p>
<Button btnType={'Danger'} clicked={props.purchaseCancelled}>CANCEL</Button>
<Button btnType={'Success'} clicked={props.purchaseContinued}>CONTINUE</Button>
......
import React from 'react';
import React, { useEffect } from 'react';
import { useState } from 'react';
import { createSearchParams, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import BuildControls from '../../components/BuildControls/BuildControls';
import Burger from '../../components/Burger/Burger'
import OrderSummary from '../../components/Burger/OrderSummary/OrderSummary';
import Modal from '../../components/UI/Modal/Modal';
import {INGREDIENT_PRICES} from "../../constants/ingredients_prices";
import { addIngredient, removeIngredient } from '../../store/ingredients.slice';
const BurgerBuilder = () => {
const dispatch = useDispatch()
const navigate = useNavigate()
const [ingredients, setIngredients] = useState({
salad: 0,
bacon: 0,
cheese: 0,
meat: 0
})
const [totalPrice, setTotalPrice] = useState(200)
const ingredients = useSelector(state => state.ingredients.basket)
const totalPrice = useSelector(state => state.ingredients.totalPrice)
const [purchasable, setPurchasable] = useState(false)
const [purchasing, setPurchasing] = useState(false)
const addIngredientHandler = (type) => {
const oldCount = ingredients[type]
const updateCount = oldCount + 1
const updatedIngredients = {...ingredients}
updatedIngredients[type] = updateCount
const priceAddition = INGREDIENT_PRICES[type]
const newPrice = totalPrice + priceAddition
setIngredients(updatedIngredients)
setTotalPrice(newPrice)
updatePurchaseState(updatedIngredients)
dispatch(addIngredient(type))
}
const removeIngredientHandler = (type) => {
const oldCount = ingredients[type]
if (oldCount <= 0) return
const updateCount = oldCount - 1
const updatedIngredients = {...ingredients}
updatedIngredients[type] = updateCount
const priceAddition = INGREDIENT_PRICES[type]
const newPrice = totalPrice - priceAddition
setIngredients(updatedIngredients)
setTotalPrice(newPrice)
updatePurchaseState(updatedIngredients)
dispatch(removeIngredient(type))
}
const disabledInfo = {...ingredients}
......@@ -57,7 +35,7 @@ const BurgerBuilder = () => {
disabledInfo[key] = disabledInfo[key] <= 0
}
const updatePurchaseState = (ingredients) => {
const updatePurchaseState = () => {
const sum = Object.keys(ingredients)
.map(igKey => ingredients[igKey])
.reduce((sum, el) => sum + el, 0)
......@@ -65,6 +43,10 @@ const BurgerBuilder = () => {
setPurchasable(sum > 0)
}
useEffect(() => {
updatePurchaseState()
}, [ingredients])
const purchaseHandler = () => {
setPurchasing(true)
}
......@@ -73,9 +55,7 @@ const BurgerBuilder = () => {
}
const purchaseContinueHandler = () => {
const params = new createSearchParams(ingredients)
//salad=0&meat=0&cheese=0&bacon=0
navigate({pathname: '/checkout' , search: params.toString()})
navigate({pathname: '/checkout'})
}
return (
......@@ -85,15 +65,13 @@ const BurgerBuilder = () => {
closed={purchaseCancelHandler}
>
<OrderSummary
ingredients={ingredients}
price={totalPrice}
purchaseCancelled={purchaseCancelHandler}
purchaseContinued={purchaseContinueHandler}
/>
</Modal>
<Burger ingredients={ingredients} />
<Burger />
<BuildControls
ingredients={ingredients}
price={totalPrice}
ingredientAdded={addIngredientHandler}
ingredientRemoved={removeIngredientHandler}
......
import React from "react";
import { useRef } from "react";
import { NavLink, Outlet, useNavigate, useSearchParams } from "react-router-dom";
import { Outlet, useNavigate } from "react-router-dom";
import CheckoutSummary from "../../components/Order/CheckoutSummary/CheckoutSummary";
import { parseSearch } from "../../helper/parseSearch";
import {INGREDIENT_PRICES} from "../../constants/ingredients_prices";
import { useSelector } from "react-redux";
const Checkout = () => {
const navigate = useNavigate()
const [searchParams, setSearchParams] = useSearchParams()
const parsed = parseSearch(searchParams)
const ingredients = useRef(parsed)
const ingredients = useSelector(state => state.ingredients.basket)
const checkoutCancelledHandler = () => {
navigate(-1)
}
const getTotalPrice = (ingredients) => {
return Object.keys(ingredients).reduce((total, ingName) => {
total += INGREDIENT_PRICES[ingName] * ingredients[ingName]
return total
}, 0)
}
const checkoutContinuedHandler = () => {
const price = getTotalPrice(ingredients.current)
navigate('contact-data', {state: {ingredients: ingredients.current, price}})
navigate('contact-data')
}
return (
......
......@@ -4,10 +4,13 @@ import Button from "../../../components/UI/Button/Button";
import {useLocation, useNavigate} from "react-router-dom";
import {apiBurger} from "../../../api/apiBurger";
import Spinner from "../../../components/UI/Spinner/Spinner";
import { useSelector } from 'react-redux';
const ContactData = () => {
const navigate = useNavigate()
const location = useLocation()
const ingredients = useSelector(state => state.ingredients.basket)
const totalPrice = useSelector(state => state.ingredients.totalPrice)
const [loading, setLoading] = useState(false)
const [customer, setCustomer] = useState({
name: '',
......@@ -19,10 +22,9 @@ const ContactData = () => {
const orderHandler = async (event) => {
event.preventDefault()
setLoading(true)
const {ingredients, price} = location.state
const order = {
ingredients: ingredients,
price: price,
price: totalPrice,
customer: {...customer}
}
try {
......
......@@ -3,10 +3,14 @@ import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import {store} from './store/store'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
......
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { apiBurger } from "../api/apiBurger";
const namespace = 'ingredients'
export const getIngredients = createAsyncThunk(
`${namespace}/getIngredients`,
async () => {
return await apiBurger.getIngredients()
}
)
export const ingredientsSlice = createSlice({
name: namespace,
initialState: {
ingredients: [],
basket: {},
totalPrice: 200,
loading: false,
prices: {}
},
reducers: {
addIngredient(state, action) {
try {
state.basket = {
...state.basket,
[action.payload]: state.basket[action.payload] + 1 || 1
}
state.totalPrice += state.prices[action.payload]
} catch (err) {
console.log(err);
}
},
removeIngredient(state, action) {
try {
state.basket = {
...state.basket,
[action.payload]: state.basket[action.payload] > 0
? state.basket[action.payload] - 1
: 0
}
state.totalPrice -= state.prices[action.payload]
} catch (err) {
console.log(err)
}
}
},
extraReducers: builder => {
builder
.addCase(getIngredients.pending, (state) => {
state.loading = true
})
.addCase(getIngredients.rejected, (state) => {
state.loading = false
})
.addCase(getIngredients.fulfilled, (state, action) => {
state.loading = false
state.ingredients = action.payload
action.payload && action.payload.forEach(ing => {
state.basket[ing.name] = 0
})
action.payload && action.payload.forEach(ing => {
state.prices[ing.name] = ing.price
})
})
}
})
export const {
addIngredient,
removeIngredient
} = ingredientsSlice.actions
\ No newline at end of file
import { configureStore } from "@reduxjs/toolkit";
import { ingredientsSlice } from "./ingredients.slice";
export const store = configureStore({
reducer: {
ingredients: ingredientsSlice.reducer
},
devTools: true
})
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment