Fruit and Vegetable Market Shop using MERN

Last Updated : 23 Jul, 2025

In this comprehensive guide, we'll walk through the step-by-step process of creating a Fruit and Vegetable Market Shop using the MERN (MongoDB, Express.js, React, Node.js) stack. This project will showcase how to set up a full-stack web application where users can view, filter, and purchase various fruits and vegetables.

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

Screenshot-2567-01-03-at-232111-(1)

Prerequisites:

Approach to create Fruit and Vegetable Market Shop in MERN:

  1. Import Statements:
    • Import necessary dependencies and components.
    • React is imported for defining React components.
    • ProductList and Header are custom components, assumed to be present in the ./components directory.
    • CustomItemContext is imported, presumably a custom context provider.
  2. Functional Component:
    • Define a functional component named App.
  3. Context Provider:
    • Wrap the Header and ProductList components inside the CustomItemContext provider. This suggests that the components within this provider have access to the context provided by CustomItemContext.
  4. Component Rendering:
    • Render the following components:
      • CustomItemContext: Presumably, this is a context provider that wraps its child components (Header and ProductList). The purpose of this context is not clear from the provided code snippet.
      • Header component.
      • ProductList component.

Steps to Create the Backend:

Step 1: Create a directory for project

npm init backend

Step 2: Open project using the command

cd backend

Step 3: Installing the required packages

npm install express mongoose cors

Project Structure:

Screenshot-2567-01-04-at-000243
Backend project structure

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

"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"mongoose": "^8.0.0",
}

Example: Create `server.js` and paste the below code.

JavaScript
// server.js
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const PORT = process.env.PORT || 5000;
const cors = require('cors');

mongoose.connect('mongodb://localhost/fruitvegmarke',
{
	useNewUrlParser: true,
	useUnifiedTopology: true
}
);

app.use(express.json());
app.use(cors()); // Use the cors middleware

const productSchema = new mongoose.Schema({
name: String,
type: String,
description: String,
price: Number,
image: String,
});

const Product = mongoose.model('Product', productSchema);

// Function to seed initial data into the database
const seedDatabase = async () => {
try {
	await Product.deleteMany(); // Clear existing data

	const products = [
	{
		name: 'Apple', type: 'Fruit',
		description: 'Fresh and crispy',
		price: 150,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142542/apple.jpg'
	},
	{
		name: 'Banana',
		type: 'Fruit',
		description: 'Rich in potassium',
		price: 75,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142554/banana.jpg'
	},
	{
		name: 'Orange',
		type: 'Fruit',
		description: 'Packed with vitamin C',
		price: 200,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142641/orange.jpg'
	},
	{
		name: 'Carrot',
		type: 'Vegetable',
		description: 'Healthy and crunchy',
		price: 100,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142613/carrot.jpg'
	},
	{
		name: 'Broccoli',
		type: 'Vegetable',
		description: 'Nutrient-rich greens',
		price: 175,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142601/brocoli.jpg'
	},
	{
		name: 'Grapes',
		type: 'Fruit',
		description: 'Sweet and juicy',
		price: 250,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142629/grapes.jpg'
	},
	{
		name: 'Strawberry',
		type: 'Fruit',
		description: 'Delicious red berries',
		price: 300,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142657/strawberry.jpg'
	},
	{
		name: 'Lettuce',
		type: 'Vegetable',
		description: 'Crisp and fresh',
		price: 120,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142635/lettue.jpg'
	},
	{
		name: 'Tomato',
		type: 'Vegetable',
		description: 'Versatile and flavorful',
		price: 180,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142704/tomato.jpg'
	},
	{
		name: 'Cucumber',
		type: 'Vegetable',
		description: 'Cool and hydrating',
		price: 130,
		image:
'https://media.geeksforgeeks.org/wp-content/uploads/20240104142621/cocumber.jpg'
	},

	];

	await Product.insertMany(products);
	console.log('Database seeded successfully');
} catch (error) {
	console.error('Error seeding database:', error);
}
};

// Seed the database on server startup
seedDatabase();

// Define API endpoint for fetching all products
app.get('/api/products', async (req, res) => {
try {
	// Fetch all products from the database
	const allProducts = await Product.find();

	// Send the entire products array as JSON response
	res.json(allProducts);
} catch (error) {
	console.error(error);
	res.status(500)
	.json({ error: 'Internal Server Error' });
}
});

app.listen(PORT, () => {
console.log(
	`Server is running on port ${PORT}`
);
});

Start the backend server:

node server.js

Steps to Create the Frontend:

Step 1: Set up React frontend using the command.

npx create-react-app client

Step 2: Navigate to the project folder using the command.

cd client

Project Structure:

Screenshot-2567-01-04-at-000408
Client /Frontend project structure

The updated dependencies in package.json for frontend will look like:

"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
CSS
/*App.css*/
.cart-items {
     border-radius: 50%;
     background-color: rgb(20, 158, 105);
     font-weight: 700;
     color: aliceblue;
     width: 30px;
     height: 30px;
     font-size: 30px;
     padding: 10px;
     top: 10px;
     position: relative;
     left: 30px;
 }

 .header {
     display: flex;
     justify-content: space-evenly;
     align-items: center;
     padding: 10px;
     border-bottom: 1px sold #ccc;

 }


 /* card */
 /* client/src/components/ProductItem.css */
 .product-card {
     border: 1px solid #ddd;
     border-radius: 8px;
     width: fit-content;
     padding: 16px;
     margin: 16px;
     box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
     background-color: #fff;
     display: flex;
     flex-direction: column;
     align-items: center;
 }

 .product-image {
     width: 200px;
     height: 200px;
     object-fit: cover;
     border-radius: 10px;
     margin-bottom: 12px;
     transition: transform 0.3s ease-in-out;
 }

 .product-image:hover {
     transform: scale(1.1);
     /* Enlarge the image on hover */
 }

 .product-details {
     text-align: center;
 }


 .item-card {
     display: flex;
     flex-wrap: wrap;
 }

 h2 {
     text-align: center;
 }

 .filter-btn {
     display: flex;
     flex-direction: row;
     padding: 10px;
     gap: 10px;
     justify-content: center;
 }

 .prdt-list {
     display: flex;
     flex-direction: column;
     justify-content: center;
 }

 .cart-num {
     margin-bottom: 40px;
     cursor: pointer;
 }

 .buy-now-btn {
     background-color: rgb(11, 162, 11);
     color: white;
     padding: 5px 10px;
     border-radius: 10px;
     font-size: 2rem;
     position: fixed;
     top: 30%;
     right: 10px;
     cursor: pointer;
 }

 .buy-now-btn:hover {
     background-color: rgb(113, 230, 113);
     color: brown;
 }

 .gfg {
     background-color: green;
     color: white;
     padding: 5px 10px;
     border-radius: 10px;
 }
JavaScript
// client/src/App.js
import React from 'react';

import ProductList from './components/ProductList';
import Header from './components/Header';
import './App.css'
import CustomItemContext from './context/ItemContext';

const App = () => {
	return (
		<CustomItemContext>
			<Header />
			<ProductList />
		</CustomItemContext>
	);
};

export default App;
JavaScript
//context/ItemContext.js

import {
	createContext,
	useEffect,
	useState
} from 'react';

const itemContext = createContext();

// creating custom provider
function CustomItemContext({ children }) {
	const [products, setProducts] = useState([]);
	const [cart, setCart] = useState([]);
	const [itemsInCart, setItemsInCart] = useState(0);
	const [totalPrice, setTotalPrice] = useState(0)

	// useEffect to load all the vegetables
	useEffect(() => {
		// Fetch products from the backend and dispatch 'SET_PRODUCTS' action
		const fetchData = async () => {
			const response =
				await fetch('http://localhost:5000/api/products');
			const products = await response.json();
			// console.log(products)
			setProducts(products);
		};

		fetchData();
	}, []);

	const addToCart = (product) => {
		setTotalPrice(totalPrice + product.price)
		setCart([...cart, product]);
		setItemsInCart(itemsInCart + 1);
	};

	const removeFromCart = (product) => {
		const index =
			cart.findIndex(
				(prdt) =>
					prdt._id === product._id);
		console.log(index);

		if (index !== -1) {
			// Item found in the cart
			// Now you can remove it from the cart array
			const updatedCart = [...cart];
			updatedCart.splice(index, 1);
			setTotalPrice(totalPrice - cart[index].price);
			setCart(updatedCart);
			setItemsInCart(itemsInCart - 1);
		} else {
			console.log("Item not found in the cart");
		}
	};

	return (
		// default provider
		<itemContext.Provider value={
			{
				products, addToCart,
				removeFromCart,
				itemsInCart, totalPrice
			}}>
			{children}
		</itemContext.Provider>
	);
}

export { itemContext };
export default CustomItemContext;
JavaScript
// client/src/components/Header.js
import React, { useContext } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faCartShopping } from '@fortawesome/free-solid-svg-icons'
import { itemContext } from '../context/ItemContext';

const Header = () => {

	const { itemsInCart, totalPrice } = useContext(itemContext)

	return (
		<div className='header' >
			<h1 className='gfg'>
				GFG Fruit & Vegetable Market
			</h1>
			<h3 style={{ color: "green" }}>
				Total Price: {totalPrice}
			</h3>
			<div className='cart-num'>
				<div className='cart-items'>
					{itemsInCart}
				</div>
				<FontAwesomeIcon icon={faCartShopping} size="4x" />
			</div>
		</div>
	);
};

export default Header;
JavaScript
// client/src/components/ProductItem.js
import React, { useContext } from 'react';
import { itemContext } from '../context/ItemContext';


const ProductItem = ({ product }) => {
	const { addToCart, removeFromCart } = useContext(itemContext)
	const handleAddToCart = (product) => {
		console.log(product)
		addToCart(product)

	};
	const handleRemoveToCart = (product) => {
		console.log("product removed", product)
		removeFromCart(product)

	};
	return (
		<div className="product-card">
			<img className="product-image"
				src={product.image}
				alt={product.name} />
			<div className="product-details">
				<h3 style={{ fontWeight: "700" }}>
					{product.name}
				</h3>
				<p style={{ fontWeight: "300" }}>
					{product.description}
				</p>
				<p style={{ fontWeight: "500" }}>
					Price: {product.price} Rs/Kg
				</p>
				<button onClick={
					() => handleAddToCart(product)
				}>
					Add to Cart
				</button>
				<button onClick={
					() =>
						handleRemoveToCart(product)
				}>
					-
				</button>
			</div>
		</div>
	);
};

export default ProductItem;
JavaScript
// client/src/components/ProductList.js

import React, { useContext, useEffect, useState } from 'react';
import ProductItem from './ProductItem';
import { itemContext } from '../context/ItemContext';

const ProductList = () => {
	const { products } = useContext(itemContext);
	// Keep a local state for sorted products
	const [sortedProducts, setSortedProducts] =
		useState([...products]);
	const [minPrice, setMinPrice] = useState(0);
	const [maxPrice, setMaxPrice] = useState(3000);
	// 'all' represents no type filter
	const [selectedType, setSelectedType] = useState('all');

	useEffect(() => {
		setSortedProducts([...products])
	}, [products])

	const handleSortByPrice = () => {
		const sorted = [...sortedProducts]
			.sort((a, b) => a.price - b.price);
		setSortedProducts(sorted);
	};

	const handleFilterByPriceRange = () => {
		const filtered =
			products.filter(
				(product) =>
					product.price >= minPrice &&
					product.price <= maxPrice);
		setSortedProducts(filtered);
	};

	const handleFilterByType = () => {
		if (selectedType === 'all') {
			// Reset the type filter
			setSortedProducts([...products]);
		} else {
			const filtered =
				products.filter(
					(product) =>
						product.type === selectedType);
			setSortedProducts(filtered);
		}
	};

	return (
		<div className='prdt-list'>
			<h2>Product List</h2>
			<div className='filter-btn'>
				<button onClick={handleSortByPrice}>
					Sort by Price
				</button>
				<label>
					Min Price:
					<input type='number' value={minPrice}
						onChange={
							(e) =>
								setMinPrice(Number(e.target.value))
						} />
				</label>
				<label>
					Max Price:
					<input type='number' value={maxPrice}
						onChange={
							(e) =>
								setMaxPrice(Number(e.target.value))
						} />
				</label>
				<button onClick={() => handleFilterByPriceRange()}>
					Filter by Price Range
				</button>
				<label>
					Filter by Type:
					<select value={selectedType}
						onChange={
							(e) =>
								setSelectedType(e.target.value)
						}>
						<option value='all'>
							All
						</option>
						<option value='Fruit'>Fruit</option>
						<option value='Vegetable'>Vegetable</option>
					</select>
				</label>

				<button onClick={handleFilterByType}>
					Filter by Type
				</button>
			</div>

			<ul className='item-card'>
				{sortedProducts.map((product) => (
					<ProductItem key={product._id}
						product={product} />
				))}
			</ul>
			<div className='buy-now-btn'>Buy Now</div>
		</div>
	);
};

export default ProductList;

To start frontend code:

npm start

Output:


Output of Data Saved in Database:

fooddb
Db
Comment

Explore