Online Food Delivery System with React

Online Food Delivery System with React

This tutorial covers creating an online food delivery system using React, Node.js, Express, and MongoDB. The system includes:

  1. Frontend: React app for users, admin, and restaurant login systems.
  2. Backend: Node.js with Express for RESTful API services.
  3. Database: MongoDB for managing users, items, categories, orders, and roles.
  4. Payment Gateway: Integration using Stripe (or another payment service).

Step 1: Setup Project Structure

1.1 Install Node.js and Create a Project

# Install Node.js from https://nodejs.org/
npx create-react-app food-delivery-system
cd food-delivery-system

1.2 Install Required Packages

Install dependencies for the frontend and backend.

# Frontend (React)
npm install react-router-dom axios redux react-redux

# Backend (Express + MongoDB)
npm install express mongoose body-parser cors bcrypt jsonwebtoken dotenv

# Payment Gateway (Stripe)
npm install stripe

Step 2: Backend Development

2.1 Setup Express Server

Create a folder backend/ and initialize it.

cd ..
mkdir backend
cd backend
npm init -y

Create server.js.

const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 5000;

app.use(cors());
app.use(express.json());

mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

const connection = mongoose.connection;
connection.once('open', () => {
  console.log('MongoDB database connection established successfully');
});

// Example Routes
const userRoutes = require('./routes/users');
const adminRoutes = require('./routes/admin');
app.use('/api/users', userRoutes);
app.use('/api/admin', adminRoutes);

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

2.2 Define Models

Create a folder models/ for MongoDB schemas.

User.js

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  role: { type: String, enum: ['user', 'restaurant', 'admin', 'superadmin'], default: 'user' },
  credit: { type: Number, default: 0 },
});

module.exports = mongoose.model('User', userSchema);

FoodItem.js

const mongoose = require('mongoose');

const foodItemSchema = new mongoose.Schema({
  name: { type: String, required: true },
  category: { type: String, enum: ['veg', 'non-veg', 'spicy'], required: true },
  price: { type: Number, required: true },
  addons: [{ name: String, price: Number }],
});

module.exports = mongoose.model('FoodItem', foodItemSchema);

Order.js

const mongoose = require('mongoose');

const orderSchema = new mongoose.Schema({
  userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
  items: [
    {
      item: { type: mongoose.Schema.Types.ObjectId, ref: 'FoodItem' },
      quantity: { type: Number, required: true },
      addons: [String],
    },
  ],
  totalAmount: { type: Number, required: true },
  status: { type: String, enum: ['pending', 'in-progress', 'delivered'], default: 'pending' },
});

module.exports = mongoose.model('Order', orderSchema);

2.3 Implement Routes

Create a folder routes/ and define routes for users, food items, orders, etc.

Example: routes/users.js

const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const User = require('../models/User');

const router = express.Router();

// Register
router.post('/register', async (req, res) => {
  const { name, email, password, role } = req.body;
  const hashedPassword = await bcrypt.hash(password, 10);
  const newUser = new User({ name, email, password: hashedPassword, role });
  await newUser.save();
  res.status(201).send('User registered');
});

// Login
router.post('/login', async (req, res) => {
  const { email, password } = req.body;
  const user = await User.findOne({ email });
  if (!user || !(await bcrypt.compare(password, user.password))) {
    return res.status(400).send('Invalid credentials');
  }
  const token = jwt.sign({ id: user._id, role: user.role }, process.env.JWT_SECRET);
  res.json({ token });
});

module.exports = router;

Step 3: Frontend Development

3.1 Setup React Router

Add routes for user pages, admin dashboard, and restaurant dashboard.

App.js

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';

import UserHome from './pages/UserHome';
import AdminDashboard from './pages/AdminDashboard';
import RestaurantDashboard from './pages/RestaurantDashboard';
import Login from './pages/Login';
import Register from './pages/Register';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<UserHome />} />
        <Route path="/admin" element={<AdminDashboard />} />
        <Route path="/restaurant" element={<RestaurantDashboard />} />
        <Route path="/login" element={<Login />} />
        <Route path="/register" element={<Register />} />
      </Routes>
    </Router>
  );
}

export default App;

3.2 User Interfaces

Login.js

import React, { useState } from 'react';
import axios from 'axios';

function Login() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const response = await axios.post('/api/users/login', { email, password });
      localStorage.setItem('token', response.data.token);
      alert('Login successful');
    } catch (error) {
      alert('Login failed');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" required />
      <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" required />
      <button type="submit">Login</button>
    </form>
  );
}

export default Login;

Continue developing the UI for AdminDashboard, RestaurantDashboard, and Order Management.


Step 4: Payment Integration

Integrate Stripe or another payment service. Example with Stripe:

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

router.post('/create-payment-intent', async (req, res) => {
  const { amount } = req.body;
  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency: 'usd',
  });
  res.send({ clientSecret: paymentIntent.client_secret });
});

Step 5: Deployment

Deploy the React frontend to Netlify or Vercel and the backend to Heroku, AWS, or another hosting platform.

Related Posts

Leave a Reply