Introduction:
In today’s fast-paced world, grocery management systems are becoming increasingly popular as they provide a convenient way for customers to purchase groceries online. To implement a secure and scalable grocery management system, we can use the MERN stack, which consists of MongoDB, Express.js, React, and Node.js. In this tutorial, we will walk through the steps involved in creating a secure and scalable grocery management system using the MERN stack.
Step 1: Setting up the Development Environment
Before we start building our grocery management system, we need to set up our development environment. Make sure you have Node.js and npm installed on your machine. You can download and install Node.js from the official website (https://nodejs.org/).
Next, create a new directory for your project and navigate to it in the terminal. Run the following command to initialize a new Node.js project:
npm init -y
Step 2: Setting up the Backend with Node.js and Express.js
Next, we will set up the backend of our grocery management system using Node.js and Express.js. To do this, run the following commands in your terminal:
npm install express body-parser mongoose dotenv
Create a new file called server.js
in the root directory of your project and add the following code:
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
const PORT = process.env.PORT || 5000;
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
app.use(bodyParser.json());
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
In the above code, we have imported the necessary modules, set up a connection to MongoDB using mongoose, and started the server on port 5000.
Step 3: Setting up the Database with MongoDB
To set up the database for our grocery management system, we will use MongoDB as our database. Sign up for a free account on MongoDB Atlas (https://www.mongodb.com/cloud/atlas) and create a new cluster.
After setting up the cluster, copy your connection string and paste it in a .env
file in the root directory of your project:
MONGO_URI=your_connection_string_here
Step 4: Creating Models for Products and Orders
Next, we will create models for products and orders in our grocery management system. Create a new folder called models
in the root directory of your project and create two new files called Product.js
and Order.js
.
In Product.js
, add the following code:
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
price: { type: Number, required: true },
category: { type: String, required: true },
image: { type: String, required: true },
});
const Product = mongoose.model('Product', productSchema);
module.exports = Product;
In Order.js
, add the following code:
const mongoose = require('mongoose');
const orderSchema = new mongoose.Schema({
products: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Product' }],
total: { type: Number, required: true },
status: { type: String, default: 'Pending' },
});
const Order = mongoose.model('Order', orderSchema);
module.exports = Order;
Step 5: Implementing CRUD Operations for Products and Orders
Now that we have set up the database and created models, we can implement CRUD operations for products and orders in our grocery management system. Create a new folder called routes
in the root directory of your project and create two new files called productRoutes.js
and orderRoutes.js
.
In productRoutes.js
, add the following code:
const express = require('express');
const Product = require('../models/Product');
const router = express.Router();
router.get('/products', async (req, res) => {
try {
const products = await Product.find();
res.json(products);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
router.post('/products', async (req, res) => {
try {
const product = new Product(req.body);
await product.save();
res.json(product);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
router.put('/products/:id', async (req, res) => {
try {
const product = await Product.findByIdAndUpdate(req.params.id, req.body, { new: true });
res.json(product);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
router.delete('/products/:id', async (req, res) => {
try {
await Product.findByIdAndDelete(req.params.id);
res.json({ message: 'Product deleted' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
module.exports = router;
In orderRoutes.js
, add the following code:
const express = require('express');
const Order = require('../models/Order');
const router = express.Router();
router.get('/orders', async (req, res) => {
try {
const orders = await Order.find().populate('products');
res.json(orders);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
router.post('/orders', async (req, res) => {
try {
const order = new Order(req.body);
await order.save();
res.json(order);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
router.put('/orders/:id', async (req, res) => {
try {
const order = await Order.findByIdAndUpdate(req.params.id, req.body, { new: true });
res.json(order);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
router.delete('/orders/:id', async (req, res) => {
try {
await Order.findByIdAndDelete(req.params.id);
res.json({ message: 'Order deleted' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Server Error' });
}
});
module.exports = router;
Step 6: Securing the Backend with JWT Authentication
To secure the backend of our grocery management system, we will implement JWT authentication. Install the jsonwebtoken
package by running the following command in your terminal:
npm install jsonwebtoken
Create a new file called auth.js
in the models
folder and add the following code:
const jwt = require('jsonwebtoken');
const generateToken = (user) => {
return jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
expiresIn: '30d',
});
};
module.exports = generateToken;
In server.js
, add the following lines of code after setting up the server:
const jwt = require('jsonwebtoken');
const auth = require('./models/auth');
Step 7: Setting up the Frontend with React
Now that we have set up the backend of our grocery management system, we can move on to setting up the frontend with React. To do this, run the following command in your terminal:
npx create-react-app client
Next, install the required packages by running the following command in the client
directory:
npm install axios react-router-dom
Step 8: Creating Components for Products and Orders
Create a new folder called components
in the client/src
directory and create two new files called Products.js
and Orders.js
.
In Products.js
, add the following code:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const Products = () => {
const [products, setProducts] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/api/products').then((res) => {
setProducts(res.data);
});
}, []);
return (
<div>
<h1>Products</h1>
{products.map((product) => (
<div key={product._id}>
<h2>{product.name}</h2>
<p>{product.price}</p>
<p>{product.category}</p>
<img src={product.image} alt={product.name} />
<button>Add to Cart</button>
</div>
))}
</div>
);
};
export default Products;
In Orders.js
, add the following code:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const Orders = () => {
const [orders, setOrders] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/api/orders').then((res) => {
setOrders(res.data);
});
}, []);
return (
<div>
<h1>Orders</h1>
{orders.map((order) => (
<div key={order._id}>
<h2>Total: {order.total}</h2>
<p>Status: {order.status}</p>
<ul>
{order.products.map((product) => (
<li key={product._id}>{product.name}</li>
))}
</ul>
</div>
))}
</div>
);
};
export default Orders;
Step 9: Setting up Routes for Products and Orders
Create a new folder called screens
in the client/src
directory and create a new file called HomeScreen.js
.
In HomeScreen.js
, add the following code:
import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Products from '../components/Products';
import Orders from '../components/Orders';
const HomeScreen = () => {
return (
<Router>
<Route path="/" component={Products} />
<Route path="/orders" component={Orders} />
</Router>
);
};
export default HomeScreen;
In App.js
in the client/src
directory, replace the existing code with the following:
import React from 'react';
import HomeScreen from './screens/HomeScreen';
const App = () => {
return (
<div>
<HomeScreen />
</div>
);
};
export default App;
Step 10: Running the Application
To run the grocery management system, start the backend server by running the following command in the root directory of your project:
node server.js
Start the frontend server by running the following command in the client
directory:
npm start
Your grocery management system should now be up and running. You can access it by visiting http://localhost:3000
in your web browser. From here, users can view products, add them to their cart, and place orders.
Conclusion:
In this tutorial, we walked through the steps involved in creating a secure and scalable grocery management system using the MERN stack. By following these steps, you should now have a working grocery management system that allows users to browse products, add them to their cart, and place orders securely and efficiently. Feel free to customize and extend the system further to meet your specific requirements.