Open In App

Recipe Generator using Next.js

In this tutorial, we’ll create a Recipe Generator App using Next.js, a React framework that allows users to generate random recipes. This type of application can be useful for people looking for new meal ideas or wanting to explore different cuisines. application fetches recipe data from API and displays it to the user.

Output Preview: Let us have a look at how the final output will look like.



Prerequisites:

Approach to Create Recipe Generator:

Steps to Create the Recipe Generator Application:

Step 1: Create a application of NextJS using the following command.



npx create-next-app recipe-generator

Step 2: Navigate to project directory

cd recipe-generator

Step 3: Install the necessary package in your project using the following command.

npm install bootstrap
npm install axios

Step 4: Create the folder structure as shown below and create the files in respective folders.

Project Structure:

The updated dependencies in package.json file will look like:

"dependencies": {
"axios": "^1.6.7",
"bootstrap": "^5.3.3",
"next": "14.1.0",
"react": "^18",
"react-dom": "^18"
}

Example: Below are the components which describes the implementation of the Recipe Generator.




// page.js
 
import RecipeGenerator from '@/components/RecipeGenerator';
import React from 'react';
 
const page = () => {
  return (
    <div>
      <RecipeGenerator />
    </div>
  )
}
 
export default page




// Navbar.js
 
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
 
const Navbar = () => {
  return (
    <nav className="nav justify-content-center navbar-light bg-success">
    <li className="nav-item">
    <a className="nav-link text-light" href="#"><h2>GFG Recipe generator</h2></a>
  </li>
 
</nav>
  );
};
 
export default Navbar;




// RecipeGenerator.js
 
'use client'
import { useState, useEffect } from 'react';
import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.min.css';
import Navbar from './Navbar';
import RecipeCard from '@/components/RecipeCard';
 
const RecipeGenerator = () => {
  const [recipes, setRecipes] = useState([]);
  const [search, setSearch] = useState('');
  const [selectedRecipe, setSelectedRecipe] = useState(null);
  const APP_ID = 'YOUR_EDAMAM_APP_ID';
  const APP_KEY = 'YOUR_EDAMAM_APP_KEY';
 
  const generateRecipe = async () => {
    try {
      const response = await axios.get(`https://api.edamam.com/search?q=${search}&app_id=bbb0cce2&app_key=2fe683efd1286808ab9fc1d52132e3dd`);
      if (response.data.hits.length > 0) {
        setRecipes(response.data.hits);
      }
    } catch (error) {
      console.error('Failed to fetch recipe', error);
    }
  };
 
  const openModal = (recipe) => {
    setSelectedRecipe(recipe);
    document.getElementById('exampleModal').style.display = 'block';
  };
 
  const closeModal = () => {
    setSelectedRecipe(null);
    document.getElementById('exampleModal').style.display = 'none';
  };
 
  return (
    <>
    <Navbar />
    <div className="container mt-3 justify-content-center">
      <div className="row">
        <div className="col mb-4">
          <input type="text" value={search} onChange={(e) => setSearch(e.target.value)} className="form-control" />
        </div>
        <div className="col">
          <button onClick={generateRecipe} className="btn btn-success justify-content-center">Generate Recipe</button>
        </div>
      </div>
       
        {recipes.length === 0 ? (
          <p>No recipes found</p>
        ) : (
         <RecipeCard recipes={recipes}
         openModal={openModal}
         closeModal={closeModal}
         selectedRecipe={selectedRecipe}
          
         />
        )}
    </div>
    </>
  );
};
 
export default RecipeGenerator;




// RecipeCard.js
 
import React from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
const RecipeCard = ({recipes, openModal, closeModal, selectedRecipe}) => {
  return (
    <div className="row">
        {
            recipes.map((recipe) => (
                <div key={recipe.recipe.label} className="col-md-3 mb-3">
                    <div className="card">
                        <img src={recipe.recipe.image} className="card-img-top" style={{ height: '200px', objectFit: 'cover' }} alt={recipe.recipe.label} />
                        <div className="card-body">
                            <h5 className="card-title">{recipe.recipe.label}</h5>
                            <p className="card-text">Calories: {recipe.recipe.calories.toFixed(2)}</p>
                            <button onClick={() => openModal(recipe)} className="btn btn-outline-success">View Ingredients</button>
                        </div>
                    </div>
                </div>
            ))
        }
        <div className="modal" id="exampleModal" tabIndex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" onClick={closeModal}>
    <div className="modal-dialog modal-dialog-centered" role="document" style={{ margin: "auto" }}>
        <div className="modal-content" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
                <h5 className="modal-title" id="exampleModalLabel">Ingredients{'  '}</h5>
                <button type="button" className="close" data-dismiss="modal" aria-label="Close" onClick={closeModal}>
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div className="modal-body">
                <ul>
                    {selectedRecipe && selectedRecipe.recipe.ingredientLines.map((ingredient, index) => (
                        <li key={index}>{ingredient}</li>
                    ))}
                </ul>
            </div>
        </div>
    </div>
</div>
 
    </div>
     
  )
}
 
export default RecipeCard

Start your application using the following command.

npm run dev

Output: Open web-browser and type the following URL http://localhost:3000/


Article Tags :