Commit 4820e13f authored by Pavel Mishakov's avatar Pavel Mishakov

finished lesson 69

parent 63ecdad7
...@@ -7,6 +7,8 @@ import Orders from "./containers/Orders/Orders"; ...@@ -7,6 +7,8 @@ import Orders from "./containers/Orders/Orders";
import { getIngredients } from "./store/ingredients.slice"; import { getIngredients } from "./store/ingredients.slice";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { useEffect } from "react"; import { useEffect } from "react";
import AddIngredient from "./containers/AddIngredient/AddIngredient";
import Ingredients from "./containers/Ingredients/Ingredients";
function App() { function App() {
const dispatch = useDispatch() const dispatch = useDispatch()
...@@ -22,6 +24,8 @@ function App() { ...@@ -22,6 +24,8 @@ function App() {
<Route path='contact-data' element={<ContactData />} /> <Route path='contact-data' element={<ContactData />} />
</Route> </Route>
<Route path={'/orders'} element={<Orders />} /> <Route path={'/orders'} element={<Orders />} />
<Route path={'/add-ingredient'} element={<AddIngredient />} />
<Route path={'/ingredients'} element={<Ingredients />} />
<Route path='*' element={<div>NOT FOUND</div>} /> <Route path='*' element={<div>NOT FOUND</div>} />
</Route> </Route>
</Routes> </Routes>
......
...@@ -16,7 +16,7 @@ class ApiBurger { ...@@ -16,7 +16,7 @@ class ApiBurger {
console.log(err) console.log(err)
} }
} }
getIngredients = async() => { getIngredients = async () => {
try { try {
const response = await burgerInstance.get('/ingredients.json') const response = await burgerInstance.get('/ingredients.json')
return response?.data return response?.data
...@@ -24,6 +24,13 @@ class ApiBurger { ...@@ -24,6 +24,13 @@ class ApiBurger {
console.log(err) console.log(err)
} }
} }
addIngredient = async (ingredient) => {
try {
await burgerInstance.post('/ingredients.json', ingredient)
} catch (err) {
console.log(err)
}
}
} }
export const apiBurger = new ApiBurger() export const apiBurger = new ApiBurger()
\ No newline at end of file
...@@ -7,12 +7,17 @@ import Ingredient from './Ingredient/Ingredient' ...@@ -7,12 +7,17 @@ import Ingredient from './Ingredient/Ingredient'
// props = {ingredients} {ingredients} // props = {ingredients} {ingredients}
const Burger = () => { const Burger = () => {
const ingredients = useSelector(state => state.ingredients.basket) const ingredients = useSelector(state => state.ingredients.basket)
const styles = useSelector(state => state.ingredients.styles)
const ingredientKeys = Object.keys(ingredients) // ['salad', 'bacon'...] const ingredientKeys = Object.keys(ingredients) // ['salad', 'bacon'...]
let ingList = [] let ingList = []
ingredientKeys.forEach(igKey => { ingredientKeys.forEach(igKey => {
let amount = ingredients[igKey] let amount = ingredients[igKey]
for (let i = 0; i < amount; i++) { for (let i = 0; i < amount; i++) {
ingList.push(<Ingredient key={igKey + i} type={igKey} />) ingList.push(<Ingredient
key={igKey + i}
type={igKey}
style={styles[igKey]} />)
} }
}) })
......
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
box-shadow: inset 1px 3px #c9c9c9; box-shadow: inset 1px 3px #c9c9c9;
} }
.Meat { /* .Meat {
width: 80%; width: 80%;
height: 8%; height: 8%;
background: linear-gradient(#7f3608, #702e05); background: linear-gradient(#7f3608, #702e05);
...@@ -116,4 +116,4 @@ ...@@ -116,4 +116,4 @@
height: 8%; height: 8%;
background: linear-gradient(to right, red 50%, white 20%, orange 30%); background: linear-gradient(to right, red 50%, white 20%, orange 30%);
margin: 2% auto; margin: 2% auto;
} } */
import React from 'react'; import React from 'react';
import './Ingredient.css'; import './Ingredient.css';
const Ingredient = ({type}) => { const Ingredient = ({type, style}) => {
switch (type) { switch (type) {
case 'bread-bottom': case 'bread-bottom':
return <div className='BreadBottom' /> return <div className='BreadBottom' />
...@@ -13,7 +13,7 @@ const Ingredient = ({type}) => { ...@@ -13,7 +13,7 @@ const Ingredient = ({type}) => {
</div> </div>
) )
default: default:
return <div className={type} /> return <div className={type} style={style} />
} }
} }
......
...@@ -8,6 +8,8 @@ const NavigationItems = () => { ...@@ -8,6 +8,8 @@ const NavigationItems = () => {
<ul className={'NavigationItems'}> <ul className={'NavigationItems'}>
<NavigationItem to={'/'} end>Burger Builder</NavigationItem> <NavigationItem to={'/'} end>Burger Builder</NavigationItem>
<NavigationItem to={'/orders'} end>Orders</NavigationItem> <NavigationItem to={'/orders'} end>Orders</NavigationItem>
<NavigationItem to={'/add-ingredient'} end>Add ingredient</NavigationItem>
<NavigationItem to={'/ingredients'} end>Ingredients</NavigationItem>
</ul> </ul>
) )
} }
......
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { addNewIngredient } from "../../store/ingredients.slice";
const AddIngredient = () => {
const [inputValues, setInputValues] = useState({
name: '',
price: ''
})
const [style, setStyle] = useState({})
const dispatch = useDispatch()
const navigate = useNavigate()
const inputHandler = (e) => {
setInputValues(prevState => {
return {...prevState, [e.target.name]: e.target.value}
})
}
const inputStyleHandler = (e) => {
setStyle(prevState => {
return {...prevState, [e.target.name]: e.target.value}
})
}
const submit = (e) => {
e.preventDefault()
const styleObj = {}
Object.keys(style).forEach((key) => {
if (style[key].trim() !== '') {
styleObj[key] = style[key]
}
})
dispatch(addNewIngredient({
name: inputValues.name,
price: inputValues.price,
style: styleObj
}))
navigate('/')
}
return (
<div>
<form onSubmit={submit}>
<input type={'text'} onChange={inputHandler} name={'name'} placeholder={'Name'} required/>
<input type={'number'} onChange={inputHandler} name={'price'} placeholder={'Price'} required/>
<div>
<input type={'text'} onChange={inputStyleHandler} name={'width'} placeholder={'Width'}/>
<input type={'text'} onChange={inputStyleHandler} name={'height'} placeholder={'Height'}/>
<input type={'text'} onChange={inputStyleHandler} name={'background'} placeholder={'Background'}/>
<input type={'text'} onChange={inputStyleHandler} name={'margin'} placeholder={'Margin'}/>
<input type={'text'} onChange={inputStyleHandler} name={'borderRadius'} placeholder={'Border-radius'}/>
</div>
<button>Add</button>
</form>
</div>
)
}
export default AddIngredient
\ No newline at end of file
import React from "react";
import { useSelector } from "react-redux";
const Ingredients = () => {
const ingredients = useSelector(state => state.ingredients.ingredients)
return (
<div>
{Object.keys(ingredients).map((key) => {
return <div key={key}>
<p>Name: {ingredients[key].name}</p>
<p>Price {ingredients[key].price}</p>
<p>{JSON.stringify(ingredients[key].style)}</p>
<br/>
</div>
})}
</div>
)
}
export default Ingredients
\ No newline at end of file
...@@ -5,24 +5,16 @@ import OrderItem from "../../components/Order/OrderItem/OrderItem"; ...@@ -5,24 +5,16 @@ import OrderItem from "../../components/Order/OrderItem/OrderItem";
import WithErrorHandler from '../../hoc/WithErrorHandler'; import WithErrorHandler from '../../hoc/WithErrorHandler';
import { burgerInstance } from '../../api/instances'; import { burgerInstance } from '../../api/instances';
import ErrorBoundary from '../../components/ErrorBoundary/ErrorBoundary'; import ErrorBoundary from '../../components/ErrorBoundary/ErrorBoundary';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { getOrders } from '../../store/orders.slice';
const Orders = () => { const Orders = () => {
const [orders, setOrders] = useState({}) const dispatch = useDispatch()
const [loading, setLoading] = useState(false); const {orders, loading} = useSelector(state => state.orders, shallowEqual)
const getOrders = async () => {
setLoading(true)
try {
const response = await apiBurger.getOrders()
setOrders(response || {})
} finally {
setLoading(false)
}
}
useEffect(() => { useEffect(() => {
getOrders() dispatch(getOrders())
}, []) }, [])
return ( return (
<> <>
......
...@@ -10,14 +10,22 @@ export const getIngredients = createAsyncThunk( ...@@ -10,14 +10,22 @@ export const getIngredients = createAsyncThunk(
} }
) )
export const addNewIngredient = createAsyncThunk(
`${namespace}/addIngredient`,
async (ingredient) => {
await apiBurger.addIngredient(ingredient)
}
)
export const ingredientsSlice = createSlice({ export const ingredientsSlice = createSlice({
name: namespace, name: namespace,
initialState: { initialState: {
ingredients: [], ingredients: {},
basket: {}, basket: {},
totalPrice: 200, totalPrice: 200,
loading: false, loading: false,
prices: {} prices: {},
styles: {}
}, },
reducers: { reducers: {
addIngredient(state, action) { addIngredient(state, action) {
...@@ -26,7 +34,7 @@ export const ingredientsSlice = createSlice({ ...@@ -26,7 +34,7 @@ export const ingredientsSlice = createSlice({
...state.basket, ...state.basket,
[action.payload]: state.basket[action.payload] + 1 || 1 [action.payload]: state.basket[action.payload] + 1 || 1
} }
state.totalPrice += state.prices[action.payload] state.totalPrice += parseInt(state.prices[action.payload])
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }
...@@ -56,12 +64,24 @@ export const ingredientsSlice = createSlice({ ...@@ -56,12 +64,24 @@ export const ingredientsSlice = createSlice({
.addCase(getIngredients.fulfilled, (state, action) => { .addCase(getIngredients.fulfilled, (state, action) => {
state.loading = false state.loading = false
state.ingredients = action.payload state.ingredients = action.payload
action.payload && action.payload.forEach(ing => { action.payload && Object.keys(action.payload).forEach(key => {
state.basket[ing.name] = 0 state.basket[action.payload[key].name] = 0
}) })
action.payload && action.payload.forEach(ing => { action.payload && Object.keys(action.payload).forEach(key => {
state.prices[ing.name] = ing.price state.prices[action.payload[key].name] = action.payload[key].price
}) })
action.payload && Object.keys(action.payload).forEach(key => {
state.styles[action.payload[key].name] = action.payload[key].style
})
})
.addCase(addNewIngredient.pending, (state) => {
state.loading = true
})
.addCase(addNewIngredient.rejected, (state) => {
state.loading = false
})
.addCase(addNewIngredient.fulfilled, (state) => {
state.loading = false
}) })
} }
}) })
......
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { apiBurger } from "../api/apiBurger";
const namespace = 'orders'
export const getOrders = createAsyncThunk(
`${namespace}/getOrders`,
async () => {
return await apiBurger.getOrders()
}
)
export const ordersSlice = createSlice({
name: namespace,
initialState: {
orders: [],
loading: false
},
extraReducers: builder => {
builder
.addCase(getOrders.pending, (state) => {
state.loading = true
})
.addCase(getOrders.rejected, (state) => {
state.loading = false
})
.addCase(getOrders.fulfilled, (state, action) => {
state.loading = false
state.orders = action.payload
})
}
})
import { configureStore } from "@reduxjs/toolkit"; import { configureStore } from "@reduxjs/toolkit";
import { ingredientsSlice } from "./ingredients.slice"; import { ingredientsSlice } from "./ingredients.slice";
import { ordersSlice } from "./orders.slice";
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
ingredients: ingredientsSlice.reducer ingredients: ingredientsSlice.reducer,
orders: ordersSlice.reducer
}, },
devTools: true 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