mirror of
https://github.com/rjNemo/meal_planner
synced 2026-06-12 13:26:45 +00:00
SearchBar & Page
This commit is contained in:
parent
6a288f1246
commit
a1462ed9e0
10 changed files with 113 additions and 87 deletions
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
Free meal planner for cooks short on ideas! (like me …)
|
Free meal planner for cooks short on ideas! (like me …)
|
||||||
|
|
||||||
|
[Available on](https://chefs-meal-planner.onrender.com/)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Random meal suggestion
|
- Random meal suggestion
|
||||||
|
|
@ -52,6 +54,7 @@ Free meal planner for cooks short on ideas! (like me …)
|
||||||
- Notation system: know what are the most loved meals
|
- Notation system: know what are the most loved meals
|
||||||
- Suggestions based on what your personal taste
|
- Suggestions based on what your personal taste
|
||||||
- Recipes in Video
|
- Recipes in Video
|
||||||
|
- Get a full menu (Starter, Main, Dessert + Cocktail)
|
||||||
|
|
||||||
## Supports
|
## Supports
|
||||||
|
|
||||||
|
|
@ -68,7 +71,7 @@ Free meal planner for cooks short on ideas! (like me …)
|
||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
|
|
||||||
### Features in V.1
|
### Features in V.0.1
|
||||||
|
|
||||||
- WebApp
|
- WebApp
|
||||||
- Random meal suggestion
|
- Random meal suggestion
|
||||||
|
|
@ -78,3 +81,4 @@ Free meal planner for cooks short on ideas! (like me …)
|
||||||
## TO DO
|
## TO DO
|
||||||
|
|
||||||
- put a preloader
|
- put a preloader
|
||||||
|
- change favicon
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="description" content="Chef's Meal Planner" />
|
<meta name="description" content="Chef's | Meal Planner" />
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
|
|
||||||
|
|
@ -25,15 +25,15 @@
|
||||||
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
href="https://fonts.googleapis.com/icon?family=Material+Icons"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<title>Chef's Meal Planner</title>
|
<title>Chef's | Meal Planner</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<!-- <script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
var elems = document.querySelectorAll(".sidenav");
|
var elems = document.querySelectorAll(".sidenav");
|
||||||
var instances = M.Sidenav.init(elems, options);
|
var instances = M.Sidenav.init(elems, options);
|
||||||
});
|
});
|
||||||
</script>
|
</script> -->
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"sizes": "512x512"
|
"sizes": "512x512"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": ".",
|
"start_url": "/",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"theme_color": "#000000",
|
"theme_color": "#000000",
|
||||||
"background_color": "#ffffff"
|
"background_color": "#ffffff"
|
||||||
|
|
|
||||||
76
src/App.js
76
src/App.js
|
|
@ -15,6 +15,7 @@ const App = () => {
|
||||||
// State Hooks
|
// State Hooks
|
||||||
const [searchString, setSearchString] = useState("");
|
const [searchString, setSearchString] = useState("");
|
||||||
const [categories, setCategories] = useState({ categories: [] });
|
const [categories, setCategories] = useState({ categories: [] });
|
||||||
|
const [searchResults, setSearchResults] = useState({ meals: [] });
|
||||||
// const [isLoading, setIsLoading] = useState(true); For Preloader
|
// const [isLoading, setIsLoading] = useState(true); For Preloader
|
||||||
// Default meal object. TODO: Find a better alternative …
|
// Default meal object. TODO: Find a better alternative …
|
||||||
const mealDef = {
|
const mealDef = {
|
||||||
|
|
@ -87,8 +88,11 @@ const App = () => {
|
||||||
return `${ROOT}${option}.php?c=${keyword}`;
|
return `${ROOT}${option}.php?c=${keyword}`;
|
||||||
} else if (option === "lookup") {
|
} else if (option === "lookup") {
|
||||||
return `${ROOT}${option}.php?i=${keyword}`;
|
return `${ROOT}${option}.php?i=${keyword}`;
|
||||||
|
} else if (option === "search") {
|
||||||
|
return `${ROOT}${option}.php?s=${keyword}`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFromAPI = (keyword, set, option = null) => {
|
const getFromAPI = (keyword, set, option = null) => {
|
||||||
const URI = createURI(keyword, option);
|
const URI = createURI(keyword, option);
|
||||||
fetch(URI)
|
fetch(URI)
|
||||||
|
|
@ -111,6 +115,10 @@ const App = () => {
|
||||||
getFromAPI("categories", setCategories);
|
getFromAPI("categories", setCategories);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSearchResults = () => {
|
||||||
|
getFromAPI(searchString, setSearchResults, "search");
|
||||||
|
};
|
||||||
|
|
||||||
const handleChange = ev => {
|
const handleChange = ev => {
|
||||||
const { value } = ev.target;
|
const { value } = ev.target;
|
||||||
setSearchString(value);
|
setSearchString(value);
|
||||||
|
|
@ -121,42 +129,30 @@ const App = () => {
|
||||||
<Router>
|
<Router>
|
||||||
<Navbar handleClick={getRandomMeal} buttonUrl={buttonUrl} />
|
<Navbar handleClick={getRandomMeal} buttonUrl={buttonUrl} />
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<SearchBar searchString={searchString} handleChange={handleChange} />
|
<SearchBar
|
||||||
|
searchString={searchString}
|
||||||
|
handleChange={handleChange}
|
||||||
|
onSubmit={getSearchResults}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route
|
<Route exact path="/">
|
||||||
exact
|
<HomePage handleClick={getRandomMeal} buttonUrl={buttonUrl} />
|
||||||
path="/"
|
</Route>
|
||||||
render={props => (
|
<Route exact path={buttonUrl}>
|
||||||
<HomePage
|
<MealPage
|
||||||
{...props}
|
meal={meal}
|
||||||
handleClick={getRandomMeal}
|
getMeal={getRandomMeal}
|
||||||
buttonUrl={buttonUrl}
|
// isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
)}
|
</Route>
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route exact path="/categories">
|
||||||
exact
|
<CategoryListPage
|
||||||
path={buttonUrl}
|
categories={categories}
|
||||||
render={props => (
|
getCategories={getCategories}
|
||||||
<MealPage
|
/>
|
||||||
{...props}
|
</Route>
|
||||||
meal={meal}
|
|
||||||
getMeal={getRandomMeal}
|
|
||||||
// isLoading={isLoading}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
exact
|
|
||||||
path="/categories"
|
|
||||||
render={props => (
|
|
||||||
<CategoryListPage
|
|
||||||
{...props}
|
|
||||||
categories={categories}
|
|
||||||
getCategories={getCategories}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Route path="/categories/:strCategory/">
|
<Route path="/categories/:strCategory/">
|
||||||
<CategoryPage
|
<CategoryPage
|
||||||
|
|
@ -166,13 +162,19 @@ const App = () => {
|
||||||
meal={meal}
|
meal={meal}
|
||||||
/>
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route exact path="/search">
|
||||||
|
<SearchPage
|
||||||
|
searchString={searchString}
|
||||||
|
searchResults={searchResults}
|
||||||
|
// getSearchResults={getSearchResults}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
<Route path="/:idMeal">
|
<Route path="/:idMeal">
|
||||||
<MealPage meal={meal} getMeal={getMeal} />
|
<MealPage meal={meal} getMeal={getMeal} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route exact path="/search" component={SearchPage} />
|
<Route>
|
||||||
{/* We'll have to input searchResults somewhere */}
|
<NotFound handleClick={getRandomMeal} />
|
||||||
<Route
|
</Route>
|
||||||
render={props => <NotFound {...props} handleClick={getRandomMeal} />}
|
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,31 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
const SearchBar = props => {
|
const SearchBar = props => {
|
||||||
return (
|
return (
|
||||||
<input
|
<div className="row">
|
||||||
type="text"
|
<input
|
||||||
name="search"
|
className="input-field col s9"
|
||||||
value={props.searchString}
|
type="text"
|
||||||
placeholder="Search a recipe"
|
name="search"
|
||||||
onChange={props.handleChange}
|
value={props.searchString}
|
||||||
//{onSubmit={props.handleSubmit}
|
placeholder="Search a recipe"
|
||||||
/>
|
onChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
<Link to="/search">
|
||||||
|
<button
|
||||||
|
className="btn waves-effect waves-light right"
|
||||||
|
type="submit"
|
||||||
|
name="searchButton"
|
||||||
|
value="Search"
|
||||||
|
onClick={props.onSubmit}
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
Search
|
||||||
|
<i class="material-icons right">send</i>
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default SearchBar;
|
export default SearchBar;
|
||||||
|
|
|
||||||
20
src/components/SearchResult.js
Normal file
20
src/components/SearchResult.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
const SearchResult = props => {
|
||||||
|
const { meal } = props;
|
||||||
|
const { idMeal, strMeal, strMealThumb } = meal;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
<Link to={`${idMeal}`}>
|
||||||
|
<li key={props.i}>
|
||||||
|
<img src={strMealThumb} alt={strMeal} />
|
||||||
|
<h3>{strMeal}</h3>
|
||||||
|
</li>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchResult;
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
const SearchResultList = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<ul>
|
|
||||||
<li>Recipe #1</li>
|
|
||||||
<li>Recipe #2</li>
|
|
||||||
<li>Recipe #…</li>
|
|
||||||
<li>Recipe #N</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SearchResultList;
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React, { useEffect } from "react";
|
||||||
import CategoryEntry from "../components/CategoryEntry";
|
import CategoryEntry from "../components/CategoryEntry";
|
||||||
|
|
||||||
const CategoryListPage = props => {
|
const CategoryListPage = props => {
|
||||||
const categories = props.categories.categories;
|
const { categories } = props.categories;
|
||||||
const { getCategories } = props;
|
const { getCategories } = props;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,10 @@ const MealPage = props => {
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col s6">
|
<div className="col s12 m6">
|
||||||
<MealPresentation meal={item} />
|
<MealPresentation meal={item} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col s6">
|
<div className="col s12 m6">
|
||||||
<IngredientList ingredients={ingredientList} />
|
<IngredientList ingredients={ingredientList} />
|
||||||
<Recipe recipe={strInstructions} />
|
<Recipe recipe={strInstructions} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
import React, { Component } from "react";
|
import React from "react";
|
||||||
import SearchResultList from "../components/SearchResultList";
|
import SearchResult from "../components/SearchResult";
|
||||||
|
|
||||||
export default class SearchPage extends Component {
|
const SearchPage = props => {
|
||||||
constructor(props) {
|
const { meals } = props.searchResults;
|
||||||
super(props);
|
const { searchString } = props;
|
||||||
this.initState = {};
|
|
||||||
this.state = this.initState;
|
// console.log(meals[0]);
|
||||||
}
|
return (
|
||||||
render() {
|
<div className="container">
|
||||||
return (
|
<h1>Search Results for: {searchString} </h1>
|
||||||
<div>
|
{meals.map((meal, i) => (
|
||||||
<h1>Search Results</h1>
|
<SearchResult i={i} meal={meal} />
|
||||||
<SearchResultList />
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
export default SearchPage;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue