[go: up one dir, main page]

0% found this document useful (0 votes)
70 views41 pages

Project Chat App

Download as doc, pdf, or txt
Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1/ 41

Project Report

ON
“Chat APP”

Submitted to
Mr. Nitish Vashishtha

DR.A.P.J.ABDUUL KALAM TECHNICAL UNIVERSIITY


LUCKNOW (UP) INDIA

Submitted by
Karan Kumar 2202310140048
Uvesh 2202310140111
Saurabh Yadav 2202310140095
Priyanshu Singh 2202310140074

Under the Guidance of

“MR. NITISH VASHISHTHA”

DEPARTMENT OF MASTER OF COMPUTER APPLICATION


R.D.ENGINNEERING COLLEGE GHAZIABAD
2023-2024
TABLE OF CONTENT
Sr, No Topic Name
1 Introduction
2 Background
3 Objective
4 Purpose, Scope and Applicability
5 Purpose
6 Scope
7 Applicability
8 Existing System
9 Proposed System
10 Requirement Analysis
11 Hardware Requirement
12 Software Requirement
13 Justification of selection of Technology
14 System Design
15 Module Division
16 Data Dictionary
17 ER Diagram
18 DFD / UML Diagram
19 Implementation
20 Code
21 Testing Approach
22 Unit Testing (Test Cases and Test Result )
23 Integration System
24 Result and Discussion
25 Conclusion and Future work
26 Reference
Introduction

Project Overview :
The Chat App project involves the development of a comprehensive real-time messaging
application utilizing the MERN (MongoDB, Express.js, React.js, Node.js) stack. The
application serves as a platform for users to engage in instant messaging, facilitating
both one-on-one and group conversations in real-time. Through this project, we aim to
demonstrate the capabilities of the MERN stack in building robust, scalable, and
responsive web applications, particularly in the context of communication tools.

Key Features and Functionality:

1. Real-Time Messaging: Users can exchange messages instantly with other


users, creating a seamless communication experience.

2. One-on-One Conversations: Users can initiate private conversations with


individuals, ensuring privacy and confidentiality in their interactions.

3. Group Chat: Users have the ability to create and participate in group conversations,
allowing for collaboration and communication among multiple users simultaneously.

4. User Authentication: Secure user authentication and authorization


mechanisms are implemented to ensure that only authenticated users can
access the application and engage in conversations.

5. User Profiles: Users have customizable profiles where they can add
personal information, profile pictures, and manage their settings.

6. Message Notifications: Users receive notifications for new messages, ensuring that they
stay updated on their conversations even when they are not actively using the application.

7. Search Functionality: Users can search for specific messages or


conversations, making it easy to find relevant information within the application.

8. Responsive Design: The application is designed to be responsive across


various devices and screen sizes, providing users with a consistent experience
whether they are using a desktop, tablet, or mobile device.
Technologies Used:

1. MongoDB: A NoSQL database used for storing user data, messages, and
other application information.

2. Express.js: A web application framework for Node.js used for building the
backend API and handling HTTP requests.

3. React.js: A JavaScript library used for building the user interface and frontend
components of the application.

4. Node.js: A JavaScript runtime environment used for running the backend


server and handling server-side logic.

5. Socket.io: A library for real-time web applications used for enabling real-time
communication between clients and the server.

6. JSON Web Tokens (JWT): Used for implementing secure authentication and
authorization mechanisms within the application.

7. Tailwind CSS: A frontend framework used for designing responsive and


mobile-first web pages.

By leveraging these technologies and implementing the aforementioned features,


the Chat App project aims to showcase the power and versatility of the MERN
stack in developing modern and feature-rich web applications.
BACKGROUOND
A chat app is a digital platform that enables users to communicate with one another in real-
time through text-based messages. Typically, users can exchange messages individually or
in group conversations. These apps often feature additional functionalities such as
multimedia sharing (photos, videos, files), emoji support, and sometimes voice or video
calling capabilities. Chat apps can be used for various purposes, including personal
communication, professional collaboration, customer support, and community building.
They are available on multiple platforms, including smartphones, tablets, and desktop
computers, allowing users to stay connected regardless of their device or location. Overall,
chat apps play a crucial role in modern communication, facilitating instant and convenient
interaction between individuals and groups across the globe.

Key features of chat apps include:

Instant Messaging: Users can send and receive messages instantly,


allowing for rapid communication.

Multimedia Sharing: Users can share photos, videos, documents, and other
files within chat conversations, enhancing communication capabilities.

Emoji and Stickers: Many chat apps support a wide range of emojis, stickers,
and GIFs to express emotions and add personality to conversations.

Voice and Video Calls: Some chat apps offer additional features such as voice calling
and video conferencing, enabling users to communicate using audio and video.

Presence Indicators: Users can see when their contacts are online or active,
providing insight into their availability for communication.

Notifications: Chat apps typically send notifications to users when they receive
new messages, ensuring that important conversations are not missed.

Encryption and Security: To protect user privacy, many chat apps employ end-to-
end encryption, ensuring that only the sender and recipient can read the messages.

Customization: Users can often customize their chat experience by changing


themes, backgrounds, and notification settings according to their preferences.

Integration with Other Services: Some chat apps integrate with other platforms and services,
allowing users to seamlessly share content or perform actions without leaving the app.
Objective

1. Design and develop a user-friendly interface for seamless communication and interaction.

2. Implement real-time messaging functionality using WebSockets to enable


instantaneous message delivery.

3. Ensure robust data security and privacy through effective user


authentication and authorization mechanisms.

4. Showcase the versatility and effectiveness of the MERN stack in building


dynamic and responsive web applications. , add more details of this paragraph
PURPOSE, SCOPE AND APPLILCABILTIY:

PURPOSE:
The purpose of this project is twofold: firstly, to address the growing need for efficient and intuitive
messaging applications that cater to modern communication preferences, and secondly, to showcase
the effectiveness of the MERN stack in developing such applications. By providing users with a
feature-rich chat platform, we aim to enhance communication experiences while highlighting the
versatility and flexibility of MERN technologies in web development.

SCOPES:
The scope of the project encompasses the entire development lifecycle of the chat application,
including requirements gathering, system design, implementation, testing, and deployment. Key
features to be included in the application comprise user authentication, real-time messaging
functionality, group chat capabilities, multimedia support, and integration with external services
for enhanced functionality. Additionally, the project will explore considerations such as data
security, scalability, and user experience to deliver a comprehensive solution.

Not in Scope:

The following use-cases are out scope:


1. Message Delete functionality is not available.,
2. Profile Picture not set by Gallery only select avatars.
3. Only Chat can be done not send any other files, like – photo, video, etc.
4. Location Functionality is not available.
5. All User will be shown , If any User Register here.
System Design

Requirement analysis is indeed a crucial phase in the system analysis and design
process, especially for developing a chat application. Let's expand on the
importance and key activities involved in requirement analysis:

Gathering Requirements: The first step is to gather requirements from stakeholders, including
end-users, business owners, and any other parties involved. This can be achieved through
interviews, surveys, workshops, and brainstorming sessions. During this process, it's essential to
capture both functional requirements (what the system should do) and non-functional
requirements (qualities the system should have), such as performance, security, and usability.

Documenting Requirements: Once requirements are gathered, they need to be


documented in a clear and structured manner. This documentation typically
includes user stories, use cases, requirements specifications, and system
constraints. Each requirement should be documented with details such as its
description, priority, acceptance criteria, and any dependencies or assumptions.

Analyzing Requirements: After documenting requirements, they need to be analyzed to


ensure they are clear, complete, and consistent. This involves reviewing requirements
with stakeholders to validate their accuracy and relevance. Any ambiguities or conflicts
in requirements should be resolved through discussions and clarification sessions.

Prioritizing Requirements: Not all requirements are of equal importance. Prioritizing


requirements helps in determining which features are essential for the initial release
and which can be deferred to future releases. Prioritization can be based on factors
such as business value, user needs, technical feasibility, and project constraints.

Managing Changes: Requirements are likely to evolve throughout the project lifecycle due to
changing business needs, user feedback, or technological advancements. It's essential to have a
process in place for managing changes to requirements, including documenting change requests,
evaluating their impact, and obtaining approval from stakeholders before implementing them.

Ensuring Traceability: Traceability ensures that each requirement can be traced back
to its source and that all requirements are addressed during development and
testing. This involves establishing links between requirements, design elements, and
test cases to ensure alignment throughout the software development lifecycle.

Communication and Collaboration: Effective communication and collaboration are critical


throughout the requirement analysis phase. This includes regular interactions with stakeholders
to gather feedback, address concerns, and ensure alignment between business goals and project
objectives. Collaborative tools such as issue trackers, version control systems, and project
management platforms can facilitate communication and collaboration among team members.
System Architecture

Frontend Layer :

The frontend layer of the chat application is responsible for rendering the user interface and
facilitating user interactions. It comprises components developed using React.js, a JavaScript
library for building dynamic and interactive UIs. Components include the chat window, message
input field, user list, and any other UI elements necessary for the chat experience. These
components are designed to be modular, reusable, and responsive across different devices and
screen sizes. React Router may be utilized for client-side routing, enabling navigation between
different views within the application, such as chat rooms, user profiles, and settings pages. The
frontend communicates with the backend via RESTful APIs and WebSocket connections to send
and receive messages, update user statuses, and fetch chat histories.

Backend Layer :

The backend layer is responsible for handling business logic, data processing, and
communication with the database. It is implemented using Node.js and Express.js, forming
the server-side logic of the application. Express.js provides a minimalist framework for
defining routes, middleware, and request handling logic. Routes are defined to handle HTTP
requests from the frontend, such as sending messages, retrieving chat histories, and
managing user authentication. WebSocket connections are established using libraries like
Socket.IO to enable real-time communication between clients and the server. This allows for
instant message delivery and updates without the need for frequent polling. MongoDB, a
NoSQL database, is used to store chat messages, user profiles, and other application data.
MongoDB's flexibility and scalability make it well-suited for managing unstructured data in a
chat application environment. Mongoose, an ODM (Object Data Modeling) library for
MongoDB, may be used to define data schemas, perform database operations, and handle
data validation within the Node.js environment.

Communication Protocols :

RESTful APIs are employed for asynchronous communication between the frontend and
backend layers. REST endpoints are defined to handle CRUD (Create, Read, Update,
Delete) operations on resources such as messages, users, and chat rooms. WebSocket
connections are used for real-time communication between clients and the server. This
enables features like instant message delivery, typing indicators, and online presence
notifications. WebSocket connections are established and maintained using libraries like
Socket.IO, ensuring bi-directional communication with minimal latency.
Deployment Topology :

The chat application can be deployed using containerization technologies such as Docker,
allowing for easy scalability and portability across different environments. Deployment
orchestration tools like Kubernetes may be used to manage containerized instances of the
application, ensuring high availability, fault tolerance, and efficient resource utilization. Load
balancers and reverse proxies like NGINX can distribute incoming traffic across multiple
instances of the application, improving scalability and reliability. Scalability, Fault Tolerance,
and Performance Optimization: Horizontal scalability is achieved by deploying multiple
instances of the application across distributed environments. This allows the system to
handle increased load and accommodate growing user bases. Fault tolerance is ensured
through redundancy and failover mechanisms. High availability is maintained by replicating
data across multiple database instances and implementing automated backup and recovery
processes. Performance optimization techniques such as caching, compression, and
asynchronous processing are employed to minimize response times and improve overall
system responsiveness. CDN (Content Delivery Network) integration may also be utilized to
accelerate content delivery to users across different geographical regions.

By considering these architectural aspects, the chat application can be designed to be


scalable, resilient, and performant, providing users with a seamless real-time communication
experience while maintaining the flexibility and versatility of the MERN stack.
Hardware and Software Requirement:

Hardware:
1. 3 GB RAM but 8GB recommended,

2. 2GB HDD space but 4GB recommended,


3. Windows, Linux or Mac all platforms,
4. Monitor resolution needs to be 1280x800 minimum,
Software:

1, ReactJS
2, Visual Studio
Language:
Front-End Languages:
Html, CSS, JavaScript
Back-End Languages:
NodeJS ,Express
Server:
Firebase, Firebase Storage, Firebase Authentication, Firebase Framework,

Preliminary Product Description:


The aim of developing this clone project is to adding new feature to the Chat-App
application and test how it is working and how much people will love it and use it,
before adding any new feature to real Chat-App application, the developer who
brings new such ideas like this first test this by making its clone application,

We can play games will using this social media, and we can share our scores by
friends by posting it on stories where more friends can play together and share
new creative ideas, We can also get to from where the person is locating,
Basic Modules:
There are various modules in this project we are going to add such as

• Sign-Up Page
• Login Page
• Home Page
• User Dashboard
• Set Avatar Page
Implementation
MongoDB Installation and Configuration: - MongoDB is a NoSQL database used as the backend
database in MERN stack applications. It stores data in flexible, JSON-like documents, making it
suitable for managing unstructured data. - To set up MongoDB, developers can download and
install the MongoDB Community Server from the official MongoDB website. Alternatively, they
can use cloud-based MongoDB services like MongoDB Atlas for easy setup and management. -
Once installed, developers need to configure MongoDB by specifying the data directory, port
number, authentication settings, and other options in the MongoDB configuration file
(mongod.conf). They can also set up authentication mechanisms like username/password
authentication or SSL/TLS encryption for enhanced security.

2. Express.js and Node.js Setup: - Express.js is a web application framework for Node.js,
used for building server-side logic and APIs in MERN stack applications. - Developers
can set up Express.js and Node.js by installing Node.js from the official Node.js website
or using a package manager like npm (Node Package Manager) or Yarn. - Once Node.js
is installed, developers can create a new Node.js project and initialize it with npm to
install Express.js and other dependencies. They can then create an Express.js server file
to define routes, middleware, and other server-side logic.

3. React.js Configuration: - React.js is a JavaScript library used for building user interfaces in
MERN stack applications. It enables developers to create dynamic and interactive UI components.
- Developers can set up React.js by creating a new React.js project using tools like Create React
App or by setting up a custom React.js project manually. - Once the React.js project is set up,
developers can install additional dependencies and configure the project structure according to
their requirements. They can create React components, define routes using React Router, and
manage application state using tools like Redux or React Context API.

4.Webpack, Babel, and ESLint Integration: - Webpack is a module bundler used to bundle
JavaScript, CSS, and other assets for deployment in MERN stack applications. - Babel is a
JavaScript compiler that converts ECMAScript 2015+ code (ES6+) into a backwards-compatible
version of JavaScript that can be run in older browsers. - ESLint is a static code analysis tool
used to identify and fix problems in JavaScript code. It helps enforce coding standards, catch
potential bugs, and improve code quality and consistency. - Developers can integrate Webpack,
Babel, and ESLint into their MERN stack projects by configuring them in the project's build
system. They can define Webpack configuration files (webpack.config.js), Babel presets and
plugins, and ESLint rules to customize the development workflow and ensure code quality. By
setting up the MERN stack development environment with MongoDB, Express.js, Node.js, and
React.js, and integrating tools like Webpack, Babel, and ESLint, developers can streamline the
development process and ensure a smooth and efficient development experience for building
modern web applications.
Frontend
Designing and Implementing Reusable Components: - React.js promotes a component-based
architecture, where UIs are composed of reusable and modular components. Frontend developers
design and implement these components to represent various UI elements such as chat windows,
message input fields, user avatars, and notification alerts. - Each component encapsulates its
own logic, state, and presentation, making it easier to maintain, test, and reuse throughout the
application. Components can be organized hierarchically to compose complex UI structures, with
parent components passing data and behavior down to child components via props.

2. Managing Application State: - React.js provides built-in state management tools, such
as useState and useEffect hooks, for managing component state and side effects.
Developers leverage these hooks to manage local component state, handle user
interactions, and trigger updates to the UI. - For more complex state management
requirements, developers may use external libraries like Redux or MobX. These libraries
provide centralized state management solutions, allowing developers to define global
application state and dispatch actions to modify state across multiple components.

3. Integrating with Backend APIs: - Frontend developers integrate React.js components with
backend APIs to fetch and update data asynchronously. This involves making HTTP requests to
backend endpoints using libraries like Axios or the built-in fetch API. - Data fetched from the
backend, such as chat messages, user profiles, and authentication tokens, is consumed by React
components and displayed in the UI. Similarly, user interactions, such as sending messages or
updating user preferences, trigger corresponding API requests to update data on the server.

4. Responsive Design: - Responsive design ensures that the chat application's UI adapts
gracefully to different screen sizes and devices, providing a consistent user experience
across desktops, tablets, and smartphones. Frontend developers use CSS media queries
and flexible layout techniques to create responsive UIs that adjust based on viewport
dimensions. - Components are designed to be fluid and flexible, allowing them to
expand, shrink, or reposition dynamically as the viewport size changes.

5. Accessibility:- Accessibility is a critical consideration in frontend development, ensuring


that the chat application is usable by all users, including those with disabilities or
impairments. Frontend developers adhere to accessibility standards and best practices, such
as semantic HTML markup, keyboard navigation, and ARIA roles and attributes. -
Components are designed with accessibility in mind, providing alternative text for images,
focus management for interactive elements, and sufficient color contrast for readability.

6. User Experience Optimization: - Frontend developers focus on optimizing the user


experience to provide a seamless and intuitive interface for users. This involves optimizing
performance, minimizing latency, and reducing friction in user interactions. - Techniques
such as lazy loading, code splitting, and caching are used to improve application load times
and responsiveness. Smooth transitions, animations, and feedback mechanisms enhance the
user experience and make the application more engaging and interactive.
Integration
1. Defining API Contracts and Data Formats: - API contracts define the structure and behavior of
the RESTful APIs used for communication between the frontend and backend layers. This
includes specifying the endpoints, HTTP methods, request and response payloads, and error
handling mechanisms. - Backend developers document the API contracts using tools like
Swagger/OpenAPI or Postman collections, providing a clear reference for frontend developers to
consume the APIs. - Data formats such as JSON (JavaScript Object Notation) are commonly used
for serializing and deserializing data exchanged between the frontend and backend layers due to
their simplicity, readability, and compatibility with JavaScript.

2. Handling Cross-Origin Resource Sharing (CORS): - CORS is a security feature implemented by


web browsers to restrict cross-origin HTTP requests initiated by client-side scripts. When the
frontend and backend components are hosted on different domains or ports, CORS issues may
arise. - Backend developers configure CORS policies on the server to specify which origins are
allowed to access the APIs. This involves setting appropriate CORS headers in HTTP responses
to indicate the allowed origins, methods, and headers. - Frontend developers ensure that requests
originating from the frontend application comply with the CORS policies defined by the backend
server, preventing CORS-related errors during API calls.

3. Implementing Error Handling and Logging Mechanisms: - Error handling mechanisms


are implemented in both frontend and backend components to handle errors gracefully
and provide meaningful feedback to users. - Backend developers define error response
formats and status codes to communicate errors effectively to the frontend. Custom
error middleware or global error handlers may be implemented to centralize error
handling logic and improve maintainability. - Logging mechanisms are implemented to
record important events, errors, and debugging information in both frontend and
backend components. This helps developers diagnose issues, monitor application
performance, and troubleshoot problems in production environments.

4. Integration Testing: - Integration testing verifies the correctness and reliability of the
communication between frontend and backend components, ensuring that they work
together seamlessly. - Test cases are designed to simulate various scenarios, such as user
authentication, message sending/receiving, and error handling, to validate the behavior of
the integrated system. - Automated testing frameworks like Jest, Mocha, or Cypress may be
used to automate the execution of integration tests, allowing for continuous testing and rapid
feedback during development iterations. - Integration tests cover end-to-end scenarios, from
the frontend UI components making API requests to the backend processing those requests
and returning responses, ensuring that the entire system behaves as expected.
Conclusion
In conclusion, the Chat App project represents a significant achievement in
showcasing the versatility and effectiveness of the MERN stack in building
modern web applications. Throughout the project lifecycle, from initial
conception to final delivery, several key accomplishments have been made:

1. Successful Technology Integration:


The project effectively integrated a range of technologies and frameworks within the
MERN stack, including MongoDB, Express.js, React.js, and Node.js. Each component
played a crucial role in enabling various functionalities of the chat application, from data
storage and server-side logic to dynamic user interfaces and real-time messaging.

2. Robust and Feature-Rich Functionality:


The chat application boasts a comprehensive set of features designed to
enhance user experience and facilitate seamless communication. Users can
register and authenticate securely, engage in one-on-one or group conversations,
share multimedia content, and customize their profiles. The application's intuitive
interface and smooth navigation contribute to a satisfying user experience.

3. Scalable and Responsive Architecture:


Leveraging the capabilities of the MERN stack, the chat application demonstrates scalability
and responsiveness, capable of handling increasing user loads and message volumes without
sacrificing performance. The architecture's flexibility allows for future expansion and optimization to
accommodate evolving user needs and technological advancements.

4. Thorough Analysis and Iterative Development:


The project adhered to best practices in software development, including
rigorous requirement analysis, systematic design, iterative development cycles,
and comprehensive testing. By prioritizing user feedback and continuously
refining the application based on insights gained from testing and evaluation

5. Effective Communication and Collaboration:


Successful project outcomes were facilitated by effective communication and
collaboration among team members, stakeholders, and end-users. Transparent communication
channels, regular progress updates, and collaborative decision-making processes fostered a
positive working environment and ensured alignment with project goals and objectives.
Code

Frontend

Main Page

import React from 'react'


import {BrowserRouter,Route,Routes} from 'react-router-dom';
import Register from './pages/Register'; import Login from
'./pages/Login';
import Chat from './pages/Chat';
import SetAvatar from './pages/SetAvatar';

function App() {
return (
<BrowserRouter>
<Routes>
<Route path='/register' element={<Register/>}/>
<Route path='/login' element={<Login/>}/>
<Route path='/setAvatar' element={<SetAvatar/>}/>
<Route path='/' element={<Chat/>}/>
</Routes>
</BrowserRouter>

)
}

export default App


Register Page :
import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-
dom"; import styled from "styled-components";
import Logo from "../assets/logo.svg";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css"; import
axios from "axios";
import { registerRoute } from "../utils/APIRoutes";
import {auth, provider} from '../utils/configure';
import { signInWithPopup } from 'firebase/auth';

function Register() {
const [gvalue, setGvalue] = useState({username: "",email:
"",password: "123456",}); const handleClick=async()=>{
try{
const result=await signInWithPopup(auth,provider)
console.log(result);
setGvalue({username:result.user.displayName,email:result.user.email});
console.log(gvalue,'gvaluedd')
}catch(err){
console.log("Cant login with google",err);
}
}

const navigate = useNavigate();


const [values, setValues] = useState({
username: "",
email: "",
password: "",
confirmPassword: "",
});
const toastOptions = {
position: "bottom-right",
autoClose: 8000,
pauseOnHover: true,
draggable: true,
theme: "dark",
};
useEffect(() => {
if (localStorage.getItem("chat-app-user")) {
navigate("/setAvatar");
}
}, [navigate]);

const handleSubmit = async (event) => {


event.preventDefault();
if (handleValidation()) {
const { password, username, email } = values;
const { data } = await
axios.post(registerRoute, { username,
email,
password,
});
if (data.status === false) {
toast.error(data.msg, toastOptions);
}
if (data.status === true) {
localStorage.setItem("chat-app-user", JSON.stringify(data.user));
navigate("/login");
}
}
};
const handleValidation = () => {
const { password, confirmPassword, username, email }
= values; if (password !== confirmPassword)
{ toast.error("Password should be same", toastOptions);
return false;
} else if (username.length < 3) {
toast.error("UserName Must be greater",
toastOptions); return false;
} else if (password.length < 5) {
toast.error("Passowrd should Be greater than 6 characters",
toastOptions); return false;
} else if (email === "") {
toast.error("Email required", toastOptions);
return false;
}
return true;
};
const handleChange = (event) => {
setValues({ ...values, [event.target.name]: event.target.value });
};
return (
<>
<FormContainer className="form">
<form
className="mainForm"
onSubmit={(event) => {
handleSubmit(event);
}}
>
<div className="brand">
<img className="regImg" src={Logo}
alt="Logo" /> <h1>Secret Chats</h1>
</div>
<input
type="text"
name="username"
placeholder="UserName"
onChange={(e) => handleChange(e)}
/>
<input
type="email"
name="email"
placeholder="Email"
onChange={(e) => handleChange(e)}
/>
<input
type="password"
name="password"
placeholder="Password"
onChange={(e) => handleChange(e)}
/>
<input
type="password"
name="confirmPassword"
placeholder="Confirm password"
onChange={(e) => handleChange(e)}
/>
<button type="submit">Create User</button>
<botton onClick={handleClick}> Log in with Google
</botton> <span>
already have an account ? <Link
to="/login">Login</Link> </span>
</form>
</FormContainer>
<ToastContainer />
</>
);
}

const FormContainer = styled.div``;

export default Register;


Login Page
import React, { useState, useEffect } from 'react' import { Link,
useNavigate } from 'react-router-dom'; import styled from
"styled-components"; import Logo from '../assets/logo.svg'

import { ToastContainer, toast } from "react-toastify"; import


'react-toastify/dist/ReactToastify.css' import axios from
"axios";
import { loginRoute } from '../utils/APIRoutes';

function Login() {
const navigate=useNavigate();
const [values, setValues] =
useState({ username: "",
password: "",
});
const toastOptions = {
position: "top-right",
autoClose: 8000,
pauseOnHover: true,
draggable: true,
theme: "dark"
}
useEffect(()=>{
if(localStorage.getItem("chat-app-user")){
navigate("/");
}
},[navigate]);

const handleSubmit =async (event) =>


{ event.preventDefault();
if( handleValidation()){
const { password, username } = values; const
{data}=await axios.post(loginRoute,{
username,
password
});
if(data.status===false){
toast.error(data.msg,toastOptions)
}
console.log("Iam in Register");
if(data.status===true){
localStorage.setItem("chat-app-
user",JSON.stringify(data.user));
navigate("/");
}
}

};
const handleValidation = () => {
const { password, username } = values;
if (password==="") {
toast.error("Email and password is required",
toastOptions);
return false;
} else if (username.length === "") {
toast.error("Email and password is required",
toastOptions);
return false;
}
return true;
}
const handleChange = (event) => {
setValues({ ...values, [event.target.name]:
event.target.value });
};
return (
<>
<FormContainer className='form'>
<form className='mainForm' onSubmit={(event) =>
{ handleSubmit(event) }}>
<div className="brand">
<img className='regImg' src={Logo} alt="Logo" />
<h1>Secret Chats</h1>
</div>
<input type="text" name="username"
placeholder='UserName' min="3" onChange={(e) =>
handleChange(e)} />
<input type="password" name="password"
placeholder='Password' onChange={(e) =>
handleChange(e)} />
<button type='submit'>Login</button>
<span>already have an account ?
<Link to='/register'>Register</Link></span>
</form>
</FormContainer>
<ToastContainer />
</>
)}
const FormContainer = styled.div``;

export default Login;


Set Avatar
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { ToastContainer, toast } from "react-toastify";
import loader from "../assets/loader.gif"; import
"react-toastify/dist/ReactToastify.css"; import axios
from "axios"; import { Buffer } from "buffer";

import { setAvatarRoute } from "../utils/APIRoutes";

function SetAvatar() {
const api = "https://api.multiavatar.com/45678945"; const
navigate = useNavigate();
const [avatars, setAvatar] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [selectedAvatar, setSelectedAvatar] = useState(undefined); const
toastOptions = {
position: "bottom-right",
autoClose: 8000,
pauseOnHover: true,
draggable: true,
theme: "dark",
};
useEffect(() => {
xyz2();
async function xyz2() {
if (!localStorage.getItem("chat-app-user"))
{ navigate("/login");
}
}
}, [navigate]);
const setProfilePicture = async () => {
if (selectedAvatar === undefined) {
toast.error("please select an avatar", toastOptions);
} else {
const user = await JSON.parse(localStorage.getItem("chat-app-user")); const
{ data } = await axios.post(`${setAvatarRoute}/${user._id}`, {
image: avatars[selectedAvatar],
});

if (data.isSet) {
user.isAvatarImageSet = true;
user.avatarImage = data.image;
localStorage.setItem("chat-app-user", JSON.stringify(user));
navigate("/");
} else {
toast.error("Error setting avatar.Please try again", toastOptions);
}
}
};
useEffect(() => {
xyz();
async function xyz() {
const data = [];
for (let i = 0; i < 4; i++) {
const image = await axios.get(
`${api}/${Math.round(Math.random() * 1000)}`
);
const buffer = new Buffer(image.data);
data.push(buffer.toString("base64"));
}
setAvatar(data);
setIsLoading(false);
}
}, []);

return (
<>
{isLoading && <img src={loader} alt="loader" className="loader" />} <div
className="container">
<div className="title-container">
<h1>Pick an avatar as your Profile Picture</h1> </div>

<div className="avatars">
{avatars.map((avatar, index) => {
return (
<div key={index} className={`avatar ${ selectedAvatar === index ?
"selected" : "" }`}>
<img src={`data:image/svg+xml;base64,${avatar}`} alt="avatar"
onClick={() => setSelectedAvatar(index)} />
</div>
); })}
</div>
<button className="submit-btn" onClick={setProfilePicture}> Set
As Profile Picture
</button>

<ToastContainer />
</div>
</>
);
}
export default SetAvatar;
Contacts
import React, { useEffect, useState } from "react"; import
Logo from "../assets/logo.svg";
function Contacts({ contacts, currentUser, changeChat }) {
const [currentUserName, setCurrentUserName] = useState(undefined); const
[currentUserImage, setCurrentUserImage] = useState(undefined); const
[currentSelected, setCurrentSelected] = useState(undefined); useEffect(() => {

console.log(contacts);
if (currentUser) {
setCurrentUserImage(currentUser.avatarImage);
setCurrentUserName(currentUser.username);
}
}, [contacts, currentUser]);
const changeCurrentChat = (index, contact) =>
{ setCurrentSelected(index); (contact); };
return (
<>
{currentUserImage && currentUserName && (
<div className="mainContact">
<div className="brand">
<img src={Logo} alt="logo" />h3 className="hide">Secret Chats</h3>
</div>
<div className="contacts">
{contacts.map((contact, index) => {
return (
<div className={`contact ${ index === currentSelected ? "selected2": " " }`}
key={index} onClick={() => changeCurrentChat(index, contact)} >
<div className="avatar2">
<img src={`data:image/svg+xml;base64,${contact.avatarImage}`} alt="avatar2"/> </div>

<div className="username hide"> <h3>{contact.username}</h3> </div>


</div>); })}
</div>
<div className="current-user">
<div className="avatar2">
<img src={`data:image/svg+xml;base64,${currentUserImage}`} alt="avatar2" /> </div>

<div className="usernamex hide"> <h2>{currentUserName}</h2> </div>


</div> <div>
)}
</>
);
}
export default Contacts;
Chat Container
import React, { useEffect, useRef, useState } from "react"; import
Logout from "./Logout";
import ChatInput from "./ChatInput";
import axios from "axios";
import { sendMessageRoute, getAllMessageRoute } from
"../utils/APIRoutes";
import { v4 as uuidv4 } from "uuid";

function ChatContainer({ currrentChat, currentUser, socket }) { const


[messeges, setMessegse] = useState([]);
const [arrivalMessage, setArrivalMessage] = useState(null);
const scrollRef = useRef();
useEffect(() => {
abc();
async function abc() {
if (currrentChat) {
const data = await JSON.parse(localStorage.getItem("chat-app-
user"));
const response = await axios.post(getAllMessageRoute,
{ from: data._id,
to: currrentChat._id,
});
setMessegse(response.data);
}
}
}, [currrentChat]);
const handleSendMsg = async (msg) =>
{ await axios.post(sendMessageRoute, {
from: currentUser._id,
to: currrentChat._id,
message: msg,
});
socket.current.emit("send-msg", {
to: currrentChat._id,
from: currentUser._id,
message: msg,
});
const msgs = [...messeges];
msgs.push({ fromSelf: true, message: msg });
setMessegse(msgs);
};
useEffect(() => {
if (socket.current) {
socket.current.on("msg-receive", (msg) => {
setArrivalMessage({ fromSelf: false, message: msg }); });

}
}, [socket]);
useEffect(() => {
arrivalMessage && setMessegse((prev) => [...prev,
arrivalMessage]);
}, [arrivalMessage]);
useEffect(() => {
scrollRef.current?.scrollIntoView({ behaviour: "smooth" });
}, [messeges]);
return (
<>
{currrentChat && (
<div className="ChatContainer">
<div className="chat-header">
<div className="user-details">
<div className="avatar"> <img
src={`data:image/svg+xml;base64,${currrentChat.avatarImage}`}
alt="avatar2" /> </div>
<div className="username">
<h3>{currrentChat.username}</h3>
</div> </div>
<Logout />
</div>
<div className="chat-messages">
{messeges.map((msg) => {
return (
<div ref={scrollRef} key={uuidv4}>
<div
className={`message${msg.fromSelf ? "sended" : "received"}`}>
<div className="content">
<p>{msg.message}</p>
</div>
</div>
</div>
);
})}
</div>
<ChatInput handleSendMsg={handleSendMsg} />
</div>
)}
</>
);
}

export default ChatContainer;


Logout

import React from 'react'


import {BiPowerOff} from "react-icons/bi" import
{ useNavigate } from 'react-router-dom'

function Logout() {
const navigate=useNavigate();
/ const [login,setLogin]=useState(true);
const
handleClick=async()=>{ localStorage.cle
ar(); //setLogin(false);

navigate("/login");
}
return (
<button className='logout'
onClick={handleClick}><BiPowerOff/></button>
)
}

export default Logout


API Routes
export const host = "http://localhost:5000";
export const registerRoute = `${host}/api/auth/register`;
export const loginRoute = `${host}/api/auth/login`;
export const setAvatarRoute =` ${host}/api/auth/setAvatar`;
export const allUsersRoute=`${host}/api/auth/allusers`;
export const sendMessageRoute=`${host}/api/messages/addmsg`;
export const getAllMessageRoute=`${host}/api/messages/getmsg`;

Configure

/ Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
/ import { getAnalytics } from "firebase/analytics"; import
{getAuth, GoogleAuthProvider} from "firebase/auth"; const
firebaseConfig = {
apiKey: "AIzaSyCz5xUTHQ25yufF8pY1sysFRZRWMOy_fAo",
authDomain: "chat-dtul.firebaseapp.com",
projectId: "chat-dtul",
storageBucket: "chat-dtul.appspot.com",
messagingSenderId: "3940487854629",
appId: "1:3940845615729:web:0c24af9kjhd0b9560fef0",
measurementId: "G-R5EHJH4KFR8"
};

/ Initialize Firebase
const app = initializeApp(firebaseConfig); const
auth = getAuth(app);
const provider = new GoogleAuthProvider();
/ const analytics = getAnalytics(app);
export {auth, provider};
BACKEND
Index.html
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const userRoutes = require("./routes/userRoutes");
const messageRoute = require("./routes/messagesRoute");
const socket = require("socket.io");

const app = express();


require("dotenv").config();

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

app.use("/api/auth", userRoutes);
app.use("/api/messages", messageRoute);

mongoose.connect(process.env.MONGO_URL)
.then(() => { console.log("DB
connected"); }).catch((err) => { console.log(err);
});

const server = app.listen(process.env.PORT, () =>


{ console.log(`Server is connected on PORT $
{process.env.PORT}`); });

const io = socket(server, {
cors: { origin: "http://localhost:3000", credentials:
true, }, });
global.onlineUsers = new Map();

io.on("connection", (socket) => {


global.chatSocket = socket;
socket.on("add-user", (userId) => {
onlineUsers.set(userId, socket.id);
});
socket.on("send-msg", (data) => {
const sendUserSocket = onlineUsers.get(data.to);
if (sendUserSocket) {
socket.to(sendUserSocket).emit("msg-receive", data.message);
}
});});
Model
UserSchema:-

const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({


username: {
type: String,
required: true,
min: 3,
max: 20,
unique: true,
},
email: {
type: String,
required: true,
unique: true,
max: 50,
},
password: {
type: String,
required: true,
min: 6,
},
isAvatarImageSet: {
type: Boolean,
default: false,
},
avatarImage: {
type: String,
default: "",
},
});
module.exports = mongoose.model("User", userSchema);

}, { timestamps: true });

module, exports=mongoose, model("Post", PostSchema)


MessageSchema:

const mongoose = require("mongoose");

const schema = new mongoose.Schema(


{
message: {
text: {
type: String,
require: true,
},
},
users: Array,
sender: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
requred: true,
},
},
{
timestamps: true,
}
);

module.exports = mongoose.model("Messeges", schema);


Controllers
UserController

const User = require("../model/userModel");


const bcrypt = require("bcrypt");

module.exports.register = async (req, res, next) => { try {

const { username, email, password } = req.body;


/ console.log(username, email, password, "Data From user");
const userNameCheck = await User.findOne({ username });

if (userNameCheck) {
return res.json({ msg: "UserName Already Taken", status: false });
}

const emailCheck = await User.findOne({ email });

if (emailCheck) {
return res.json({ msg: "Email Already used", status: false });
}
const hashedPassword = await bcrypt.hash(password, 10);
const user = await User.create({
email,
username,
password: hashedPassword,
});
delete user.password;
return res.json({ status: true, user });
} catch (err)
{ next(err);
}
};
module.exports.login = async (req, res, next) => { try {

const { username, password } = req.body;


/ console.log(username,email,password,"Data From user");
/ await UserModel.find(query).maxTimeMS(30000);
const user = await User.findOne({ username });

if (!user) {
return res.json({ msg: "Incorrect username or password", status: false });
}
const isPasswordValid = await bcrypt.compare(password, user.password); if (!
isPasswordValid) {
return res.json({ msg: "Incorrect username or password", status: false });
}
delete user.password;
return res.json({ status: true, user });
} catch (err)
{ next(err);
}
};
module.exports.setAvatar = async (req, res, next) => { try {

const userId = req.params.id;


const avatarImage = req.body.image;
const userData = await User.findByIdAndUpdate(userId,
{ isAvatarImageSet: true,
avatarImage,
});
return res.json({
isSet: userData.isAvatarImageSet,
image: userData.avatarImage,
});
} catch (err)
{ next(err);
}
};
module.exports.getAllUsers = async (req, res, next) => { try {

const users = await User.find({ _id: { $ne: req.params.id } }).select([ "email",

"username",
"avatarImage",
"_id",
]);
return res.json(users);
} catch (err)
{ next(err);
}
};
Message Controller

const messageModel = require("../model/messageModel");

module.exports.addMessage = async (req, res, next) => { try {

const { from, to, message } = req.body;


const data = await messageModel.create({
message: { text: message },
users: [from, to],
sender: from,
});
if (data) return res.json({ msg: "Messege sended successfully" });
return res.json({ msg: "failed to add message in DB" });
} catch (err)
{ next(err);
}
};

module.exports.getAllMessage = async (req, res, next) => { try {

const { from, to } = req.body;


const messages = await messageModel
.find({
users: {
$all: [from, to],
},
})
.sort({ updatedAt: 1 });
const projectedMessages = messages.map((msg) =>
{ return {
fromSelf: msg.sender.toString() === from,
message: msg.message.text,
};
});
res.json(projectedMessages);
} catch (er) {
next(er);
}
};
Routes

UserRoutes
const router=require('express').Router();
const { register, login,setAvatar,getAllUsers } =
require('../controllers/usersControllers');

router.post('/register',register);
router.post('/login',login);
router.post('/setAvatar/:id',setAvatar);
router.get('/allUsers/:id',getAllUsers);

module.exports=router;

MessageRoutes

const {addMessage,
getAllMessage}=require("../controllers/messagesController");

const router=require("express").Router();

router.post("/addmsg",addMessage);
router.post('/getmsg',getAllMessage);

module.exports=router;
Package. Json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"firebase": "^10.7.0",
"mongoose": "^8.0.0",
"socket.io": "^4.7.2"
}
}
Register Page

Login Page
Mail Validation

Password Validation
SetAvatar Page

Main Page
User Page

Chat Page

You might also like