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:
- Frontend: React app for users, admin, and restaurant login systems.
- Backend: Node.js with Express for RESTful API services.
- Database: MongoDB for managing users, items, categories, orders, and roles.
- 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.