Steps to Create the Backend of the Project

Step 1: Start a node.js app by typing the following command

npm init -y

Step 2: Install the following packages

npm i bcyptjs body-parser cors dotenv express helmet jsonwebtoken mongoose morgan nodemon

package.json file should be looking like:

"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.2",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.18.3",
"helmet": "^7.1.0",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.2.1",
"morgan": "^1.10.0",
"nodemon": "^3.1.0"
}

Step 3: Create the following folder structure. We are going to use the model-view-controller architecture (MVC).

Project Structure(Backend)

Project Structure

Example: Below is the code for Backend of Restaurant Reservation System.

JavaScript
// api/index.js

import express from "express";
import dotenv from "dotenv";
import helmet from "helmet";
import morgan from "morgan";
import mongoose from "mongoose";
import cookieParser from "cookie-parser";
import cors from "cors"

import adminRoute from "./routes/admins.js"
import userRoute from "./routes/users.js"
import restRoute from "./routes/rests.js"
import reservRoute from "./routes/reservations.js"

const app = express();
dotenv.config();

const PORT = process.env.PORT || 7700;

const connect = async () => {
    try {
        await mongoose.connect(process.env.MONGO);
        console.log("Connected to mongoDB.");
    } catch (error) {
        throw error;
    }
};

mongoose.connection.on("disconnected", () => {
    console.log("mongoDB disconnected!");
});

app.get('/', (req, res) => { res.send('Hello from Express!') });

//middlewares
app.use(cookieParser())
app.use(express.json());
app.use(helmet());

app.use(cors({
    origin: "http://localhost:3000",
    credentials: true
}))

app.use(morgan("common"));

app.use("/api/admin", adminRoute);
app.use("/api/users", userRoute);
app.use("/api/restaurants", restRoute);
app.use("/api/reservations", reservRoute);

app.listen(PORT, () => {
    console.log("Listening on port 7700");
    connect();
});
JavaScript
// api/error.js

export const createError = (status, message) => {
    const err = new Error();
    err.status = status;
    err.message = message;
    return err;
}
JavaScript
// api/models/Admin.js

import mongoose from "mongoose";

const AdminSchema = new mongoose.Schema(
  {
    username: {
      type: String,
      require: true,
    },
    password: {
      type: String,
      required: true,
      min: 6,
    },
    isAdmin: {
      type: Boolean,
      default: true,
    },
    rest: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Restaurant'
    }
  },
  { timestamps: true }
);



export default mongoose.model("Admin", AdminSchema);
JavaScript
// api/models/Reservation.js

import mongoose from "mongoose";

const ReservationSchema = new mongoose.Schema(
  {
    date: {
        type: Date,
        required: true
    },
    slot: {
        type: String,
        required: true
    },
    people: {
        type: Number,
        required: true
    },
    author: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    rest: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Restaurant'
    }
  },
  { timestamps: true }
);



export default mongoose.model("Reservation", ReservationSchema);
JavaScript
// api/models/Restaurant.js

import mongoose from "mongoose";

const RestaurantSchema = new mongoose.Schema(
  {
    name: {
        type: 'String',
        required: true
    },
    location: {
        type: 'String',
        required: true
    },
    admin: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Admin'
    },
    contact: {
        type: 'String',
        required: true
    }, 
    description: {
        type: 'String',
        required: true
    },
    photo: {
        type: String,
        required: true
    },
    price: {
        type: 'String',
        required: true
    },
    rating: {
        type: Number
    }

  },
  { timestamps: true }
);



export default mongoose.model("Restaurant", RestaurantSchema);
JavaScript
// api/models/User.js

import mongoose from "mongoose";

const UserSchema = new mongoose.Schema(
  {
    username: {
      type: String,
      required: true,
    },
    email: {
      type: String,
      required: true,
      unique: true,
    },
    password: {
      type: String,
      required: true,
    },
    isAdmin: {
      type: Boolean,
      default: false,
    },
    reservations: [
      {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Reservation'
      }
  ]
  },
  { timestamps: true }
);



export default mongoose.model("User", UserSchema);
JavaScript
// api/controllers/admin.js

import Admin from "../models/Admin.js";
import bcrypt from "bcryptjs"
import jwt from "jsonwebtoken"
import { createError } from "../error.js"

export const register = async (req, res, next) => {
    try {

        const salt = bcrypt.genSaltSync(10);
        const hash = bcrypt.hashSync(req.body.password, salt);

        const newAdmin = new Admin({
            ...req.body,
            password: hash
        })

        await newAdmin.save();

        res.status(201).json("Admin has been created");
    }
    catch (err) {
        next(err)
    }
}

export const login = async (req, res, next) => {
    try {
        const admin = await Admin.findOne({ username: req.body.username })
        if (!admin) return next(createError(404, "User not found"))

        const isCorrectPassword = await bcrypt.compare(req.body.password, admin.password);
        if (!isCorrectPassword) return next(createError(400, "Username or Password incorrect"));

        const token = jwt.sign({ id: admin._id }, process.env.JWT)

        const { password, ...otherDetails } = admin._doc;
        res
            .cookie("access_token", token, {
                httpOnly: true,
            })
            .status(200)
            .json({ details: { ...otherDetails }});
    }
    catch (err) {
        next(err)
    }
}
JavaScript
// api/controllers/reservation.js

import Reservation from "../models/Reservation.js";
import Restaurant from "../models/Restaurant.js";
import { slots } from "../data.js";

export const checkAvailableSlots = async(req, res, next) => {
  const date = req.params.date;
  const restId = req.params.id;
  try {
    const reservations = await Reservation.find({
      rest: restId,
      date: {$eq: new Date(date)} 
    });

    const reservedSlots = reservations.map(reservation => reservation.slot);
    const availableSlots = slots.filter(slot => !reservedSlots.includes(slot));
    res.status(200).json(availableSlots);
  }
  catch(err) {
    next(err)
  }
}

export const createReservation = async (req, res, next) => {

  const newRes = new Reservation(req.body);
  try {
    const reservation = await newRes.save();
    res.status(200).json(reservation);

  } catch (err) {
    next(err);
  }
};

// function to cancel reservation
export const deleteReservation = async (req, res, next) => {
  const resId = req.params.id;
  try {
    await Reservation.findByIdAndDelete(resId);
    res.status(200).json("Deleted Successfully");
  } catch (err) {
    next(err);
  }
};

// Function to get reservations by user ID
export const getReservationsByUserId = async (req, res, next) => {
  const userId = req.params.id;
  try {
    const reservations = await Reservation.find({ author: userId }).populate('rest', 'name');
    res.status(200).json(reservations);
  } catch (error) {
    next(err);
  }
};

// Function to get reservations by user ID
export const getReservationsByRestId = async (req, res, next) => {
  const restId = req.params.id;
  try {
    const reservations = await Reservation.find({ rest: restId }).populate('rest', 'name');
    res.status(200).json(reservations);
  } catch (error) {
    next(err);
  }
};
JavaScript
// api/controllers/rest.js

// create, update, view, get all reservations

import Restaurant from "../models/Restaurant.js";
import Admin from "../models/Admin.js";

export const createRestaurant = async (req, res, next) => {
  const adminId = req.body.admin; 
  const newRestaurant = new Restaurant(req.body);
  try {
    const savedRestaurant = await newRestaurant.save();
    await Admin.findOneAndUpdate(
      { _id: adminId },
      { $set: { rest: savedRestaurant._id } },
      { new: true }
    );
    res.status(200).json(savedRestaurant);
  } catch (err) {
    next(err);
  }
};

export const updateRestaurant = async (req, res, next) => {
  try {
    const restaurant = await Restaurant.findByIdAndUpdate(
      req.params.id,
      { $set: req.body },
      { new: true }
    );
    res.status(200).json(restaurant);
  } catch (err) {
    next(err);
  }
};


export const getRestaurant = async (req, res, next) => {
  try {
    const restaurant = await Restaurant.findById(req.params.id);
    res.status(200).json(restaurant);
  } catch (err) {
    next(err);
  }
};

export const getRestaurants = async (req, res, next) => {
  try {
    const rests = await Restaurant.find();
    res.status(200).json(rests);
  } catch (err) {
    next(err)
  }
}
JavaScript
// api/controllers/user.js

import User from "../models/User.js";
import bcrypt from "bcryptjs"
import jwt from "jsonwebtoken"
import { createError } from "../error.js"

export const register = async (req, res, next) => {
    try {

        const salt = bcrypt.genSaltSync(10);
        const hash = bcrypt.hashSync(req.body.password, salt);

        const newUser = new User({
            ...req.body,
            password: hash
        })

        await newUser.save();

        res.status(201).json("User has been created");
    }
    catch (err) {
        next(err)
    }
}

export const login = async (req, res, next) => {
    try {
        const user = await User.findOne({ username: req.body.username })
        if (!user) return next(createError(404, "User not found"))

        const isCorrectPassword = await bcrypt.compare(req.body.password, user.password);
        if (!isCorrectPassword) return next(createError(400, "Username or Password incorrect"));

        const token = jwt.sign({ id: user._id }, process.env.JWT)

        const { password, ...otherDetails } = user._doc;
        res
            .cookie("access_token", token, {
                httpOnly: true,
            })
            .status(200)
            .json({ details: { ...otherDetails }});
    }
    catch (err) {
        next(err)
    }
}
JavaScript
// api/routes/admins.js

import express from "express";
import { login, register } from "../controllers/admin.js ";

const router = express.Router();

router.post("/register", register)
router.post("/login", login)

export default router;
JavaScript
// api/routes/reservations.js

import express from "express";
import {
  createReservation,
  getReservationsByUserId,
  getReservationsByRestId,
  deleteReservation,
  checkAvailableSlots
} from "../controllers/reservation.js";

const router = express.Router();

router.get("/slots/:id/:date", checkAvailableSlots)
router.post("/", createReservation);
router.delete("/:id", deleteReservation);
router.get("/rest/:id", getReservationsByRestId);
router.get("/user/:id", getReservationsByUserId);

export default router;
JavaScript
import express from "express";
import {
  createRestaurant,
  getRestaurant,
  getRestaurants,
  updateRestaurant,
} from "../controllers/rest.js";

const router = express.Router();

router.post("/", createRestaurant);
router.put("/:id", updateRestaurant);
router.get("/:id", getRestaurant);
router.get("/", getRestaurants);

export default router;
JavaScript
// api/routes/users.js

import express from "express";
import { login, register } from "../controllers/user.js ";

const router = express.Router();

router.post("/register", register)
router.post("/login", login)

export default router;
JavaScript
// api/data.js

export const slots = [
    "11:00 AM - 12:00 PM",
    "12:00 PM - 01:00 PM",
    "01:00 PM - 02:00 PM",
    "02:00 PM - 03:00 PM",
    "03:00 PM - 04:00 PM",
    "04:00 PM - 05:00 PM",
    "05:00 PM - 06:00 PM",
    "06:00 PM - 07:00 PM",
    "07:00 PM - 08:00 PM",
    "08:00 PM - 09:00 PM",
    "09:00 PM - 10:00 PM"
];

Restaurant Reservation System using MERN Stack

Restaurant reservation system that helps people book tables at restaurants they like. It’s built using React, Node.js, Express, and the MERN stack, along with Sass for styling. Users can search for restaurants based on their preferences, see details like location, description, price range, and contact info, and then pick a date, time, and number of people for their reservation. MongoDB stores all the important information about restaurants, reservations, and users. React makes the system easy to use with its dynamic and interactive features.

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

Preview of final output

Similar Reads

Prerequisites

ReactNodeExpressMongodb and MongooseSassContext APIREST APICloudinary...

Approach to Create Restaurant Reservation System

The website has the following features:...

Steps to Create the Backend of the Project

Step 1: Start a node.js app by typing the following command...

Steps to Create Frontend

Step 1: Create a react application by using the following command and navigate to the folder:...