,

MERN Stack Grocery Management System: Reliable and Scalable Security

Posted by


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.