Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save josecarneiro/e6e9de9baf8fbb0647da52560283fd4f to your computer and use it in GitHub Desktop.
Save josecarneiro/e6e9de9baf8fbb0647da52560283fd4f to your computer and use it in GitHub Desktop.
import React, { useState } from 'react';
import foods from './foods.json';
const MealBox = (props) => {
const [quantity, setQuantity] = useState(1);
const meal = props.meal;
const handleQuantityChange = (event) => {
const { value } = event.target;
setQuantity(Number(value));
};
const handleFormSubmission = (event) => {
event.preventDefault();
props.onAddToTodaysMeals(meal, quantity);
};
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={handleFormSubmission}>
<input
className="form-control col-9"
type="number"
onChange={handleQuantityChange}
value={quantity}
/>
<button className="btn btn-primary col-3">+</button>
</form>
</div>
);
};
const AddNewMealForm = (props) => {
const [name, setName] = useState('');
const [calories, setCalories] = useState(0);
const [image, setImage] = useState('');
const handleFormSubmission = (event) => {
event.preventDefault();
props.onAddNewMeal({ name, calories, image });
};
return (
<form onSubmit={handleFormSubmission}>
<label htmlFor="name-input">Meal Name</label>
<input
id="name-input"
type="text"
placeholder="Name"
name="name"
required
onChange={(event) => setName(event.target.value)}
value={name}
/>
<label htmlFor="calories-input">Number of Calories</label>
<input
id="calories-input"
type="number"
placeholder="Calories"
name="calories"
required
onChange={(event) => setCalories(event.target.valueAsNumber)}
value={calories}
/>
<label htmlFor="image-input">Image</label>
<input
id="image-input"
type="text"
placeholder="Image"
name="image"
required
onChange={(event) => setImage(event.target.value)}
value={image}
/>
<button>Confirm Meal</button>
</form>
);
};
const Search = (props) => (
<input
type="text"
placeholder="Search for any meal..."
value={props.query}
onChange={(event) => props.onQueryChange(event.target.value)}
/>
);
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>
);
};
const App = () => {
const [addNewMealActive, setAddNewMealActive] = useState(false);
const [query, setQuery] = useState('');
const [meals, setMeals] = useState(foods);
const [todaysMeals, setTodaysMeals] = useState([]);
const handleMealAddition = (meal) => {
setMeals([meal, ...meals]);
setAddNewMealActive(false);
};
const handleTodaysMealsAddition = (meal, quantity) => {
const existingMealInList = todaysMeals.find(
(todaysMeal) => todaysMeal.name === meal.name
);
if (existingMealInList) {
const updatedTodaysMeals = todaysMeals.map((todaysMeal) => {
if (todaysMeal === existingMealInList) {
return {
...meal,
quantity: quantity + existingMealInList.quantity,
};
} else {
return todaysMeal;
}
});
setTodaysMeals(updatedTodaysMeals);
} else {
setTodaysMeals([...todaysMeals, { ...meal, quantity }]);
}
};
/*
If there is no search query, all meals should be rendered
If there is a search query, only meals in which name matches query
should be rendered
*/
const filteredMeals = !query
? meals
: meals.filter((meal) =>
meal.name.toLowerCase().includes(query.toLowerCase())
);
return (
<div>
<Search query={query} onQueryChange={(value) => setQuery(value)} />
{(addNewMealActive && (
<AddNewMealForm onAddNewMeal={handleMealAddition} />
)) || (
<button onClick={() => setAddNewMealActive(true)}>Add new meal</button>
)}
{filteredMeals.map((meal) => (
<MealBox
key={meal.name}
meal={meal}
onAddToTodaysMeals={handleTodaysMealsAddition}
/>
))}
<TodaysMealsList meals={todaysMeals} />
</div>
);
};
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment