Open In App

Travel Planning App API using Node & Express.js

Last Updated : 05 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we’ll walk through the step-by-step process of creating a Travel Planning App With Node and ExpressJS. This application will provide users with the ability to plan their trips by searching for destinations, booking flights and hotels, submitting reviews, receiving notifications, sharing their trips on social media, and processing payments.

Prerequisites:

Approach to Create Travel Planning App API using Node and ExpressJS:

  • Identify key features like user authentication, booking flights/hotels, reviews, notifications, and payments.
  • Install Node.js, npm, and ExpressJS.
  • Create a new project directory and initialize it.
  • Implement features like user authentication, booking, review submission, and payment processing using Express.js controllers and routes.
  • Integrate third-party APIs for flight/hotel booking, implement notifications, and enable trip sharing on social media.

Steps to Create the NodeJS App and Installing Module:

Step 1: Create a NodeJS project using the following command.

npm init -y

Step 2: Install Express.js and other necessary dependencies.

npm install express mongoose body-parser bcrypt jsonwebtoken 

Step 3: Create folders for different parts of the application such as models, controllers, routes, and middleware. Inside each folder, create corresponding files for different components of the application.

Step 4: Set up a MongoDB database either locally or using a cloud-based service like MongoDB Atlas. Define Mongoose models for the data entities such as User, Trip, Booking, Review, Notification, and Payment.

Step 5: Create controller functions for each feature such as searchDestinations, bookFlight, bookHotel, submitReview, sendNotification, shareTrip, and processPayment. Implement authentication middleware (authenticate) to protect routes that require authentication. Define route handlers for each feature in separate route files (authRoutes.js, tripRoutes.js, bookingRoutes.js, etc.).

Project Structure:

Screenshot-2024-04-03-035857

Project Folder Structure

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

"dependencies": {
"express": "^4.18.2",
"mongoose": "^8.2.1",
"body-parser": "^1.20.2",
"bcrypt": "^5.1.1",
"jsonwebtoken": "^9.0.2"
}

Example: Below is an example of Travel Planning App with NodeJS and ExpressJS.

JavaScript
// authController.js
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const { secret } = require('../config');

async function signup(req, res) {
    try {
        const { email, password } = req.body;
        const hashedPassword = await bcrypt.hash(password, 10);
        const user = await User.create({
            email, password: hashedPassword
        });
        res.status(201).json({ user });
    } catch (error) {
        res.status(400).json({
            error: error.message
        });
    }
}

async function login(req, res) {
    try {
        const { email, password } = req.body;
        const user = await User.findOne({ email });
        if (!user) {
            throw new Error('User not found');
        }
        const validPassword = await bcrypt.compare(
            password, user.password);
        if (!validPassword) {
            throw new Error('Invalid password');
        }
        const token = jwt.sign({
            userId: user._id
        },
            secret, { expiresIn: '1h' });
        res.status(200).json({ token });
    } catch (error) {
        res.status(401).json({
            error: error.message
        });
    }
}

module.exports = { signup, login };
JavaScript
// bookingController.js
const Booking = require('../models/Booking');

async function bookFlight(req, res) {
    try {
        /* Assuming request body contains
         necessary details for flight booking
         */
        const { userId, tripId, flightDetails } = req.body;

        // Create a new flight booking document in the database
        const booking = await Booking.create({
            userId,
            tripId,
            type: 'Flight',
            details: flightDetails,
            // Store flight details in the database
        });

        res.status(201).json({ booking });
    } catch (error) {
        res.status(400).json({
            error: error.message
        });
    }
}

async function bookHotel(req, res) {
    try {
        /* Assuming request body contains
        necessary details for hotel booking
        */
        const { userId, tripId, hotelDetails } = req.body;

        // Create a new hotel booking document in the database
        const booking = await Booking.create({
            userId,
            tripId,
            type: 'Hotel',
            details: hotelDetails,
            // Store hotel details in the database
        });

        res.status(201).json({ booking });
    } catch (error) {
        res.status(400).json({
            error: error.message
        });
    }
}

module.exports = { bookFlight, bookHotel };
JavaScript
// notificationController.js
const Notification = require('../models/Notification');

async function sendNotification(req, res) {
    try {
        /* Assuming request body contains 
        necessary details for sending notification
        */
        const { userId, message } = req.body;

        // Create a new notification document in the database
        const notification = await Notification.create({
            userId,
            message,
            sentAt: new Date(),
            // Record the time when the notification is sent
        });

        res.status(201).json({ notification });
    } catch (error) {
        res.status(400).json({
            error: error.message
        });
    }
}

module.exports = { sendNotification };
JavaScript
// paymentController.js
const Payment = require('../models/Payment');

async function processPayment(req, res) {
    try {
        /*
         Assuming request body contains 
         necessary details for processing payment
         */
        const { userId, amount, paymentDetails } = req.body;

        // Create a new payment document in the database
        const payment = await Payment.create({
            userId,
            amount,
            paymentDetails, // Store payment details in the database
            status: 'Success', // Assuming payment is successful
            createdAt: new Date(),
            // Record the time when the payment is processed
        });
        res.status(201).json({ payment });
    } catch (error) {
        res.status(400).json({
            error: error.message
        });
    }
}

module.exports = { processPayment };
JavaScript
// reviewController.js
const Review = require('../models/Review');

async function submitReview(req, res) {
  try {
    /* Assuming request body contains necessary
     details for submitting a review
     */
    const { userId, destination, rating, comment } = req.body;
    
    // Create a new review document in the database
    const review = await Review.create({
      userId,
      destination,
      rating,
      comment,
      createdAt: new Date(), 
      // Record the time when the review is submitted
    });

    res.status(201).json({ review });
  } catch (error) {
    res.status(400).json({ 
        error: error.message });
  }
}

module.exports = { submitReview };
JavaScript
// socialController.js
async function shareTrip(req, res) {
    try {
        /* Assuming request body contains necessary
         details for sharing a trip
         */
        const { userId, tripId, socialMedia, message } = req.body;

        // Implement social sharing logic here

        // Assuming sharing is successful
        res.status(200).json({
            message: 'Trip shared successfully'
        });
    } catch (error) {
        res.status(400).json({
            error: error.message
        });
    }
}

module.exports = { shareTrip };
JavaScript
// tripController.js
const Trip = require('../models/Trip');

async function searchDestinations(req, res) {
    try {
        /* For simplicity, let's assume we return a
         list of destinations from the database
         */
        const destinations = await Trip.find().distinct('destination');
        res.status(200).json({ destinations });
    } catch (error) {
        res.status(400).json({ error: error.message });
    }
}

async function createItinerary(req, res) {
    try {
        /* Assuming request body contains necessary
         details for creating an itinerary
         */
        const { userId, destination, startDate, endDate } = req.body;

        // Create a new itinerary document in the database
        const itinerary = await Trip.create({
            userId,
            destination,
            startDate,
            endDate,
            createdAt: new Date(),
            // Record the time when the itinerary is created
        });

        res.status(201).json({ itinerary });
    } catch (error) {
        res.status(400).json({ error: error.message });
    }
}

module.exports = { searchDestinations, createItinerary };
JavaScript
// authMiddleware.js
const jwt = require('jsonwebtoken');
const { secret } = require('../config');

function authenticate(req, res, next) {
    const token = req.headers.authorization;
    if (!token) {
        return res.status(401).json({
            error: 'Authorization header missing'
        });
    }

    try {
        const decodedToken = jwt.verify(token, secret);
        req.userId = decodedToken.userId;
        next();
    } catch (error) {
        return res.status(401).json({
            error: 'Invalid token'
        });
    }
}

module.exports = { authenticate };
JavaScript
// errorMiddleware.js
function errorHandler(err, req, res, next) {
    console.error(err.stack);
    res.status(500).json({
        error: 'Something went wrong!'
    });
}

module.exports = { errorHandler };
JavaScript
// Booking.js
const mongoose = require('mongoose');

const bookingSchema = new mongoose.Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    tripId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Trip',
        required: true
    },
    type: {
        type: String,
        required: true
    }, // Flight, Hotel, Car, etc.
    // Add more fields as needed
});

const Booking = mongoose.model('Booking', bookingSchema);

module.exports = Booking;
JavaScript
// Notification.js
const mongoose = require('mongoose');

const notificationSchema = new mongoose.Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User', required: true
    },
    message: {
        type: String,
        required: true
    },
    // Add more fields as needed
});

const Notification = mongoose.model('Notification', notificationSchema);

module.exports = Notification;
JavaScript
// Payment.js
const mongoose = require('mongoose');

const paymentSchema = new mongoose.Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User', required: true
    },
    amount: {
        type: Number,
        required: true
    },
    status: {
        type: String,
        default: 'Pending'
    },
    // Add more fields as needed
});

const Payment = mongoose.model('Payment', paymentSchema);

module.exports = Payment;
JavaScript
// Review.js
const mongoose = require('mongoose');

const reviewSchema = new mongoose.Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User', required: true
    },
    destination: {
        type: String,
        required: true
    },
    rating: {
        type: Number,
        required: true
    },
    comment: {
        type: String
    },
    // Add more fields as needed
});

