Online Food Ordering System: Bachelor of Computer Application
Online Food Ordering System: Bachelor of Computer Application
Online Food Ordering System: Bachelor of Computer Application
SYSTEM
Bachelor of Computer
Application
This is to certify that Mr. Dev Kumar Mahato, Mr. Piyush Kumar , Ms. Neha
Modi have successfully completed the project titled “Online Food Ordering
System” under my supervision during the period from June 2020 to August
2020 which is in partial fulfilment of requirements for the award of Bachelor of
Computer Application degree and submitted to Computer Application
Department of Dr. B.C. Roy Engineering College, Academy Of professional
Courses(323) ,Durgapur,West Bengal.
2
1
Index
3
Acknowledgement
Success of any project depends largely on the encouragement and guidelines of many others.
We take this sincere opportunity to express our gratitude to the people who have been
instrumental in the successful completion of this project work.
Our heartfelt thanks to Mr Pranay Kumar, Student of the Department of Computer Science
and Engineering, BCREC, for providing us the opportunity to develop the project at Ardent
Computech Pvt.Ltd.
We would like to show our greatest appreciation to Mr. Arnab Chakraborty, Project guide at
Ardent, Kolkata. We always feel motivated and encouraged every time by his valuable advice
and constant inspiration; without his encouragement and guidance this project would not have
materialized.
Words are inadequate in offering our thanks to the other trainees, project assistants and other
members at Ardent Computech Pvt. Ltd. for their encouragement and cooperation in carrying
out this project work. The guidance and support received from all the members and who are
contributing to this project, was vital for the success of this project.
4
1. ABSTRACT
Online Food Ordering System is a part of e-commerce. E-commerce or business through net
means distributing, buying, selling, marketing, and servicing of products or services over
electronic systems such as the Internet and other computer networks. Thus if we own a
restaurant we need to upload menu online to attract potential customers. The online food
ordering system gives restaurants the ability to increase sales and expand their business by
giving customers the facility to order food online. The restaurants’ can even customize online
restaurant menu and upload images easily. Having restaurant menu on internet, potential
customers can easily access it a0nd place order at their convenience.
5
2. INTRODUCTION
An online food ordering system is a web-based application that stimulates the foodies
(customers) to put food orders through internet from their favourite restaurant. This
application is based on the MEAN Stack platform.
Relevance Of Project:
Restaurants can reach to their customers and sell their products more easily using this
application. Moreover the customers also can order their desired food just seating in home.
Problem Definition:
Problems of Manual Food ordering process:
Usually to purchase food from restaurant a customer must visit the restaurant.
Otherwise customer should have the contact number of the restaurant to get
home delivery.
Small scale restaurants can reach only to a certain number customers this way.
Project Objective:
6
3. METHODOLOGY
System Analysis
Desig
n
Codin
g
Testin
g
Maintenance
Fig – 3.0
7
4. SYSTEM ANALYSIS
The act, process, or profession of studying an activity (such as a procedure, a business, or a
physiological function) typically by mathematical means in order to define its goals or
purposes and to discover operations and procedures for accomplishing them most efficiently.
Feasibility Study:
Technical feasibility: Since MEAN Stack is a open source and easily available platform
it is easy to develop a web application like “Online Food Ordering System” using it.
Moreover Applications developed in Angular are single page application and user interactive
and in mongoDB it is easy to handle collections of data.
Economic feasibility: Since MEAN Stack is a open source and free to all platform it is
also economically feasible to develop a web application like “Online Food Ordering System”
using it.
Legal feasibility: Since MEAN Stack is a open source and free to all platform it is also
legally feasible to develop a web application like “Online Food Ordering System” using it,
because there is no copyright issue.
Social feasibility: An “Online Food Ordering System” can be very much popular in the
society.
Existing System:
“Online Food Ordering System” has been designed to digitalize the following functions that
are performed by the manual system:
Usually to purchase food from restaurant a customer must visit the restaurant.
Otherwise customer should have the contact number of the restaurant to get
home delivery.
Small scale restaurants can reach only to a certain number customers this way.
8
Proposed System:
Online menus (original and searchable format)
Provision of restaurant owners to register themselves with their menu.
Simple, fast and convenient ordering of food
Availability of the menu online, no need to recite the complete menu over the phone.
An online menu is ready to be viewed and printed by people worldwide.
Accurate – no more spelling out the dishes’ names.
Menu with the actual pictures of the product thereby adding to the uniqueness of your
online presence.
A Data Flow Diagram (DFD) is a diagram that describes the flow of 0data and
the processes that change data throughout a system. A structured analysis and
design tool that can be used for flowcharting in place of or in association with
information. Oriented and process oriented system flowcharts. When analysts
prepare the Data Flow Diagram, they specify the user needs at a level of detail
that virtually determines the information flow into and out of the system and the
required data resources. This network is constructed by using a set of symbols
that do not imply physical implementations. The Data Flow Diagram reviews the
current physical system, prepares input and output specification, specifies the
implementation plan etc.
9
Four basic symbols are used to construct data flow diagrams. They are
symbols that represent data source, data flows, and data transformations and data
storage. The points at which data are transformed are represented by enclosed
figures, usually circles, which are called nodes.
Data Flow
Process
Storage
Steps to Construct Data Flow Diagram:
Four Steps are generally used to construct a DFD.
Process should be named and referred for easy reference. Each name should be
representative of the reference.
The destination of flow is from top to bottom and from left to right.
When a process is distributed into lower level details they are numbered.
10
The names of data stores, sources and destinations are written in capital letters.
Level 0 DFD
Registration Log in
Log
Use in Admi
r Online Check and n
Food Confirm
Place Ordering Order
Order System
Get Confirmation
Maintain or View
Food Category Menu
List
Fig- 4.1
11
for
Level 2 DFD For USER
User
Credential
Validation
Registration
1.2.0
1.1.0
Generate Confirmation
mail Save Order Details if food
Available Order Database
Show Order Details
User ID User ID
&
Admin Passwor Passwor
&
d d
Response Response Admin
Validatio
n
Database
Logi
5.2.0
n
5.1.
0
Response
Response Check
for Login Check
for Login
Categor
y Data Save
Insert Category
Insertio Data
Data Database
n
Data
13
Use Case Diagram:
Logi
n
Registe
r
Add
Food
Details
Delete
Food
Details
Edit
Food
Details
Confir
m
Order
Use Admi
r n
Admin
Registratio
n
Admin
Login
Place
food
Order
Fig- 4.5
14
SOFTWAREREQUIREMENTS:
HARDWAREREQUIREMENTS:
Hardware:
15
5. SYSTEM DESIGN
Systems design is the process of defining the architecture, modules, interfaces, and data for
a system to satisfy specified requirements. Systems design could be seen as the application of
systems theory to product development.
Database Design:
Data design is the first and the foremost activity of system design. In MEAN stack we design
database using MongoDB.
Schema Diagram:
NoSql(MongoDB), unlike SQL which has schema diagrams, has neither names nor
constraints for data modeling diagram(s). The obvious reason is NoSql’s lack of hard and fast
relationship rules, which aims to get a developer started with minimum requirements.
16
Schema Diagram
Categorys Foods
_id _id
categoryname fname
fdesc
RegUsers fprice
_id _id
Orders fpic
category_id
fname
fullname
fdesc
email cname
phone cemail
address cphone
caddress
passward
quan
price
date Note:
Users Schema
_id
fullname
Many To
email ManyRelation
passward _id Auto generated
Primary
Key of MongoDB
17
ER Diagram:
An entity–relationship model is a systematic way of describing and
defining a database. The process is modelled as components (entities)
that are linked with each other by relationships that express the
dependencies and requirements between them. Entities may have
various properties (attributes) that characterize them. Diagrams created
to represent these entities, attributes, and relationships graphically are
called entity–relationship diagrams.
Symbols of ER Diagram:
Symbol Meaning
Entity
Attribute
Key Attribute
m n
Many to
Many
Relationship
18
ER Diagram:
fullnam emai
_id e l
passwor
Users d
categorynam fnam
_id _id e fdes
e c
fpric
e
m n
Categorie contai Food fpic
s n s
m Category_i
d
contai
fullnam n
e passwor caddres
_id d s _id
n fnam
m e
n
RegUse hav Order fdes
e c
rs s
cmai cphon
emai addres l cnam pric e
l phon s e e
e dat
qua e
n
19
Normalization And Denormaliztion of MongoDB:
Normalization:
When you normalize your data, you are dividing your data into multiple collections with
references between those collections. Each piece of data will be in a collection, but
multiple documents will reference it. So this process is better Known as Referencing.
This means, to change your data, you only need to update one document, because that
data is only defined once. However, MongoDB doesn’t have any join facilities, like SQL
does. Therefore, if you need data from several collections, you will need to perform
several queries.
When to use:
You have large subdocuments
Your data changes frequently
You need your data to be up-to-date
Your documents grow by a large amount
Your data is often excluded from your results
You want faster writes
Denormalization:
In this way we can store the preferred Documents of each user as an embedded
document. So this process is better known as Embedding. The advantage of this is that
you need less query to get the information. The downside is that it takes up more space
and is more difficult to keep in sync.
When to use:
You have small subdocuments
Your data does not need to change regularly
You don’t need immediate consistency ( not up-to-date )
Your documents grow by a small amount
You need this data to perform a second query
You want faster reads
Note:
For the application “Online Food Ordering System” we have used Referencing
(Normalization) since it is fulfilling the criteria to use Referencing.
20
MongoDB Collection Design:
MongoDB does not support SQL, it stores data as documents in JSON format. So it is
a document oriented database.A Collection may store a number of documents.
A Collection is analogous to a table of an RDBMS. A Collection may store documents those
who are not same in structure. This is possible because MongoDB is a Schema-
free database.
Collection Definition:
Documents are analogous to the records of an RDBMS. Insert, update, and delete operations
can be performed on a collection. The following table will help you to understand the concept
more easily :
RDBMS MongoDB
Table Collection
Column Key
Value Value
21
Collection Name: Orders
var Order=mongoose.model('order',{
})
22
Collection Name: Users (For Admin)
Fig- 23
5.3
Form Design:
Since Angular is Single Page Application ,so one web form(page) can hold different
components. Our project “Online Food Ordering System” contains two forms:
1. Admin Form ,
2. User Form.
Components Of Form:
Fig 5.4
24
Add Food Category Component:
Fig- 5.5
Fig – 5.6
25
View Food Category Component:
Fig – 5.7
Fig – 5.8
26
View Customers component:
Fig -5.9
Fig -5.10
27
2. User Form Components
Fig – 5.11
Fig 5.12
28
Order Component:
Fig – 5.13
6. CODING
The input to the coding phase is the design document. During the coding
phase, different modules identified in the design document are coded
according to the respective module specifications. The objective of the
coding phase is to transform the design of a system, as given by its
module specification, into a high-level language code and to unit test this
code. Good software development organizations require their
programmers to adhere to some well-defined and standard style of
coding called codingstandards
29
Features of Language:
MEAN Stack mainly contains languages like:
JavaScript:
JavaScript is a object-based scripting language.
It is light weighted.
TypeScript:
TypeScript supports JavaScript libraries: The developers can use existing
JavaScript code with the TypeScript. It can use all of the JavaScript frameworks,
tools, and other libraries.
JavaScript is TypeScript: It means the code written in JavaScript with valid .js
extension can be converted to TypeScript by changing the extension from .js to .ts and
compiled with other TypeScript files.
TypeScript is portable: TypeScript is portable because it can be run on any
browsers, devices or any operating systems. It can be run in any environment where
JavaScript runs on. It is not specific to any virtual-machine for execution.
DOM Manipulation: TypeScript can be used to manipulate the DOM for adding or
removing elements similar as of JavaScript.
TypeScript is just a JavaScript: TypeScript code is not understandable by any
browsers directly. TypeScript code starts with JavaScript and ends with JavaScript.
Hence, we only need to know JavaScript to use it in TypeScript. The code is written
30
in TypeScript is compiled and converted into its JavaScript equivalent for the
execution. The above process is known as Trans-piled. With the help of JavaScript
code, browsers are able to read the code and display the output.
JSON:
JSON stands for JavaScript Object Notation.
Codes:
MEAN Stack is based on MVC structure. So you discuss the code according to Model,
View and Controller:
View:
User View:
1. SignIn Component:
HTML:
<div>
<img src="assets/img/single_user.png" id="icon" alt="User Icon" />
</div>
<form #signInForm="ngForm" (ngSubmit)="signInForm.valid &&
onSubmit(signInForm)">
<input type="text" name="email" #email="ngModel" [(ngModel)]="model.email"
placeholder="Email" [pattern]="emailRegex" required
[ngClass]="{'invalid-textbox' :signInForm.submitted && !email.valid }">
<div *ngIf="signInForm.submitted && email.errors?.pattern">
<label class="validation-message">Invalid email address.</label>
</div>
<input type="password" name="password" #password="ngModel"
[(ngModel)]="model.password" placeholder="Password" required minlength="4"
[ngClass]="{'invalid-textbox' :signInForm.submitted && !password.valid }">
<div *ngIf="signInForm.submitted && password.errors?.minlength">
<label class="validation-message">Minimum 4 characters.</label>
</div>
<input type="submit" value="Sign In">
</form>
<!-- Error message -->
31
<div class="alert" *ngIf="serverErrorMessages">
{{serverErrorMessages}}
</div>
Typescript:
import { Component, OnInit } from '@angular/core';
import { NgForm } from "@angular/forms";
import { Router } from "@angular/router";
import { UserService } from '../../shared/user.service';
@Component({
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.css']
})
export class SignInComponent implements OnInit {
constructor(private userService: UserService,private router : Router) { }
model ={
email :'',
password:''
};
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-
9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
serverErrorMessages: string;
ngOnInit() {
if(this.userService.isLoggedIn())
this.router.navigateByUrl('/userprofile');
}
onSubmit(form : NgForm){
this.userService.login(form.value).subscribe(
res => {
this.userService.setToken(res['token']);
this.router.navigateByUrl('/userprofile');
},
err => {
this.serverErrorMessages = err.error.message;
} ); }}
2. SignUp Component:
HTML:
<div>
<img src="/assets/img/users.png" id="icon" alt="User Icon" />
</div>
<form #signUpForm="ngForm" (ngSubmit)="signUpForm.valid &&
onSubmit(signUpForm)">
<input type="text" #fullName="ngModel"
[(ngModel)]="userService.selectedUser.fullName" name="fullName" placeholder="Full
Name"
required [ngClass]="{'invalid-textbox' :signUpForm.submitted && !fullName.valid }">
<div *ngIf="signUpForm.submitted && !fullName.valid">
<label class="validation-message">This field is required.</label>
</div>
<input type="text" #email="ngModel" [(ngModel)]="userService.selectedUser.email"
name="email" placeholder="Email"
required [pattern]="emailRegex" [ngClass]="{'invalid-textbox' :signUpForm.submitted &&
!email.valid }">
32
<div *ngIf="signUpForm.submitted && email.errors">
<label *ngIf="email.errors.required" class="validation-message">This field is
required.</label>
<label *ngIf="email.errors.pattern" class="validation-message">Invalid email
address.</label>
</div>
<input type="number" #phone="ngModel" [(ngModel)]="userService.selectedUser.phone"
name="phone" placeholder="Phone Number"
required [ngClass]="{'invalid-textbox' :signUpForm.submitted && !phone.valid }">
<div *ngIf="signUpForm.submitted && email.errors">
<label *ngIf="email.errors.required" class="validation-message">This field is
required.</label>
<label *ngIf="email.errors.pattern" class="validation-message">Invalid email
address.</label>
</div>
<input type="text" #address="ngModel" [(ngModel)]="userService.selectedUser.address"
name="address" placeholder="Address"
required [ngClass]="{'invalid-textbox' :signUpForm.submitted && !address.valid }">
<div *ngIf="signUpForm.submitted && email.errors">
<label *ngIf="email.errors.required" class="validation-message">This field is
required.</label>
<label *ngIf="email.errors.pattern" class="validation-message">Invalid email
address.</label>
</div>
<input type="password" #password="ngModel"
[(ngModel)]="userService.selectedUser.password" name="password"
placeholder="Password"
minlength="4" required [ngClass]="{'invalid-textbox' :signUpForm.submitted &&
!password.valid }">
<div *ngIf="signUpForm.submitted && password.errors">
<label *ngIf="password.errors.required" class="validation-message">This field is
required.</label>
<label *ngIf="password.errors.minlength" class="validation-message">Enter atleast 4
characters.</label>
</div>
<input type="submit" value="Sign Up">
</form>
<!-- Success message -->
<div class="success" *ngIf="showSucessMessage">
Saved successfully
</div>
<!-- Error message -->
<div class="alert" *ngIf="serverErrorMessages">
{{serverErrorMessages}}
</div>
TypeScript:
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { UserService } from '../../shared/user.service'
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
33
})
export class SignUpComponent implements OnInit {
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-
9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
showSucessMessage: boolean;
serverErrorMessages: string;
constructor(private userService: UserService) { }
ngOnInit() {
}
onSubmit(form: NgForm) {
this.userService.postUser(form.value).subscribe(
res => {
this.showSucessMessage = true;
setTimeout(() => this.showSucessMessage = false, 4000);
this.resetForm(form);
},
err => {
if (err.status === 422) {
this.serverErrorMessages = err.error.join('<br/>');
} else {
this.serverErrorMessages = 'Something went wrong.Please contact admin.';
}
}
);
}
resetForm(form: NgForm) {
this.userService.selectedUser = {
fullName: '',
email: '',
phone: '',
address: '',
password: ''
};
form.resetForm();
this.serverErrorMessages = '';
}
}
3. User-Home Component:
HTML:
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
<!-- Brand -->
<a class="navbar-brand" href="#">Logo</a>
<!-- Links -->
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" routerLink="home1">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="about1">About</a>
</li>
</ul>
<ul class="navbar-nav" *ngFor="let cat of category">
<li class="nav-item">
<a class="nav-link" (click)="onFood(cat.categoryname)">{{cat.categoryname}}</a>
34
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" routerLink="bookhistory">Booking History</a>
</li>
</ul>
<ul class="navbar-nav">
<li *ngIf="userDetails" class="nav-item" style="color:aquamarine">
<a class="nav-link" href="">Welcome User:{{userDetails.fullName.split(' ')[0]}}</a>
</li>
<li>
<button class="btn btn-success" (click)="onLogout()">LOG OUT</button>
</li>
</ul>
</nav>
<router-outlet></router-outlet>
TypeScript:
import { Component, OnInit } from '@angular/core';
import { UserService } from '../shared/user.service';
import { CategoryService } from '../shared/category.service';
import { Category } from '../shared/category.model';
import { Router, ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.css']
})
export class UserProfileComponent implements OnInit {
userDetails;
public category = [];
public id = '';
constructor(private userService: UserService, private router: Router, private catservice:
CategoryService ,
private route: ActivatedRoute) { }
ngOnInit() {
this.getCategory();
this.userService.getUserProfile().subscribe(
res => {
this.userDetails = res['reguser'];
},
err => {
console.log(err);
}
);
this.id = this.route.snapshot.paramMap.get('id');
console.log(this.id);
}
onLogout() {
this.userService.deleteToken();
this.router.navigate(['/login']);
}
onFood(catname) {
this.router.navigate ( [ 'userprofile/food1', {id: catname} ] );
}
getCategory() {
this.catservice.getCategory().subscribe((res) => {
this.category = res as Category[];
});
}
}
35
Admin View:
1. Sign In Component:
HTML:
<div>
<img src="assets/img/single_user.png" id="icon" alt="User Icon" />
</div>
<form #signInForm="ngForm" (ngSubmit)="signInForm.valid &&
onSubmit(signInForm)">
<input type="text" name="email" #email="ngModel" [(ngModel)]="model.email"
placeholder="Email" [pattern]="emailRegex" required
[ngClass]="{'invalid-textbox' :signInForm.submitted && !email.valid }">
<div *ngIf="signInForm.submitted && email.errors?.pattern">
<label class="validation-message">Invalid email address.</label>
</div>
<input type="password" name="password" #password="ngModel"
[(ngModel)]="model.password" placeholder="Password" required minlength="4"
[ngClass]="{'invalid-textbox' :signInForm.submitted && !password.valid }">
<div *ngIf="signInForm.submitted && password.errors?.minlength">
<label class="validation-message">Minimum 4 characters.</label>
</div>
<input type="submit" value="Sign In">
</form>
<!-- Error message -->
<div class="alert" *ngIf="serverErrorMessages">
{{serverErrorMessages}}
</div>
TypeScript:
import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Router } from '@angular/router';
import { UserService } from '../../shared/user.service';
@Component({
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.css']
})
export class SignInComponent implements OnInit {
constructor(private userService: UserService,private router : Router) { }
model = {
email :'',
password:''
};
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-
9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
serverErrorMessages: string;
ngOnInit() {
if(this.userService.isLoggedIn())
this.router.navigateByUrl('/userprofile');
}
36
onSubmit(form : NgForm){
this.userService.login(form.value).subscribe(
res => {
this.userService.setToken(res['token']);
this.router.navigateByUrl('/userprofile');
},
err => {
this.serverErrorMessages = err.error.message;
}
);
}
}
HTML
<div style="text-align:center">
<h1>
Add Category
</h1>
</div>
<div style="margin:20px 50px 20px 50px;">
<form #categoryform="ngForm" (ngSubmit)="onSubmit(categoryform)">
<input type="hidden" name="_id" #_id="ngModel" ngModel
[(ngModel)]="selectedCategory._id">
<div class="form-group">
<label for="category">Category Name</label>
<input type="text" name="category" #qname="ngModel" ngModel
[(ngModel)]="selectedCategory.categoryname" class="form-control" id="inputdefault"
placeholder="Category Name">
</div>
<div class="form-group">
<input type="submit" class="form-control btn btn-success" id="inputdefault">
</div>
</form>
</div>
TypeScript
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { NgForm } from '@angular/forms';
import { CategoryService } from '../../shared/category.service';
import { Category} from '../../shared/categoty.model';
@Component({
selector: 'app-addcategory',
templateUrl: './addcategory.component.html',
styleUrls: ['./addcategory.component.css']
})
export class AddcategoryComponent implements OnInit {
public selectedCategory = new Category();
constructor(private router: Router, private catservice: CategoryService) { }
ngOnInit() {
}
onSubmit(form: NgForm) {
if (form.value._id === '' || form.value._id == null) {
this.catservice.insertCategory(this.selectedCategory).
37
subscribe(
data => console.log('Success', data),
error => console.error('Error', error)
);
alert(' Data Saved Successfully ');
this.router.navigateByUrl('userprofile/ViewCategory');
} else {
console.log(form.value);
}}}
3. Add Food Component:
HTML
<div style="text-align:center">
<h1>
Add Food
</h1>
</div>
<div style="margin:20px 50px 20px 50px;">
<form #Foodform="ngForm" (ngSubmit)="onSubmit(Foodform)" enctype="multipart/form-
data">
<input type="hidden" name="_id" #_id="ngModel" ngModel
[(ngModel)]="selectedFood._id">
<div class="form-group">
<label for="Food">Food Name</label>
<input type="text" name="Food" #qname="ngModel" ngModel
[(ngModel)]="selectedFood.fname" class="form-control" id="inputdefault"
placeholder="Food Name">
</div>
<div class="form-group">
<label for="Food">Food Description</label>
<input type="text" name="Food" #qname="ngModel" ngModel
[(ngModel)]="selectedFood.fdesc" class="form-control" id="inputdefault"
placeholder="Food Description">
</div>
<div class="form-group">
<label for="Food">Food Price</label>
<input type="text" name="Food" #qname="ngModel" ngModel
[(ngModel)]="selectedFood.fprice" class="form-control" id="inputdefault"
placeholder="Food Price">
</div>
<div class="form-group">
<label for="Food">Food Picture</label>
<input type="file" name="photo" [(ngModel)]="selectedFood.fpic" class="form-control"
id="inputdefault" (change)="onfileselect($event)" />
</div>
<div class="form-group">
<label for="Food">Food Category</label>
<select [(ngModel)]="selectedFood.category_id" name="fooa" class="form-control">
<option [selected]="selectedFood.category_id == 'select'" [value]="select">SELECT
CATEGORY</option>
<option *ngFor="let cat of category"
[value]="cat.categoryname">{{cat.categoryname}}</option>
</select>
</div>
<div class="form-group">
<input type="submit" class="form-control btn btn-success" id="inputdefault">
</div>
</form>
</div>
TypeScript:
38
import { Component, OnInit } from '@angular/core';
import { FileUploader, FileSelectDirective } from 'ng2-file-upload/ng2-file-upload';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { NgForm } from '@angular/forms';
import { FoodService } from '../../shared/food.service';
import { CategoryService} from '../../shared/category.service';
import { Category } from '../../shared/categoty.model';
import { Food} from '../../shared/food.model';
const URL = 'http://localhost:3000/pics';
@Component({
selector: 'app-addfood',
templateUrl: './addfood.component.html',
styleUrls: ['./addfood.component.css']
})
export class AddfoodComponent implements OnInit {
public selectedFood = new Food();
public category = [];
selectedfile: File = null;
public uploader: FileUploader = new FileUploader({url: URL, itemAlias: 'photo'});
constructor(private http: HttpClient, private router: Router, private catservice:
CategoryService, private foodservice: FoodService) { }
ngOnInit() {
this.getCategory();
}
getCategory() {
this.catservice.getCategory().subscribe((res) => {
t}h)i;s.category = res as Category[];
}
onfileselect(event) {
this.selectedfile = <File>event.target.files[0];
}
onSubmit(form: NgForm) {
form.value.photo = this.selectedfile.name;
this.selectedFood.fpic = form.value.photo;
const fd = new FormData();
fd.append('image', this.selectedfile, this.selectedfile.name);
this.http.post('http://localhost:3000/pics', fd).subscribe( res => {
});
this.http.post('http://localhost:4200/assets', fd).subscribe( res => {
});
this.foodservice.insertFood(this.selectedFood).
subscribe(
data => console.log('Success', data),
error => console.error('Error', error)
);
alert(' Data Saved Successfully ');
this.router.navigateByUrl('userprofile/ViewFood');
}
}
HTML
<div class="viewcat" style="background-color: aquamarine; max-height: 300vh;">
39
<div class="container">
<h2>View Category</h2>
<table class="table table-hover">
<tr>
<th>Sl No.</th>
<th>Catgory Name</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<tr *ngFor="let cat of category;let i = index">
<td>{{i+1}}</td>
<td>{{cat.categoryname}}</td>
<td><a routerLink="../EditCategory/{{cat._id}}"><img src="assets/logo/edit.png"
id="icon" height="50" width="50" alt="User Icon" /></a></td>
<td><a class="action-btn" (click)="onDelete(cat._id)"><img
src="assets/logo/delete.png" id="icon" height="50" width="50" alt="User Icon" /></a></td>
</tr>
<router-outlet></router-outlet>
</table>
</div>
</div>
TypeScript
import { Component, OnInit } from '@angular/core';
import { Router} from '@angular/router';
import { CategoryService } from '../../shared/category.service';
import { Category } from '../../shared/categoty.model';
@Component({
selector: 'app-viewcategory',
templateUrl: './viewcategory.component.html',
styleUrls: ['./viewcategory.component.css']
})
export class ViewcategoryComponent implements OnInit {
public category = [];
constructor(private router: Router, private catservice: CategoryService) { }
ngOnInit() {
this.getCategory();
this.refresh();
}
getCategory() {
this.catservice.getCategory().subscribe((res) => {
this.category = res as Category[];
});
}
refresh() {
this.catservice.getCategory().subscribe((res) => {
t}h)i;s.category = res as Category[] ;
}
onDelete(_id: string) {
if (confirm('Are you sure to delete this record ?') === true) {
this.catservice.deleteCategory(_id).subscribe((res) => {
});
this.refresh();
}
}
}
40
View Food Component
HTML
<div class="viewcat" style="background-color: aquamarine; max-height: 300vh;">
<div class="container">
<h2>View Category</h2>
<table class="table table-hover">
<tr>
<th>Sl No.</th>
<th>Food Name</th>
<th>Description</th>
<th>Price</th>
<th>Picture</th>
<th>Category</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<tr *ngFor="let food of foods;let i = index">
<td>{{i+1}}</td>
<td>{{food.fname}}</td>
<td>{{food.fdesc}}</td>
<td>{{food.fprice}}</td>
<td><img [src]="getSafeUrl(food.fpic)" height="100" width="100"></td>
<td>{{food.category_id}}</td>
<td><a routerLink="../EditCategory/"><img src="assets/logo/edit.png" id="icon"
height="50" width="50" alt="User Icon" /></a></td>
<td><a class="action-btn"><img src="assets/logo/delete.png" id="icon" height="50"
width="50" alt="User Icon" /></a></td>
</tr>
<router-outlet></router-outlet>
</table>
</div>
</div>
TypeScript
import { Component, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { uploads } from '../../../../../server';
import { Router} from '@angular/router';
import { FoodService } from '../../shared/food.service';
import { Food } from '../../shared/food.model';
import { Category } from 'src/app/shared/categoty.model';
declare var require: any;@Component({
selector: 'app-viewfood',
templateUrl: './viewfood.component.html',
styleUrls: ['./viewfood.component.css']
})
export class ViewfoodComponent implements OnInit {
// imgname = require('F:/login/server/uploads/download1.jpg');
public apiurl = 'http://localhost:3000';
trustedUrl;
public foods = [];
constructor(private fservice: FoodService , private sanitizer: DomSanitizer) {
this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl(this.apiurl);
}
getFOoddetails() {
this.fservice.getFood().subscribe((res) => {
t}h)i;s.foods = res as Food[];
}
getSafeUrl(fpic) {
return this.sanitizer.bypassSecurityTrustResourceUrl(this.apiurl + '/' + fpic);
}ngOnInit() {
this.getFOoddetails();
}
41
Model:
Categorys Model
const mongoose = require('mongoose');
var Category = mongoose.model('Category',{ //give model name in singular so that it
chnages to plural
categoryname:{type: String},
});
module.exports={Category};
Foods Model
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Food = mongoose.model('Food',{ //give model name in singular so that it chnages to
plural
fname:{type: String},
fdesc:{type: String},
fprice:{type: Number},
fpic:{type: String},
//category_id:{type: Schema.Types.ObjectId}
category_id:{type:String}
});
module.exports={Food};
RegUsers Model
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
var reguserSchema = new mongoose.Schema({
fullName: {
type: String,
required: 'Full name can\'t be empty'
},
email: {
type: String,
required: 'Email can\'t be empty',
unique: true
},
phone: {
type: String,
required: 'Phone can\'t be empty',
unique: true
},
address: {
type: String,
required: 'Address can\'t be empty',
},
password: {
type: String,
required: 'Password can\'t be empty',
minlength: [4, 'Password must be atleast 4 character long']
},
saltSecret: String
});
// Custom validation for email
reguserSchema.path('email').validate((val) => {
42
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-
9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
// Events
reguserSchema.pre('save', function (next) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(this.password, salt, (err, hash) => {
this.password = hash;
this.saltSecret = salt;
next();
});
});
});
// Methods
reguserSchema.methods.verifyPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};
reguserSchema.methods.generateJwt = function () {
return jwt.sign({ _id: this._id},
process.env.JWT_SECRET,
{
expiresIn: process.env.JWT_EXP
});
}
mongoose.model('Reguser', reguserSchema);
Users Model
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
var userSchema = new mongoose.Schema({
fullName: {
type: String,
required: 'Full name can\'t be empty'
},
email: {
type: String,
required: 'Email can\'t be empty',
unique: true
},
password: {
type: String,
required: 'Password can\'t be empty',
minlength: [4, 'Password must be atleast 4 character long']
},
saltSecret: String
});
// Custom validation for email
userSchema.path('email').validate((val) => {
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-
9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
// Events
userSchema.pre('save', function (next) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(this.password, salt, (err, hash) => {
43
this.password = hash;
this.saltSecret = salt;
next();
});
});
});
// Methods
userSchema.methods.verifyPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};
userSchema.methods.generateJwt = function () {
retpuroncjewsst..seingvn.(J{W_Tid_:StE
hiCs.R
_iEdT},
{
expiresIn: process.env.JWT_EXP
});
}
mongoose.model('User', userSchema);
Orders Model
const mongoose=require('mongoose')
var Order=mongoose.model('order',{
})
module.exports={Order}
Controller:
44
module.exports.register = (req, res, next) => {
var user = new User();
user.fullName = req.body.fullName;
user.email = req.body.email;
user.password = req.body.password;
user.save((err, doc) => {
if (!err)
res.send(doc);
else {
if (err.code == 11000)
res.status(422).send(['Duplicate email adrress found.']);
else
return next(err);
}
});
}
module.exports.authenticate = (req, res, next) => {
// call for passport authentication
passport.authenticate('local', (err, user, info) => {
// error from passport middleware
if (err) return res.status(400).json(err);
// registered user
else if (user) return res.status(200).json({ "token": user.generateJwt() });
// unknown user or wrong password
else return res.status(404).json(info);
})(req, res);
}
module.exports.userProfile = (req, res, next) =>{
User.findOne({ _id: req._id },
(err, user) => {
if (!user)
return res.status(404).json({ status: false, message: 'User record not found.' });
else
return res.status(200).json({ status: true, user : _.pick(user,['fullName','email']) });
}
);
}
45
}
module.exports.authenticate1 = (req, res, next) => {
// call for passport authentication
passport.authenticate('local1', (err, reguser, info) => {
// error from passport middleware
if (err) return res.status(400).json(err);
// registered reguser
else if (reguser) return res.status(200).json({ "token": reguser.generateJwt() });
// unknown reguser or wrong password
else return res.status(404).json(info);
})(req, res);
}
module.exports.reguserProfile1 = (req, res, next) =>{
Reguser.findOne({ _id: req._id },
(err, reguser) => {
if (!reguser)
return res.status(404).json({ status: false, message: 'reguser record not found.' });
else
return res.status(200).json({ status: true, reguser :
_.pick(reguser,['fullName','email']) });
}
);
}
3. Food Controller
const express=require('express');
var router=express.Router();
const mongoose = require('mongoose');
var ObjectId = require('mongoose').Types.ObjectId;
//var {Category} = require('../models/categoryModel');
var {Food} = require('../models/foodModel');
var {Category}=require('../models/categoryModel');
46
else console.log('Error Retriving Food Data : ' + JSON.stringify(err));
});
});
//update the database
router.put('/:id',(req, res) => {
if(!ObjectId.isValid(req.params.id))
return res.status(400).send('No record with given Id : ${req.params.id}');
var updateData={
fname: req.body.fname,
fdesc: req.body.fdesc,
fprice: req.body.fprice,
fpic: req.body.fpic,
category_id: req.body.category_id,
};
Food.findByIdAndUpdate(req.params.id, {$set: updateData}, {new: true}, (err, doc) => {
if(!err) res.send(doc);
else console.log('Error in Updating Update : '+JSON.stringify(err, undefined, 2));
});
});
//delete from database
router.delete('/:id',(req, res) => {
if(!ObjectId.isValid(req.params.id))
return res.status(400).send('No records with given id : ${req.params.id}');
Food.findByIdAndRemove(req.params.id, (err, doc) => {
if(!err) res.send(doc);
else console.log('No record with the given Id : '+JSON.stringify(err, undefined, 2));
});
});
module.exports = router;
4. UserFood Controller
const express = require('express');
var router = express.Router();
var ObjectId = require('mongoose').Types.ObjectId;
var { Food } = require('../models/foodModel');
router.get('/:category_id', (req, res) => {
Food.find({category_id:req.params.category_id}, (err, doc) => {
if (!err) { res.send(doc); }
else { console.log('Error in Retriving :' + JSON.stringify(err, undefined, 2)); }
});
});module.exports = router;
47
7. TESTING
Fig- 7.1
Messege from webpage:
Fig- 7.2
48
Data Stored in Database:
Fig – 7.3
User Chooses a food and places a order and confirmation message appears:
Fig – 7.4
49
Booking Details is shown to user:
Fig 7.5
Fig – 7.6
50
Test Case-3 (Test to enter food category):
Category of a food entered by Admin:
Fig – 7.7
Fig – 7.8
51
Data saved in database:
Fig – 7.9
Fig – 7.10
52
Message from web page:
Fig – 7.11
Fig – 7.12
53
Test Case-5 (Error Messages)
Duplicate email found:
Fig – 7.13
Wrong email id or password:
Fig – 7.14
54
8. Contribution Of Work
TASKS PERFORMED BY
9. FUTURE SCOPE
“Online Food Ordering System” is a application to save time to order foods from restaurant.
But this application can be more useful with the following features:
1. This application can take order from one restaurant. But in future it can be modified
with the feature of taking orders from multiple restaurants.
2. Live Tracking of order can be added as feature.
10. CONCLUSION
Technology makes life easier. This application is made to save some important time in daily
life. But we should not forget about spending great time in restaurants with friends and
family, which is also important for social life. Because technology is not for making barriers
in social life, it is for making a better life.
55
11. REFERENCES
URLs:
1. https://www.w3schools.com/
2. https://www.tutorialspoint.com
3. https://www.nodejs.org
4. https://www.mongodb.com
5. https://www.angular.io
56