Commit e2f4559a authored by Pavel Mishakov's avatar Pavel Mishakov

task 1 done

parent ed3827d9
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
"name": "classwork", "name": "classwork",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^2.8.2",
"axios": "^1.9.0", "axios": "^1.9.0",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-redux": "^9.2.0",
"react-router": "^7.6.1", "react-router": "^7.6.1",
"react-router-dom": "^7.6.1" "react-router-dom": "^7.6.1"
}, },
...@@ -1060,6 +1062,32 @@ ...@@ -1060,6 +1062,32 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@reduxjs/toolkit": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz",
"integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==",
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.0.0",
"@standard-schema/utils": "^0.3.0",
"immer": "^10.0.3",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
"reselect": "^5.1.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@rolldown/pluginutils": { "node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.9", "version": "1.0.0-beta.9",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz",
...@@ -1347,6 +1375,18 @@ ...@@ -1347,6 +1375,18 @@
"win32" "win32"
] ]
}, },
"node_modules/@standard-schema/spec": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
"license": "MIT"
},
"node_modules/@standard-schema/utils": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
"integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
"license": "MIT"
},
"node_modules/@types/babel__core": { "node_modules/@types/babel__core": {
"version": "7.20.5", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
...@@ -1410,7 +1450,7 @@ ...@@ -1410,7 +1450,7 @@
"version": "19.1.6", "version": "19.1.6",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz",
"integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==", "integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
...@@ -1426,6 +1466,12 @@ ...@@ -1426,6 +1466,12 @@
"@types/react": "^19.0.0" "@types/react": "^19.0.0"
} }
}, },
"node_modules/@types/use-sync-external-store": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
"integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.33.1", "version": "8.33.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz",
...@@ -1996,7 +2042,7 @@ ...@@ -1996,7 +2042,7 @@
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/debug": { "node_modules/debug": {
...@@ -2677,6 +2723,16 @@ ...@@ -2677,6 +2723,16 @@
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
...@@ -3175,6 +3231,29 @@ ...@@ -3175,6 +3231,29 @@
"react": "^19.1.0" "react": "^19.1.0"
} }
}, },
"node_modules/react-redux": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
"license": "MIT",
"dependencies": {
"@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0"
},
"peerDependencies": {
"@types/react": "^18.2.25 || ^19",
"react": "^18.0 || ^19",
"redux": "^5.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.17.0", "version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
...@@ -3223,6 +3302,27 @@ ...@@ -3223,6 +3302,27 @@
"react-dom": ">=18" "react-dom": ">=18"
} }
}, },
"node_modules/redux": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT"
},
"node_modules/redux-thunk": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
"license": "MIT",
"peerDependencies": {
"redux": "^5.0.0"
}
},
"node_modules/reselect": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
"license": "MIT"
},
"node_modules/resolve-from": { "node_modules/resolve-from": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
...@@ -3551,6 +3651,15 @@ ...@@ -3551,6 +3651,15 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/use-sync-external-store": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "6.3.5", "version": "6.3.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "^2.8.2",
"axios": "^1.9.0", "axios": "^1.9.0",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-redux": "^9.2.0",
"react-router": "^7.6.1", "react-router": "^7.6.1",
"react-router-dom": "^7.6.1" "react-router-dom": "^7.6.1"
}, },
......
import { useAppDispatch } from '../../../hooks/useAppDispatch'
import { addIngredient, removeIngredient } from '../../../stores/newStore/burgerSlice'
import { TIngredientNames } from '../../../types/TIngredientNames' import { TIngredientNames } from '../../../types/TIngredientNames'
import styles from './BuildControl.module.css' import styles from './BuildControl.module.css'
import { MouseEventHandler } from 'react' // import { MouseEventHandler } from 'react'
type Props = { type Props = {
type: TIngredientNames type: TIngredientNames
added: MouseEventHandler<HTMLButtonElement> // added: MouseEventHandler<HTMLButtonElement>
removed: MouseEventHandler<HTMLButtonElement> // removed: MouseEventHandler<HTMLButtonElement>
disabled?: boolean disabled?: boolean
} }
const BuildControl = ({type, added, removed, disabled}: Props) => { const BuildControl = ({type, disabled}: Props) => {
const dispatch = useAppDispatch()
const add = (type: TIngredientNames) => {
dispatch(addIngredient(type))
}
const remove = (type: TIngredientNames) => {
dispatch(removeIngredient(type))
}
return ( return (
<div className={styles.BuildControl}> <div className={styles.BuildControl}>
<div className={styles.Label}>{type}</div> <div className={styles.Label}>{type}</div>
<button disabled={!disabled} onClick={removed} className={styles.Less}>Less</button> <button disabled={!disabled} onClick={() => remove(type)} className={styles.Less}>Less</button>
<button onClick={added} className={styles.More}>More</button> <button onClick={() => add(type)} className={styles.More}>More</button>
</div> </div>
) )
} }
......
import { TIngredients } from '../../types/TIngredients' // import { TIngredients } from '../../types/TIngredients'
import styles from './BuildControls.module.css' import styles from './BuildControls.module.css'
import BuildControl from './BuildControl/BuildControl' import BuildControl from './BuildControl/BuildControl'
import { TIngredientNames } from '../../types/TIngredientNames' // import { TIngredientNames } from '../../types/TIngredientNames'
import { EIngredientPrices } from '../../enums/EIngredientPrices' import { EIngredientPrices } from '../../enums/EIngredientPrices'
import Modal from '../UI/Modal/Modal' import Modal from '../UI/Modal/Modal'
import { useRef } from 'react' import { useRef } from 'react'
import OrderSummary from '../OrderSummary/OrderSummary' import OrderSummary from '../OrderSummary/OrderSummary'
import { useAppSelector } from '../../hooks/useAppSelector'
type Props = { // type Props = {
ingredients: TIngredients // ingredients: TIngredients
price: number // price: number
ingredientAdded: (type: TIngredientNames) => void // ingredientAdded: (type: TIngredientNames) => void
ingredientRemoved: (type: TIngredientNames) => void // ingredientRemoved: (type: TIngredientNames) => void
} // }
const BuildControls = ({ingredients, price, ingredientAdded, ingredientRemoved}: Props) => { const BuildControls = () => {
const modalRef = useRef<HTMLDialogElement>(null) const modalRef = useRef<HTMLDialogElement>(null)
const {ingredients, totalPrice} = useAppSelector(state => state.burger)
const showModalHandler = () => { const showModalHandler = () => {
if(!modalRef.current) return if(!modalRef.current) return
modalRef.current.showModal() modalRef.current.showModal()
...@@ -24,20 +25,20 @@ const BuildControls = ({ingredients, price, ingredientAdded, ingredientRemoved}: ...@@ -24,20 +25,20 @@ const BuildControls = ({ingredients, price, ingredientAdded, ingredientRemoved}:
return ( return (
<div className={styles.BuildControls}> <div className={styles.BuildControls}>
<p>Current Price: <strong>{price}</strong></p> <p>Current Price: <strong>{totalPrice}</strong></p>
{Object.keys(ingredients) {Object.keys(ingredients)
.map(ingType => { .map(ingType => {
return <BuildControl return <BuildControl
key={ingType} key={ingType}
type={ingType as keyof typeof ingredients} type={ingType as keyof typeof ingredients}
added={() => ingredientAdded(ingType as keyof typeof ingredients)} // added={() => ingredientAdded(ingType as keyof typeof ingredients)}
removed={() => ingredientRemoved(ingType as keyof typeof ingredients)} // removed={() => ingredientRemoved(ingType as keyof typeof ingredients)}
disabled={!!ingredients[ingType as keyof typeof ingredients]} disabled={!!ingredients[ingType as keyof typeof ingredients]}
/> />
}) })
} }
<button <button
disabled={price <= EIngredientPrices.bread} disabled={totalPrice <= EIngredientPrices.bread}
className={styles.OrderButton} className={styles.OrderButton}
onClick={showModalHandler} onClick={showModalHandler}
> >
...@@ -45,8 +46,8 @@ const BuildControls = ({ingredients, price, ingredientAdded, ingredientRemoved}: ...@@ -45,8 +46,8 @@ const BuildControls = ({ingredients, price, ingredientAdded, ingredientRemoved}:
</button> </button>
<Modal ref={modalRef}> <Modal ref={modalRef}>
<OrderSummary <OrderSummary
ingredients={ingredients} // ingredients={ingredients}
price={price} // price={totalPrice}
/> />
</Modal> </Modal>
</div> </div>
......
import { TIngredients } from "../../types/TIngredients" // import { TIngredients } from "../../types/TIngredients"
import styles from './Burger.module.css' import styles from './Burger.module.css'
import Ingredient from "../Ingredient/Ingredient" import Ingredient from "../Ingredient/Ingredient"
import { useAppSelector } from "../../hooks/useAppSelector"
type Props = { // type Props = {
ingredients: TIngredients // ingredients: TIngredients
} // }
const Burger = ({ingredients}: Props) => { const Burger = () => {
const ingList: React.ReactNode[] = [] const ingList: React.ReactNode[] = []
const {ingredients} = useAppSelector(state => state.burger)
Object.keys(ingredients) Object.keys(ingredients)
.forEach((igKey: string) => { .forEach((igKey: string) => {
let amount: number = ingredients[igKey as keyof typeof ingredients] let amount: number = ingredients[igKey as keyof typeof ingredients]
......
'use client' // import { TIngredients } from "../../types/TIngredients"
// import { useState } from "react"
import { TIngredients } from "../../types/TIngredients"
import { useState } from "react"
import Burger from "../Burger/Burger" import Burger from "../Burger/Burger"
import BuildControls from "../BuildControls/BuildControls" import BuildControls from "../BuildControls/BuildControls"
import { TIngredientNames } from "../../types/TIngredientNames" // import { TIngredientNames } from "../../types/TIngredientNames"
import { EIngredientPrices } from "../../enums/EIngredientPrices" // import { useReducer } from "react"
// import reducer, { initialState } from "../../stores/oldStore/reducer"
// import { addIngredient, removeIngredient } from "../../stores/newStore/burgerReducer"
// import { useAppDispatch } from "../../hooks/useAppDispatch"
// import { useAppSelector } from "../../hooks/useAppSelector"
// import { addIngredient, removeIngredient } from "../../stores/oldStore/actions"
// import { EIngredientPrices } from "../../enums/EIngredientPrices"
const BurgerBuilder = () => { const BurgerBuilder = () => {
const [totalPrice, setTotalPrice] = useState<number>(EIngredientPrices.bread) // const [state, dispatch] = useReducer(reducer, initialState)
const [ingredients, setIngredients] = useState<TIngredients>({ // const {ingredients, totalPrice} = state
salad: 0, // const [totalPrice, setTotalPrice] = useState<number>(EIngredientPrices.bread)
meat: 0, // const [ingredients, setIngredients] = useState<TIngredients>({
bacon: 0, // salad: 0,
cheese: 0 // meat: 0,
}) // bacon: 0,
// cheese: 0
// })
// const {ingredients, totalPrice} = useAppSelector(state => state.burger)
// const dispatch = useAppDispatch()
const addIngredientHandler = (type: TIngredientNames) => { // const addIngredientHandler = (type: TIngredientNames) => {
setIngredients(prevState => ({...prevState, [type]: prevState[type] + 1})) // dispatch(addIngredient(type))
setTotalPrice(prevState => prevState + EIngredientPrices[type]) // setIngredients(prevState => ({...prevState, [type]: prevState[type] + 1}))
} // setTotalPrice(prevState => prevState + EIngredientPrices[type])
// }
const removeIngredientHandler = (type: TIngredientNames) => { // const removeIngredientHandler = (type: TIngredientNames) => {
setIngredients(prevState => ({...prevState, [type]: Math.max(0, prevState[type] - 1)})) // dispatch(removeIngredient(type))
setTotalPrice(prevState => prevState - EIngredientPrices[type]) // setIngredients(prevState => ({...prevState, [type]: Math.max(0, prevState[type] - 1)}))
} // setTotalPrice(prevState => prevState - EIngredientPrices[type])
// }
return ( return (
<> <>
<Burger ingredients={ingredients} /> <Burger
// ingredients={ingredients}
/>
<BuildControls <BuildControls
ingredients={ingredients} // ingredients={ingredients}
price={totalPrice} // price={totalPrice}
ingredientAdded={addIngredientHandler} // ingredientAdded={addIngredientHandler}
ingredientRemoved={removeIngredientHandler} // ingredientRemoved={removeIngredientHandler}
/> />
</> </>
) )
......
import { TIngredients } from "../../types/TIngredients" // import { TIngredients } from "../../types/TIngredients"
import styles from './OrderSummary.module.css' import styles from './OrderSummary.module.css'
import Button from "../UI/Button/Button" import Button from "../UI/Button/Button"
import { FormEvent } from "react" import { FormEvent } from "react"
import { useNavigate, useSearchParams } from "react-router-dom" import { useNavigate, useSearchParams } from "react-router-dom"
import { useAppSelector } from '../../hooks/useAppSelector'
type Props = { // type Props = {
ingredients: TIngredients // ingredients: TIngredients
price: number // price: number
} // }
const OrderSummary = ({ ingredients, price }: Props) => { const OrderSummary = () => {
const [searchParams, setSearchParams] = useSearchParams() const [searchParams, setSearchParams] = useSearchParams()
const navigate = useNavigate() const navigate = useNavigate()
const {ingredients, totalPrice} = useAppSelector(state => state.burger)
const ingredientSummary = Object.keys(ingredients).map((igKey) => { const ingredientSummary = Object.keys(ingredients).map((igKey) => {
return ( return (
<li key={igKey}> <li key={igKey}>
...@@ -42,7 +44,7 @@ const OrderSummary = ({ ingredients, price }: Props) => { ...@@ -42,7 +44,7 @@ const OrderSummary = ({ ingredients, price }: Props) => {
<p>A delicious burger with the following ingredients:</p> <p>A delicious burger with the following ingredients:</p>
<ul className={styles.list}>{ingredientSummary}</ul> <ul className={styles.list}>{ingredientSummary}</ul>
<p> <p>
<strong>Total Price: {price}</strong> <strong>Total Price: {totalPrice}</strong>
</p> </p>
<p>Continue to checkout?</p> <p>Continue to checkout?</p>
<div className={styles.formBlock}> <div className={styles.formBlock}>
......
import { useDispatch } from "react-redux";
import { AppDispatch } from "../stores/newStore/store";
export const useAppDispatch: () => AppDispatch = useDispatch
\ No newline at end of file
import { TypedUseSelectorHook, useSelector } from "react-redux";
import { RootState } from "../stores/newStore/store";
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
\ No newline at end of file
...@@ -9,6 +9,8 @@ import Layout from './components/layouts/Layout/Layout.tsx' ...@@ -9,6 +9,8 @@ import Layout from './components/layouts/Layout/Layout.tsx'
import { fetchOrders } from './components/Orders/Orders.tsx' import { fetchOrders } from './components/Orders/Orders.tsx'
import { lazy, Suspense } from 'react' import { lazy, Suspense } from 'react'
import Spinner from './components/UI/Spinner/Spinner.tsx' import Spinner from './components/UI/Spinner/Spinner.tsx'
import { Provider } from 'react-redux'
import store from './stores/newStore/store.ts'
const Orders = lazy(() => import('./components/Orders/Orders.tsx')) const Orders = lazy(() => import('./components/Orders/Orders.tsx'))
const router = createBrowserRouter([ const router = createBrowserRouter([
...@@ -48,7 +50,9 @@ const router = createBrowserRouter([ ...@@ -48,7 +50,9 @@ const router = createBrowserRouter([
]) ])
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<RouterProvider router={router} />, <Provider store={store}>
<RouterProvider router={router} />
</Provider>
) )
......
import { createSlice, PayloadAction } from "@reduxjs/toolkit"
import { EIngredientPrices } from "../../enums/EIngredientPrices"
import { TIngredients } from "../../types/TIngredients"
import { TIngredientNames } from "../../types/TIngredientNames"
export type State = {
ingredients: TIngredients
totalPrice: number
}
const namespace = 'burger'
const initialState: State = {
ingredients: {
bacon: 0,
cheese: 0,
meat: 0,
salad: 0
},
totalPrice: EIngredientPrices.bread
}
const burgerSlice = createSlice({
name: namespace,
initialState,
reducers: {
addIngredient: (state, action: PayloadAction<TIngredientNames>) => {
state.ingredients[action.payload] = state.ingredients[action.payload] + 1
state.totalPrice += EIngredientPrices[action.payload]
},
removeIngredient: (state, action: PayloadAction<TIngredientNames>) => {
state.ingredients[action.payload] = state.ingredients[action.payload] - 1
state.totalPrice -= EIngredientPrices[action.payload]
},
}
})
export const {
addIngredient,
removeIngredient,
} = burgerSlice.actions
export default burgerSlice.reducer
\ No newline at end of file
import { configureStore } from "@reduxjs/toolkit";
import burgerReducer from './burgerSlice'
const store = configureStore({
reducer: {
burger: burgerReducer
}
})
export type RootState = ReturnType<typeof store.getState>
export type AppStore = typeof store
export type AppDispatch = typeof store.dispatch
export default store
\ No newline at end of file
import { TIngredientNames } from "../../types/TIngredientNames";
export type AddIngredient = {type: 'ADD_INGREDIENT', payload: TIngredientNames};
export type RemoveIngredient = {type: 'REMOVE_INGREDIENT', payload: TIngredientNames;};
export type Action = AddIngredient | RemoveIngredient;
export const addIngredient = (payload: TIngredientNames): AddIngredient => ({type: 'ADD_INGREDIENT', payload})
export const removeIngredient = (payload: TIngredientNames): RemoveIngredient => ({type: 'REMOVE_INGREDIENT', payload})
import { EIngredientPrices } from "../../enums/EIngredientPrices"
import { TIngredients } from "../../types/TIngredients"
import { Action } from "./actions"
export type State = {
ingredients: TIngredients
totalPrice: number
}
export const initialState: State = {
ingredients: {
bacon: 0,
cheese: 0,
meat: 0,
salad: 0,
},
totalPrice: EIngredientPrices.bread,
}
const reducer = (state = initialState, action: Action): State => {
switch(action.type) {
case 'ADD_INGREDIENT':
return {
...state,
ingredients: {
...state.ingredients, [action.payload]: state.ingredients[action.payload] + 1
},
totalPrice: state.totalPrice + EIngredientPrices[action.payload]
}
case 'REMOVE_INGREDIENT':
return {
...state,
ingredients: {
...state.ingredients, [action.payload]: state.ingredients[action.payload] - 1
},
totalPrice: state.totalPrice - EIngredientPrices[action.payload]
}
default:
return state
}
}
export default reducer
\ No newline at end of file
export const ADD_INGREDIENT = 'ADD_INGREDIENT';
export const REMOVE_INGREDIENT = 'REMOVE_INGREDIENT';
\ 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