const Review = mongoose.model('Review', reviewSchema);

module.exports = Review;
JavaScript
// Trip.js
const mongoose = require('mongoose');

const tripSchema = new mongoose.Schema({
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User', required: true
    },
    destination: {
        type: String,
        required: true
    },
    startDate: {
        type: Date,
        required: true
    },
    endDate: {
        type: Date,
        required: true
    },
    // Add more fields as needed
});

const Trip = mongoose.model('Trip', tripSchema);

module.exports = Trip;
JavaScript
// User.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    email: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: true
    },
    // Add more fields as needed
});

const User = mongoose.model('User', userSchema);

module.exports = User;
JavaScript
// authRoutes.js
const express = require('express');
const router = express.Router();
const { signup, login } = require('../controllers/authController');

router.post('/signup', signup);
router.post('/login', login);

module.exports = router;
JavaScript
// bookingRoutes.js
const express = require('express');
const router = express.Router();
const { bookFlight, bookHotel } = require('../controllers/bookingController');
const { authenticate } = require('../middleware/authMiddleware');

router.post('/book-flight', authenticate, bookFlight);
router.post('/book-hotel', authenticate, bookHotel);

module.exports = router;
JavaScript
// notificationRoutes.js
const express = require('express');
const router = express.Router();
const { sendNotification } = require('../controllers/notificationController');
const { authenticate } = require('../middleware/authMiddleware');

router.post('/send-notification', authenticate, sendNotification);

module.exports = router;
JavaScript
// paymentRoutes.js
const express = require('express');
const router = express.Router();
const { processPayment } = require('../controllers/paymentController');
const { authenticate } = require('../middleware/authMiddleware');

router.post('/process-payment', authenticate, processPayment);

module.exports = router;
JavaScript
// reviewRoutes.js
const express = require('express');
const router = express.Router();
const { submitReview } = require('../controllers/reviewController');
const { authenticate } = require('../middleware/authMiddleware');

router.post('/submit-review', authenticate, submitReview);

module.exports = router;
JavaScript
// socialRoutes.js
const express = require('express');
const router = express.Router();
const { shareTrip } = require('../controllers/socialController');
const { authenticate } = require('../middleware/authMiddleware');

router.post('/share-trip', authenticate, shareTrip);

module.exports = router;
JavaScript
// tripRoutes.js
const express = require('express');
const router = express.Router();
const { searchDestinations, createItinerary } = require('../controllers/tripController');
const { authenticate } = require('../middleware/authMiddleware');

router.get('/destinations', searchDestinations);
router.post('/itinerary', authenticate, createItinerary);

module.exports = router;
JavaScript
// constants.js
const secret = 'your_secret_key_here';

module.exports = { secret };
JavaScript
// helper.js
// This file contains helper functions that can be used across the application

function formatDate(date) {
    // Implement date formatting logic here
    const options = {
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    };
    return date.toLocaleDateString('en-US', options);
}

function calculateTotalCost(items) {
    // Implement logic to calculate total cost based on items
    return items.reduce(
        (total, item) => total + item.cost, 0);
}

module.exports = { formatDate, calculateTotalCost };
JavaScript
// app.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const authRoutes = require('./routes/authRoutes');
const tripRoutes = require('./routes/tripRoutes');
const bookingRoutes = require('./routes/bookingRoutes');
const reviewRoutes = require('./routes/reviewRoutes');
const notificationRoutes = require('./routes/notificationRoutes');
const socialRoutes = require('./routes/socialRoutes');
const paymentRoutes = require('./routes/paymentRoutes');
const { errorHandler } = require('./middleware/errorMiddleware');

// Initialize Express app
const app = express();

// Middleware
app.use(bodyParser.json());

// Connect to MongoDB
mongoose.connect('mongodb+srv://admn:<password>@cluster0.tudvjbv.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
.then(() => console.log('Connected to MongoDB'))
.catch(error => console.error('MongoDB connection error:', error));

// Routes
app.use('/api/auth', authRoutes);
app.use('/api/trip', tripRoutes);
app.use('/api/booking', bookingRoutes);
app.use('/api/review', reviewRoutes);
app.use('/api/notification', notificationRoutes);
app.use('/api/social', socialRoutes);
app.use('/api/payment', paymentRoutes);

// Error handling middleware
app.use(errorHandler);

// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
JavaScript
// config.js
module.exports = {
    secret: 'your_secret_key_here',
};

Start your server using the following command:

node app.js

Output:

Travel-Planning-App-with-NodeJS-and-ExpressJS

Final Output



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads