Created
March 11, 2021 20:37
-
-
Save josecarneiro/f6576b4aadd62b0e1f394203daa1da6a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import meals from './foods.json'; | |
class MealBox extends React.Component { | |
state = { | |
quantity: 1, | |
}; | |
handleQuantityChange = (event) => { | |
const { value } = event.target; | |
// const value = event.target.value; | |
// const value = event.target.valueAsNumber; | |
this.setState({ | |
quantity: Number(value), | |
}); | |
}; | |
handleFormSubmission = (event) => { | |
event.preventDefault(); | |
const { quantity } = this.state; | |
const { meal } = this.props; | |
this.props.onAddToTodaysMeals(meal, quantity); | |
}; | |
render() { | |
const meal = this.props.meal; | |
return ( | |
<div className="media"> | |
<img | |
src={meal.image} | |
className="img-thumbnail mr-3 mw-25 border-0" | |
style={{ maxWidth: '10em' }} | |
alt={meal.name} | |
/> | |
<div className="media-body align-self-center"> | |
<h5 className="mt-0 mb-1">{meal.name}</h5> | |
<small>{meal.calories} cal</small> | |
</div> | |
<form | |
className="row align-self-center" | |
onSubmit={this.handleFormSubmission} | |
> | |
<input | |
className="form-control col-9" | |
type="number" | |
onChange={this.handleQuantityChange} | |
value={this.state.quantity} | |
/> | |
<button className="btn btn-primary col-3">+</button> | |
</form> | |
</div> | |
); | |
} | |
} | |
class AddNewMealForm extends React.Component { | |
state = { | |
name: '', | |
calories: 0, | |
image: '', | |
}; | |
handleInputChange = (event) => { | |
// const { value, name } = event.target; | |
// this.setState({ | |
// [name]: value, | |
// }); | |
const value = event.target.value; | |
const placeholder = event.target.name; | |
this.setState({ | |
[placeholder]: value, | |
}); | |
}; | |
handleFormSubmission = (event) => { | |
event.preventDefault(); | |
// const { name, calories, image } = this.state; | |
// const meal = { name, calories, image }; | |
const meal = { | |
name: this.state.name, | |
calories: this.state.calories, | |
image: this.state.image, | |
}; | |
this.props.onAddNewMeal(meal); | |
}; | |
render() { | |
return ( | |
<form onSubmit={this.handleFormSubmission}> | |
<label htmlFor="name-input">Meal Name</label> | |
<input | |
id="name-input" | |
type="text" | |
placeholder="Name" | |
name="name" | |
required | |
onChange={this.handleInputChange} | |
value={this.state.name} | |
/> | |
<label htmlFor="calories-input">Number of Calories</label> | |
<input | |
id="calories-input" | |
type="number" | |
placeholder="Calories" | |
name="calories" | |
required | |
onChange={this.handleInputChange} | |
value={this.state.calories} | |
/> | |
<label htmlFor="image-input">Image</label> | |
<input | |
id="image-input" | |
type="text" | |
placeholder="Image" | |
name="image" | |
required | |
onChange={this.handleInputChange} | |
value={this.state.image} | |
/> | |
<button>Confirm Meal</button> | |
</form> | |
); | |
} | |
} | |
const Search = (props) => { | |
const handleInputChange = (event) => { | |
props.onQueryChange(event.target.value); | |
}; | |
return ( | |
<input | |
type="text" | |
placeholder="Search for any meal..." | |
value={props.query} | |
onChange={handleInputChange} | |
/> | |
); | |
}; | |
const TodaysMealsList = ({ meals }) => { | |
const total = meals.reduce( | |
(sum, meal) => sum + meal.calories * meal.quantity, | |
0 | |
); | |
return ( | |
<div> | |
<ul> | |
{meals.map((meal) => ( | |
<li> | |
{meal.quantity} - {meal.name} = {meal.calories * meal.quantity}{' '} | |
calories | |
</li> | |
))} | |
</ul> | |
<span>Total: {total} calories</span> | |
</div> | |
); | |
}; | |
class App extends React.Component { | |
state = { | |
addNewMealActive: false, | |
meals: meals, | |
searchQuery: '', | |
todaysMeals: [], | |
}; | |
handleMealAddition = (meal) => { | |
this.setState({ | |
meals: [meal, ...this.state.meals], | |
addNewMealActive: false, | |
}); | |
}; | |
openAddNewMealForm = () => { | |
this.setState({ | |
addNewMealActive: true, | |
}); | |
}; | |
handleQueryChange = (query) => { | |
this.setState({ | |
searchQuery: query, | |
}); | |
}; | |
handleTodaysMealsAddition = (meal, quantity) => { | |
const { todaysMeals } = this.state; | |
const existingMealInList = todaysMeals.find( | |
(todaysMeal) => todaysMeal.name === meal.name | |
); | |
if (existingMealInList) { | |
const replacerMeal = { | |
...meal, | |
quantity: quantity + existingMealInList.quantity, | |
}; | |
const cloneTodaysMeals = [...todaysMeals]; | |
const indexOfExistentMeal = todaysMeals.indexOf(existingMealInList); | |
cloneTodaysMeals.splice(indexOfExistentMeal, 1, replacerMeal); | |
this.setState({ | |
todaysMeals: cloneTodaysMeals, | |
}); | |
} else { | |
this.setState({ | |
todaysMeals: [...this.state.todaysMeals, { ...meal, quantity }], | |
}); | |
} | |
}; | |
render() { | |
const filteredMeals = this.state.meals.filter((meal) => { | |
if (!this.state.searchQuery) { | |
return true; | |
} else { | |
return meal.name | |
.toLowerCase() | |
.includes(this.state.searchQuery.toLowerCase()); | |
} | |
}); | |
return ( | |
<div className="App"> | |
<Search | |
query={this.state.searchQuery} | |
onQueryChange={this.handleQueryChange} | |
/> | |
{(this.state.addNewMealActive && ( | |
<AddNewMealForm onAddNewMeal={this.handleMealAddition} /> | |
)) || <button onClick={this.openAddNewMealForm}>Add new meal</button>} | |
{filteredMeals.map((meal) => ( | |
<MealBox | |
key={meal.name} | |
meal={meal} | |
onAddToTodaysMeals={this.handleTodaysMealsAddition} | |
/> | |
))} | |
<TodaysMealsList meals={this.state.todaysMeals} /> | |
</div> | |
); | |
} | |
} | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment